PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
booking / includes / page-add-appointment / add_appointment__page.php

add_appointment__page.php in Booking Calendar 11.8.4, at includes/page-add-appointment/add_appointment__page.php

511 lines 20.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Dedicated Add Appointment administrator page.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Check whether the Add Appointment tab is the current Booking Calendar page.
14 *
15 * @return bool True on the Add Appointment tab.
16 */
17 function wpbc_add_appointment_page_is_active() {
18 if ( ! is_admin() ) {
19 return false;
20 }
21
22 $page = isset( $_GET['page'] ) && ! is_array( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
23 $tab = isset( $_GET['tab'] ) && ! is_array( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
24
25 return 'wpbc' === $page && 'add-appointment' === $tab;
26 }
27
28 /**
29 * Return the canonical administrator URL for the Add Appointment workflow.
30 *
31 * @return string Absolute WordPress administrator URL.
32 */
33 function wpbc_add_appointment_page_get_url() {
34 return add_query_arg(
35 array(
36 'page' => 'wpbc',
37 'tab' => 'add-appointment',
38 ),
39 admin_url( 'admin.php' )
40 );
41 }
42
43 /**
44 * Read the page-level Appointment options from the current administrator URL.
45 *
46 * These values configure only the dedicated Add Appointment screen. Service
47 * duration, buffers, price, and Booking Form remain owned by the Service.
48 *
49 * @return array{calendar_months:int,auto_select_provider:bool,allow_past:bool} Normalized page options.
50 */
51 function wpbc_add_appointment_page_get_settings() {
52 $months = isset( $_GET['appointment_months'] ) && ! is_array( $_GET['appointment_months'] )
53 ? absint( wp_unslash( $_GET['appointment_months'] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
54 : 1;
55 $months = min( 12, max( 1, $months ) );
56
57 return array(
58 'calendar_months' => $months,
59 'auto_select_provider' => isset( $_GET['appointment_auto_select_provider'] ) && ! is_array( $_GET['appointment_auto_select_provider'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
60 'allow_past' => isset( $_GET['allow_past'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
61 );
62 }
63
64 /**
65 * Print the legacy booking context required by calendar and submit scripts.
66 *
67 * Reusing the Add Booking minimum-date calculation keeps past-date behavior
68 * identical in both administrator workflows.
69 *
70 * @param bool $allow_past Whether past dates may be selected and submitted.
71 *
72 * @return void
73 */
74 function wpbc_add_appointment_page_print_booking_context( $allow_past ) {
75 $allow_past_date_arr = WPBC_Add_Booking_Component::get_allow_past_min_date_arr(
76 array(
77 'allow_past' => $allow_past ? 1 : 0,
78 'booking_hash' => '',
79 )
80 );
81 ?>
82 <script type="text/javascript">
83 if ( 'undefined' !== typeof _wpbc ) {
84 _wpbc.set_other_param( 'this_page_booking_hash', '' );
85 _wpbc.set_other_param( 'this_page_allow_past', <?php echo wp_json_encode( $allow_past ? 1 : 0 ); ?> );
86 _wpbc.set_other_param( 'this_page_allow_past_arr', <?php echo wp_json_encode( $allow_past_date_arr ); ?> );
87 }
88 </script>
89 <?php
90 }
91
92 /**
93 * Enqueue the existing Appointment controller and the page-only admin styles.
94 *
95 * @param string $where_to_load Booking Calendar asset context.
96 *
97 * @return void
98 */
99 function wpbc_add_appointment_page_enqueue_css( $where_to_load ) {
100 if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! wpbc_add_appointment_page_is_active() ) {
101 return;
102 }
103
104 wp_enqueue_style(
105 'wpbc-add-appointment-page',
106 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/add_appointment_page.css',
107 array( 'wpbc-all-admin', 'wpbc-booking-appointment' ),
108 WP_BK_VERSION_NUM
109 );
110 }
111 add_action( 'wpbc_enqueue_css_files', 'wpbc_add_appointment_page_enqueue_css', 73 );
112
113 /**
114 * Enqueue the existing AJAX Appointment controller and page inspector client.
115 *
116 * @param string $where_to_load Booking Calendar asset context.
117 *
118 * @return void
119 */
120 function wpbc_add_appointment_page_enqueue_js( $where_to_load ) {
121 if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! wpbc_add_appointment_page_is_active() ) {
122 return;
123 }
124
125 wp_enqueue_script(
126 'wpbc-add-appointment-page',
127 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/add_appointment_page.js',
128 array( 'jquery', 'wpbc-booking-appointment', 'wpbc_all' ),
129 WP_BK_VERSION_NUM,
130 array( 'in_footer' => WPBC_JS_IN_FOOTER )
131 );
132 $settings = wpbc_add_appointment_page_get_settings();
133 $allow_past_date_arr = WPBC_Add_Booking_Component::get_allow_past_min_date_arr(
134 array(
135 'allow_past' => $settings['allow_past'] ? 1 : 0,
136 'booking_hash' => '',
137 )
138 );
139
140 wp_localize_script(
141 'wpbc-add-appointment-page',
142 'wpbc_add_appointment_page_config',
143 array(
144 'emptyLabel' => __( 'Not selected', 'booking' ),
145 'enabledLabel' => __( 'Enabled', 'booking' ),
146 'disabledLabel' => __( 'Disabled', 'booking' ),
147 'minutesLabel' => __( 'min', 'booking' ),
148 'allowPast' => $settings['allow_past'] ? 1 : 0,
149 'allowPastDateArr' => $allow_past_date_arr,
150 'adminBookingNonce' => WPBC_Add_Booking_Component::get_admin_booking_nonce(),
151 )
152 );
153 }
154 add_action( 'wpbc_enqueue_js_files', 'wpbc_add_appointment_page_enqueue_js', 73 );
155
156 /**
157 * Add Appointment page integrated into the shared Booking Calendar page shell.
158 */
159 class WPBC_Page_Add_Appointment extends WPBC_Page_Structure {
160
161 /**
162 * Place the page beside Booking Listing, Timeline, and Add Booking.
163 *
164 * @return string Parent page slug.
165 */
166 public function in_page() {
167 if ( ! WPBC_Add_Booking_Component::current_user_can_add_booking() ) {
168 return (string) wp_rand( 100000, 1000000 );
169 }
170
171 return 'wpbc';
172 }
173
174 /**
175 * Register the released Appointment tab and shared inspector layout.
176 *
177 * @return array<string,array<string,mixed>> Tab definition.
178 */
179 public function tabs() {
180 return array(
181 'add-appointment' => array(
182 'is_show_top_path' => true,
183 'is_show_top_navigation' => true,
184 'left_navigation__default_view_mode' => '', // FixIn:11.7.1.1: 'min',
185 'right_vertical_sidebar__is_show' => true,
186 'right_vertical_sidebar__default_view_mode' => '',
187 'right_vertical_sidebar_compact__is_show' => true,
188 'page_title' => __( 'Add New Appointment', 'booking' ),
189 'page_description' => __( 'Select a Service and Provider, then create the Appointment with the existing Booking Calendar form.', 'booking' ),
190 'title' => __( 'Add Appointment', 'booking' ),
191 'hint' => __( 'Add Appointment', 'booking' ),
192 'font_icon' => 'wpbc-bi-plus-circle-dotted wpbc_icn_rotate_180',
193 'default' => false,
194 'disabled' => false,
195 'hided' => false,
196 'subtabs' => array(),
197 ),
198 );
199 }
200
201 /**
202 * Render compact controls for the Appointment inspector.
203 *
204 * @return void
205 */
206 public function right_sidebar_compact_content() {
207 WPBC_UI_Sidebar_Panels::render_rightbar_tabs(
208 array(
209 array(
210 'id' => 'wpbc_tab_add_appointment_overview',
211 'panel_id' => 'wpbc_add_appointment__inspector_overview',
212 'title' => __( 'Settings', 'booking' ),
213 'icon' => 'wpbc_icn_tune',
214 'selected' => true,
215 ),
216 array(
217 'id' => 'wpbc_tab_add_appointment_help',
218 'panel_id' => 'wpbc_add_appointment__inspector_help',
219 'title' => __( 'Help', 'booking' ),
220 'icon' => 'wpbc-bi-info-circle',
221 ),
222 ),
223 array(
224 'aria_label' => __( 'Add Appointment Panels', 'booking' ),
225 'context' => 'add_appointment',
226 'class' => 'wpbc_add_appointment__rightbar_tabs',
227 )
228 );
229 }
230
231 /**
232 * Render the standard Builder-style Appointment inspector panels.
233 *
234 * @return void
235 */
236 public function right_sidebar_content() {
237 ?>
238 <div class="wpbc_bfb__panel--library wpbc_rightbar_palette wpbc_add_appointment__rightbar">
239 <?php
240 WPBC_UI_Sidebar_Panels::render_panel(
241 array(
242 'id' => 'wpbc_add_appointment__inspector_overview',
243 'labelledby' => 'wpbc_tab_add_appointment_overview',
244 'class' => 'wpbc_add_appointment__inspector_overview',
245 ),
246 array( $this, 'render_overview_panel' )
247 );
248 WPBC_UI_Sidebar_Panels::render_panel(
249 array(
250 'id' => 'wpbc_add_appointment__inspector_help',
251 'labelledby' => 'wpbc_tab_add_appointment_help',
252 'class' => 'wpbc_add_appointment__inspector_help',
253 'hidden' => true,
254 ),
255 array( $this, 'render_help_panel' )
256 );
257 ?>
258 </div>
259 <?php
260 }
261
262 /**
263 * Render the contextual workflow panel.
264 *
265 * @return void
266 */
267 public function render_overview_panel() {
268 $settings = wpbc_add_appointment_page_get_settings();
269 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Appointment Settings', 'booking' ), __( 'Page-level options for this administrator booking.', 'booking' ) );
270 ?>
271 <div class="wpbc_bfb__inspector__body wpbc_add_appointment__inspector_body">
272 <?php
273 WPBC_UI_Sidebar_Panels::render_collapsible_group(
274 array(
275 'id' => 'wpbc_add_appointment_summary_group',
276 'group' => 'add-appointment-summary',
277 'title' => __( 'Appointment Summary', 'booking' ),
278 'open' => true,
279 ),
280 array( $this, 'render_summary_content' )
281 );
282 WPBC_UI_Sidebar_Panels::render_collapsible_group(
283 array(
284 'id' => 'wpbc_add_appointment_booking_tools_group',
285 'group' => 'add-appointment-booking-tools',
286 'title' => __( 'Booking tools', 'booking' ),
287 'open' => false,
288 ),
289 function () {
290 $send_emails = get_bk_option( 'booking_send_emails_off_addbooking' ) !== 'On';
291 wpbc_render_admin_cost_correction_control(
292 array(
293 'input_id' => 'wpbc_add_appointment_cost_correction',
294 'wrapper_class' => 'wpbc_add_appointment__setting_row wpbc_add_appointment__cost_correction',
295 'label_class' => 'wpbc_add_appointment__cost_correction_label',
296 'control_class' => 'wpbc_add_appointment__cost_correction_control',
297 'help_class' => 'wpbc_add_appointment__tool_help',
298 'help' => __( 'Leave the number empty to use the calculated Appointment cost. Enter an exact total to replace the final cost for this Appointment.', 'booking' ),
299 )
300 );
301 ?>
302 <div class="wpbc_add_appointment__setting_row wpbc_add_appointment__setting_row--toggle">
303 <?php
304 wpbc_flex_toggle(
305 array(
306 'id' => 'is_send_email_for_pending',
307 'name' => 'is_send_email_for_pending',
308 'label' => array( 'title' => __( 'Emails sending', 'booking' ) ),
309 'value' => 'On',
310 'selected' => $send_emails,
311 'legend' => __( 'Send email notifications for this Appointment', 'booking' ),
312 )
313 );
314 ?>
315 <p><?php esc_html_e( 'Send the normal Booking Calendar notifications when this Appointment is created.', 'booking' ); ?></p>
316 </div>
317 <div class="wpbc_add_appointment__panel_actions wpbc_add_appointment__tool_actions">
318 <button type="button" class="button wpbc_add_appointment__autofill" data-wpbc-add-appointment-autofill disabled><?php esc_html_e( 'Auto-fill form', 'booking' ); ?></button>
319 <button type="button" class="button wpbc_add_appointment__start_over" data-wpbc-add-appointment-start-over hidden><?php esc_html_e( 'Start over', 'booking' ); ?></button>
320 </div>
321 <p class="wpbc_add_appointment__tool_help"><?php esc_html_e( 'Auto-fill becomes available after the Booking Form loads. It fills sample contact details but never submits the Appointment.', 'booking' ); ?></p>
322 <?php
323 }
324 );
325 WPBC_UI_Sidebar_Panels::render_collapsible_group(
326 array(
327 'id' => 'wpbc_add_appointment_booking_options_group',
328 'group' => 'add-appointment-booking-options',
329 'title' => __( 'Booking options', 'booking' ),
330 'open' => false,
331 ),
332 function () use ( $settings ) {
333 ?>
334 <form class="wpbc_add_appointment__settings_form" method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
335 <input type="hidden" name="page" value="wpbc">
336 <input type="hidden" name="tab" value="add-appointment">
337 <div class="wpbc_add_appointment__setting_row">
338 <label for="wpbc_add_appointment__months"><strong><?php esc_html_e( 'Calendar months', 'booking' ); ?></strong></label>
339 <select id="wpbc_add_appointment__months" name="appointment_months">
340 <?php foreach ( array( 1, 2, 3, 4, 6, 12 ) as $months ) : ?>
341 <option value="<?php echo absint( $months ); ?>" <?php selected( $settings['calendar_months'], $months ); ?>><?php echo absint( $months ); ?></option>
342 <?php endforeach; ?>
343 </select>
344 <p><?php esc_html_e( 'Number of months shown in the Provider calendar.', 'booking' ); ?></p>
345 </div>
346 <div class="wpbc_add_appointment__setting_row wpbc_add_appointment__setting_row--toggle">
347 <?php
348 wpbc_flex_toggle(
349 array(
350 'id' => 'wpbc_add_appointment__auto_provider',
351 'name' => 'appointment_auto_select_provider',
352 'label' => array( 'title' => __( 'Auto-select the only Provider', 'booking' ) ),
353 'value' => '1',
354 'selected' => $settings['auto_select_provider'],
355 'legend' => __( 'Auto-select the only compatible Provider', 'booking' ),
356 )
357 );
358 ?>
359 <p><?php esc_html_e( 'Skip Provider selection when only one compatible Provider exists.', 'booking' ); ?></p>
360 </div>
361 <div class="wpbc_add_appointment__setting_row wpbc_add_appointment__setting_row--toggle">
362 <?php
363 wpbc_flex_toggle(
364 array(
365 'id' => 'wpbc_add_appointment__allow_past',
366 'name' => 'allow_past',
367 'label' => array( 'title' => __( 'Allow booking in the past', 'booking' ) ),
368 'value' => '1',
369 'selected' => $settings['allow_past'],
370 'legend' => __( 'Allow booking in the past', 'booking' ),
371 )
372 );
373 ?>
374 <p><?php esc_html_e( 'Use only for historical or manually entered Appointments.', 'booking' ); ?></p>
375 </div>
376 <button type="submit" class="button button-primary wpbc_add_appointment__apply_settings"><?php esc_html_e( 'Apply settings', 'booking' ); ?></button>
377 <p class="wpbc_add_appointment__settings_notice"><?php esc_html_e( 'Applying settings restarts the current selection.', 'booking' ); ?></p>
378 </form>
379 <?php
380 }
381 );
382 WPBC_UI_Sidebar_Panels::render_collapsible_group(
383 array(
384 'id' => 'wpbc_add_appointment_manage_setup_group',
385 'group' => 'add-appointment-manage-setup',
386 'title' => __( 'Manage setup', 'booking' ),
387 'open' => false,
388 ),
389 function () {
390 ?>
391 <p><?php
392 if ( wpbc_appointment_services_is_pricing_available() ) {
393 esc_html_e( 'Services define duration, buffers, price, and Booking Form. Providers retain their existing calendars and availability.', 'booking' );
394 } else {
395 esc_html_e( 'Services define duration, buffers, and Booking Form. Providers retain their existing calendars and availability.', 'booking' );
396 }
397 ?></p>
398 <div class="wpbc_add_appointment__panel_actions">
399 <a class="button" href="<?php echo esc_url( admin_url( 'admin.php?page=wpbc-services' ) ); ?>"><?php esc_html_e( 'Manage Services', 'booking' ); ?></a>
400 <a class="button" href="<?php echo esc_url( admin_url( 'admin.php?page=wpbc-resources' ) ); ?>"><?php esc_html_e( 'Manage Providers', 'booking' ); ?></a>
401 </div>
402 <?php
403 }
404 );
405 do_action( 'wpbc_admin_add_appointment_overview_panel' );
406 ?>
407 </div>
408 <?php
409 }
410
411 /**
412 * Render a live, read-only summary of the current Appointment stage.
413 *
414 * @return void
415 */
416 public function render_summary_content() {
417 ?>
418 <dl class="wpbc_add_appointment__summary" aria-live="polite">
419 <div class="wpbc_add_appointment__summary_status"><dt><?php esc_html_e( 'Current step', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="step"><?php esc_html_e( 'Service', 'booking' ); ?></dd></div>
420 <div><dt><?php esc_html_e( 'Service', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="service">&mdash;</dd></div>
421 <div><dt><?php esc_html_e( 'Provider', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="provider">&mdash;</dd></div>
422 <div><dt><?php esc_html_e( 'Duration', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="duration">&mdash;</dd></div>
423 <div><dt><?php esc_html_e( 'Buffers (before / after)', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="buffers">&mdash;</dd></div>
424 <?php if ( wpbc_appointment_services_is_pricing_available() ) : ?>
425 <div><dt><?php esc_html_e( 'Service price', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="price">&mdash;</dd></div>
426 <?php endif; ?>
427 <div><dt><?php esc_html_e( 'Date', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="date">&mdash;</dd></div>
428 <div><dt><?php esc_html_e( 'Start time', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="time">&mdash;</dd></div>
429 <div><dt><?php esc_html_e( 'Customer', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="customer">&mdash;</dd></div>
430 <div><dt><?php esc_html_e( 'Booking Form', 'booking' ); ?></dt><dd data-wpbc-add-appointment-summary="form">&mdash;</dd></div>
431 <div>
432 <dt><?php esc_html_e( 'Email notifications', 'booking' ); ?></dt>
433 <dd>
434 <a href="#wpbc_add_appointment_booking_tools_group"
435 class="wpbc_add_appointment__summary_link"
436 data-wpbc-add-appointment-open-group="add-appointment-booking-tools"
437 data-wpbc-add-appointment-focus="#is_send_email_for_pending"
438 data-wpbc-add-appointment-summary="emails"
439 aria-label="<?php esc_attr_e( 'Change email notification setting', 'booking' ); ?>">&mdash;</a>
440 </dd>
441 </div>
442 </dl>
443 <?php do_action( 'wpbc_admin_add_appointment_summary_panel' ); ?>
444 <?php
445 }
446
447 /**
448 * Render contextual help without duplicating Booking Calendar settings.
449 *
450 * @return void
451 */
452 public function render_help_panel() {
453 WPBC_UI_Sidebar_Panels::render_inspector_header( __( 'Appointment Help', 'booking' ), __( 'This page creates a normal Booking with an attached Service snapshot.', 'booking' ) );
454 ?>
455 <div class="wpbc_bfb__inspector__body wpbc_bfb__inspector__body--content wpbc_add_appointment__help_body">
456 <div class="wpbc_add_appointment__hint"><span class="wpbc_icn_info_outline" aria-hidden="true"></span><p><?php esc_html_e( 'Availability belongs to the selected Provider booking resource. Service duration and buffers are validated before submission.', 'booking' ); ?></p></div>
457 <div class="wpbc_add_appointment__help_section">
458 <h4><?php esc_html_e( 'Appointment Flow', 'booking' ); ?></h4>
459 <ol class="wpbc_add_appointment__steps">
460 <li><span>1</span><?php esc_html_e( 'Choose a Service', 'booking' ); ?></li>
461 <li><span>2</span><?php esc_html_e( 'Choose a Provider', 'booking' ); ?></li>
462 <li><span>3</span><?php esc_html_e( 'Select date, time, and details', 'booking' ); ?></li>
463 </ol>
464 </div>
465 <div class="wpbc_add_appointment__help_section">
466 <h4><?php esc_html_e( 'When to use this page', 'booking' ); ?></h4>
467 <p><?php esc_html_e( 'Use Add Appointment for the guided Service-first workflow. Use Add Booking for unrestricted resource-first administration.', 'booking' ); ?></p>
468 </div>
469 <a class="button wpbc_add_appointment__help_action" href="<?php echo esc_url( wpbc_get_new_booking_url() ); ?>"><?php esc_html_e( 'Open Add Booking', 'booking' ); ?></a>
470 <?php do_action( 'wpbc_admin_add_appointment_help_panel' ); ?>
471 </div>
472 <?php
473 }
474
475 /**
476 * Render the existing AJAX Appointment component inside the admin canvas.
477 *
478 * @return void|false False when the current user cannot add bookings.
479 */
480 public function content() {
481 do_action( 'wpbc_hook_add_booking_page_header', 'add_appointment' );
482
483 if ( ! wpbc_is_mu_user_can_be_here( 'activated_user' ) || ! WPBC_Add_Booking_Component::current_user_can_add_booking() ) {
484 return false;
485 }
486
487 if ( function_exists( 'wpbc_js_for_bookings_page' ) ) {
488 wpbc_js_for_bookings_page();
489 }
490
491 $settings = wpbc_add_appointment_page_get_settings();
492 $config = array(
493 'cal_count' => $settings['calendar_months'],
494 'auto_select_provider' => $settings['auto_select_provider'],
495 'allow_past' => $settings['allow_past'],
496 );
497 $config = (array) apply_filters( 'wpbc_admin_add_appointment_config', $config, $settings );
498 wpbc_add_appointment_page_print_booking_context( $settings['allow_past'] );
499 ?>
500 <div class="wpbc_add_appointment_page wpdevelop" data-wpbc-add-appointment-page="1">
501 <div class="wpbc_add_appointment__canvas">
502 <?php echo wpbc_booking_appointment_shortcode( $config ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
503 </div>
504 </div>
505 <?php
506
507 do_action( 'wpbc_hook_add_booking_page_footer', 'add_appointment' );
508 }
509 }
510 add_action( 'wpbc_menu_created', array( new WPBC_Page_Add_Appointment(), '__construct' ) );
511