$configuration Registered Service catalog configuration. * * @return void */ function wpbc_appointment_services_migrate_catalog_preferences( $configuration ) { $user_id = get_current_user_id(); $namespace = WPBC_UI_Catalog_Preferences::get_namespace( 'appointment_services_catalog' ); if ( ! $user_id || '' === $namespace || false !== get_user_option( $namespace, $user_id ) ) { return; } $legacy_preferences = get_user_option( 'wpbc_admin_listing_preferences', $user_id ); $legacy_preferences = is_array( $legacy_preferences ) && isset( $legacy_preferences['appointment_services_catalog'] ) && is_array( $legacy_preferences['appointment_services_catalog'] ) ? $legacy_preferences['appointment_services_catalog'] : array(); if ( empty( $legacy_preferences ) ) { return; } $request_values = array_intersect_key( $legacy_preferences, array( 'items_per_page' => true, 'sort_by' => true, 'sort_order' => true, 'column_order' => true, ) ); if ( isset( $legacy_preferences['visible_fields'] ) && is_array( $legacy_preferences['visible_fields'] ) ) { $request_values['visible_columns'] = $legacy_preferences['visible_fields']; } $legacy_filters = isset( $legacy_preferences['filters'] ) && is_array( $legacy_preferences['filters'] ) ? $legacy_preferences['filters'] : array(); $service_request = WPBC_Appointment_Services_Catalog_Request::create( array( 'status' => isset( $legacy_filters['status'] ) ? $legacy_filters['status'] : 'all', 'resource_id' => isset( $legacy_filters['resource_id'] ) ? $legacy_filters['resource_id'] : 0, ) ); $request = WPBC_UI_Catalog_Request::create( $configuration, $request_values ); if ( ! is_wp_error( $request ) && ! is_wp_error( $service_request ) ) { WPBC_UI_Catalog_Preferences::save( 'appointment_services_catalog', $request, array( 'status' => $service_request->get( 'status', 'all' ), 'resource_id' => $service_request->get( 'resource_id', 0 ), ), $user_id, 1 ); } } /** * Return validated initial URL overrides for the Services catalog. * * @return array Shared catalog URL overrides. */ function wpbc_appointment_services_get_initial_catalog_overrides() { $parameter_map = array( 'page_number' => 'catalog_page', 'items_per_page' => 'catalog_per_page', 'sort_by' => 'catalog_sort', 'sort_order' => 'catalog_order', 'search' => 'catalog_search', 'visible_columns' => 'catalog_columns', 'column_order' => 'catalog_column_order', 'template_pack' => 'template_pack', ); $url_overrides = array(); foreach ( $parameter_map as $request_key => $parameter_name ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only initial catalog state. if ( ! isset( $_GET[ $parameter_name ] ) ) { continue; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Validated by WPBC_UI_Catalog_Request. $request_value = wp_unslash( $_GET[ $parameter_name ] ); if ( in_array( $request_key, array( 'visible_columns', 'column_order' ), true ) && is_scalar( $request_value ) ) { $request_value = '' === trim( (string) $request_value ) ? array() : explode( ',', (string) $request_value ); } $url_overrides[ $request_key ] = $request_value; } return $url_overrides; } /** * Build the shared Services catalog browser configuration. * * @return array Browser-safe Service and catalog configuration. */ function wpbc_appointment_services_get_catalog_client_config() { $catalog_id = 'appointment_services_catalog'; $domain_configuration = wpbc_appointment_services_get_catalog_config(); $configuration = WPBC_UI_Catalog_Registry::get_instance()->get_configuration( $catalog_id ); if ( empty( $configuration ) ) { return array(); } wpbc_appointment_services_migrate_catalog_preferences( $configuration ); $stored_preferences = WPBC_UI_Catalog_Preferences::load( $catalog_id ); $shared_request = WPBC_UI_Catalog_Request::create( $configuration, array( 'request_id' => 1 ), $stored_preferences, wpbc_appointment_services_get_initial_catalog_overrides(), true ); $service_values = array( 'status' => isset( $stored_preferences['status'] ) ? $stored_preferences['status'] : 'all', 'resource_id' => isset( $stored_preferences['resource_id'] ) ? $stored_preferences['resource_id'] : 0, ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only initial Provider filter. if ( isset( $_GET['provider_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Validated by the Service request object. $service_values['resource_id'] = wp_unslash( $_GET['provider_id'] ); } $service_request = WPBC_Appointment_Services_Catalog_Request::create( $service_values ); $auto_load = ! is_wp_error( $shared_request ) && ! is_wp_error( $service_request ); if ( ! $auto_load ) { $shared_request = WPBC_UI_Catalog_Request::create( $configuration, array( 'request_id' => 1 ) ); if ( is_wp_error( $shared_request ) ) { return array(); } $initial_error = is_wp_error( $service_request ) ? $service_request : new WP_Error( 'wpbc_appointment_services_invalid_request', __( 'The Services request is invalid.', 'booking' ) ); $initial_response = WPBC_UI_Catalog_Response::from_wp_error( $catalog_id, 1, $initial_error ); $service_request = WPBC_Appointment_Services_Catalog_Request::create(); } else { $empty_response = WPBC_UI_Catalog_Response::create_empty( $catalog_id, $shared_request ); $initial_response = is_wp_error( $empty_response ) ? WPBC_UI_Catalog_Response::from_wp_error( $catalog_id, 1, $empty_response ) : $empty_response->to_array(); } $initial_request = $shared_request->to_array(); $initial_request['status'] = $service_request->get( 'status', 'all' ); $initial_request['resource_id'] = $service_request->get( 'resource_id', 0 ); $client_configuration = WPBC_UI_Catalog::get_client_configuration( $catalog_id, 'wpbc_appointment_services_catalog', $initial_request, $initial_response ); $client_configuration['ajax_url'] = admin_url( 'admin-ajax.php' ); $client_configuration['auto_load'] = $auto_load; $client_configuration['nonce'] = wp_create_nonce( $configuration['nonce_name'] ); $default_request = WPBC_UI_Catalog_Request::create( $configuration ); if ( is_wp_error( $default_request ) ) { return array(); } $client_configuration['default_request'] = $default_request->to_array(); $client_configuration['default_request']['status'] = 'all'; $client_configuration['default_request']['resource_id'] = 0; $client_configuration['url_parameters'] = array( 'page_number' => 'catalog_page', 'items_per_page' => 'catalog_per_page', 'sort_by' => 'catalog_sort', 'sort_order' => 'catalog_order', 'search' => 'catalog_search', 'visible_columns' => 'catalog_columns', 'column_order' => 'catalog_column_order', 'template_pack' => 'template_pack', 'resource_id' => 'provider_id', ); $client_configuration['filters'] = $domain_configuration['filters']; $client_configuration['actions'] = $domain_configuration['actions']; return $client_configuration; } /** * Enqueue and configure the AJAX Appointment Services management client. * * @param string $where_to_load Booking Calendar asset context. * * @return void */ function wpbc_appointment_services_enqueue_js( $where_to_load ) { if ( ! in_array( $where_to_load, array( 'admin', 'both' ), true ) || ! wpbc_appointment_services__is_page() ) { return; } WPBC_UI_Catalog::enqueue_scripts(); wpbc_load_js__required_for_media_upload(); $selected_service_id = wpbc_appointment_services_get_initial_service_id(); $default_provider_ids = array(); if ( ! class_exists( 'wpdev_bk_personal' ) ) { $default_provider_id = function_exists( 'wpbc_get_default_resource' ) ? absint( wpbc_get_default_resource() ) : 1; if ( ! $default_provider_id ) { $default_provider_id = 1; } $default_provider_ids[] = $default_provider_id; } wp_enqueue_script( 'wpbc-appointment-services-page', trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/appointment_services_page.js', array( 'jquery', 'wpbc_all', 'wpbc-ui-catalog', 'wpbc-ui-catalog-actions', ), WP_BK_VERSION_NUM, array( 'in_footer' => WPBC_JS_IN_FOOTER ) ); wp_localize_script( 'wpbc-appointment-services-page', 'wpbc_appointment_services_config', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'wpbc_appointment_services_ajax_nonce' ), 'actions' => array( 'list' => 'WPBC_AJX_APPOINTMENT_SERVICES_LIST', 'load' => 'WPBC_AJX_APPOINTMENT_SERVICE_LOAD', 'save' => 'WPBC_AJX_APPOINTMENT_SERVICE_SAVE', 'duplicate' => 'WPBC_AJX_APPOINTMENT_SERVICE_DUPLICATE', 'archive' => 'WPBC_AJX_APPOINTMENT_SERVICE_ARCHIVE', 'inline_schema' => 'WPBC_AJX_APPOINTMENT_SERVICES_INLINE_SCHEMA', 'bulk_contract' => 'WPBC_AJX_APPOINTMENT_SERVICES_BULK_CONTRACT', 'preview' => 'WPBC_AJX_APPOINTMENT_SERVICES_CATALOG_PREVIEW', 'apply' => 'WPBC_AJX_APPOINTMENT_SERVICES_CATALOG_APPLY', 'delete_preview' => 'WPBC_AJX_APPOINTMENT_SERVICES_DELETE_PREVIEW', 'delete_apply' => 'WPBC_AJX_APPOINTMENT_SERVICES_DELETE_APPLY', ), 'selected_id' => $selected_service_id, 'focus_section' => wpbc_appointment_services_get_requested_focus_section(), 'default_provider_ids' => $default_provider_ids, 'pricing_available' => wpbc_appointment_services_is_pricing_available(), 'catalog' => wpbc_appointment_services_get_catalog_client_config(), 'i18n' => array( 'loading' => __( 'Loading Services', 'booking' ) . '...', 'empty' => __( 'No Services yet', 'booking' ), 'empty_help' => __( 'Create the first Service to define what customers can book.', 'booking' ), 'no_providers' => __( 'No Providers available', 'booking' ), 'no_providers_help'=> __( 'Create a Provider before assigning Services and accepting Appointments.', 'booking' ), 'not_connected' => __( 'The Services database is not ready. Reload this page as an administrator or reactivate Booking Calendar to finish the database upgrade.', 'booking' ), 'load_failed' => __( 'Services could not be loaded.', 'booking' ), 'operation_failed' => __( 'The Service editor could not be opened. Please reload the page and try again.', 'booking' ), 'save_failed' => __( 'The Service could not be saved.', 'booking' ), 'duplicate_failed' => __( 'The Service could not be duplicated.', 'booking' ), 'archive_failed' => __( 'The Service could not be archived.', 'booking' ), 'preview_failed' => __( 'The Service changes could not be reviewed.', 'booking' ), 'apply_failed' => __( 'The Service changes could not be applied.', 'booking' ), 'delete_preview_failed' => __( 'The Service deletion could not be reviewed.', 'booking' ), 'delete_apply_failed' => __( 'The selected Services could not be permanently deleted.', 'booking' ), 'confirm_archive' => __( 'Archive this Service?', 'booking' ), 'confirm_discard' => __( 'Discard unsaved Service changes?', 'booking' ), 'untitled' => __( 'Untitled Service', 'booking' ), 'new_service' => __( 'New Service', 'booking' ), 'create_service_title' => __( 'Add Service', 'booking' ), 'create_service_description' => __( 'Create a Service without leaving the catalog.', 'booking' ), 'edit_service_title' => __( 'Edit Service', 'booking' ), 'edit_service_description' => __( 'Update this Service without leaving the catalog.', 'booking' ), 'inspector_context_new' => __( 'New', 'booking' ), /* translators: %d: Service ID. */ 'inspector_context_id' => __( 'ID: %d', 'booking' ), 'active' => __( 'Active', 'booking' ), 'draft' => __( 'Draft', 'booking' ), 'archived' => __( 'Archived', 'booking' ), 'no_provider' => __( 'No Providers assigned', 'booking' ), 'no_availability' => __( 'No weekly availability', 'booking' ), 'more_providers' => __( 'more Providers', 'booking' ), 'available' => __( 'Available', 'booking' ), 'unavailable' => __( 'Unavailable', 'booking' ), 'available_providers' => __( 'Available Providers: %s', 'booking' ), 'no_available_providers' => __( 'No assigned Providers are available', 'booking' ), 'edit_availability' => __( 'Edit availability for %s', 'booking' ), 'edit_provider_availability' => __( 'Edit Provider availability', 'booking' ), 'column_id' => __( 'ID', 'booking' ), 'column_service' => __( 'Service', 'booking' ), 'column_duration' => __( 'Duration', 'booking' ), 'column_price' => __( 'Price', 'booking' ), 'column_providers' => __( 'Providers', 'booking' ), 'column_weekly_availability' => __( 'Weekly Availability', 'booking' ), 'column_status' => __( 'Status', 'booking' ), 'column_actions' => __( 'Actions', 'booking' ), /* translators: %s: Duration in minutes. */ 'duration_minutes' => __( '%s min', 'booking' ), /* translators: 1: Buffer before in minutes, 2: Buffer after in minutes. */ 'buffers_summary' => __( 'Buffers: %1$s / %2$s min', 'booking' ), /* translators: 1: Buffer before in minutes, 2: Buffer after in minutes. */ 'buffers_tooltip' => __( 'Buffer before: %1$s min; Buffer after: %2$s min', 'booking' ), /* translators: 1: Service title, 2: Service description. */ 'service_thumbnail_tooltip' => __( 'Title: %1$s — Description: %2$s', 'booking' ), 'no_description' => __( 'No description', 'booking' ), 'edit' => __( 'Edit Service', 'booking' ), 'archive' => __( 'Archive Service', 'booking' ), /* translators: %s: Service title. */ 'select_service' => __( 'Select %s', 'booking' ), 'select_all' => __( 'Select all visible Services', 'booking' ), 'editing_rows' => __( 'Editing rows', 'booking' ), /* translators: %s: Number of changed Service rows. */ 'changed_rows' => __( '%s changed rows', 'booking' ), 'changed' => __( 'Changed', 'booking' ), 'inline_help' => __( 'Edit safe fields on this page, then review all changes before applying them.', 'booking' ), 'inline_schema_failed' => __( 'Safe inline Service fields could not be loaded.', 'booking' ), 'bulk_contract_failed' => __( 'Safe fields could not be determined for this Service selection.', 'booking' ), 'cancel' => __( 'Cancel', 'booking' ), 'review_changes' => __( 'Review changes', 'booking' ), 'apply_changes' => __( 'Apply changes', 'booking' ), 'bulk_edit_title' => __( 'Edit selected Services', 'booking' ), 'bulk_edit_description' => __( 'Enable only the fields that should change for every selected Service.', 'booking' ), 'inline_review_title' => __( 'Review inline changes', 'booking' ), 'bulk_review_title' => __( 'Review bulk changes', 'booking' ), 'review_confirmation' => __( 'Confirm the row-specific changes before applying them.', 'booking' ), 'review_description' => __( 'No Service will change until you choose Apply changes.', 'booking' ), 'showing' => __( 'Showing %1$s–%2$s of %3$s Services', 'booking' ), ), 'currency_symbol' => wpbc_appointment_services_is_pricing_available() && function_exists( 'wpbc_get_currency_symbol' ) ? wpbc_get_currency_symbol() : '', 'weekdays' => array( __( 'Monday', 'booking' ), __( 'Tuesday', 'booking' ), __( 'Wednesday', 'booking' ), __( 'Thursday', 'booking' ), __( 'Friday', 'booking' ), __( 'Saturday', 'booking' ), __( 'Sunday', 'booking' ), ), ) ); } add_action( 'wpbc_enqueue_js_files', 'wpbc_appointment_services_enqueue_js', 66 ); /** * Print Service-owned catalog templates on the Services page only. * * @return void */ function wpbc_appointment_services_print_catalog_templates() { static $templates_printed = false; if ( $templates_printed || ! wpbc_appointment_services__is_page() ) { return; } $templates_printed = true; WPBC_UI_Catalog::print_templates( 'appointment_services_catalog' ); } add_action( 'admin_footer', 'wpbc_appointment_services_print_catalog_templates', 40 ); /** * Render the global Add Service action in the Booking Calendar top toolbar. * * Creating a Service is a page-level action, while saving remains contextual * to the Service editor in the right inspector. * * @param string $page_tag Current Booking Calendar page tag. * @param string $active_page_tab Current active page tab. * @param string $active_page_subtab Current active page subtab. * * @return void */ function wpbc_appointment_services_render_top_toolbar( $page_tag, $active_page_tab, $active_page_subtab ) { if ( ! wpbc_appointment_services__is_page() || ! current_user_can( wpbc_appointment_services_get_manage_capability() ) ) { return; } ?>
> Page tab definition. */ public function tabs() { $service_hint = wpbc_appointment_services_is_pricing_available() ? __( 'Create Services and configure duration, buffers, price, Providers, and Booking Form.', 'booking' ) : __( 'Create Services and configure duration, buffers, Providers, and Booking Form.', 'booking' ); return array( 'appointment_services' => array( 'is_show_top_path' => true, 'is_show_top_navigation' => false, 'left_navigation__default_view_mode' => '', // FixIn:11.7.1.1: 'compact', 'right_vertical_sidebar__is_show' => true, 'right_vertical_sidebar__default_view_mode' => 'none', 'right_vertical_sidebar__content_click_collapse_mode' => 'none', 'right_vertical_sidebar_compact__is_show' => true, 'top_path' => array( 'root_title' => false ), 'top_path_title' => __( 'Services', 'booking' ), 'title' => __( 'Services', 'booking' ), 'page_title' => __( 'Services', 'booking' ), 'hint' => $service_hint, 'font_icon' => 'wpbc-bi-grid', 'default' => true, 'disabled' => false, 'hided' => false, 'subtabs' => array(), ), ); } /** * Render the compact Settings and Help controls for the right sidebar. * * @return void */ public function right_sidebar_compact_content() { WPBC_UI_Sidebar_Panels::render_rightbar_tabs( array( array( 'id' => 'wpbc_tab_service_settings', 'panel_id' => 'wpbc_service__inspector_settings', 'title' => __( 'Settings', 'booking' ), 'icon' => 'wpbc_icn_tune', 'selected' => true, ), array( 'id' => 'wpbc_tab_service_help', 'panel_id' => 'wpbc_service__inspector_help', 'title' => __( 'Help', 'booking' ), 'icon' => 'wpbc-bi-info-circle', ), ), array( 'aria_label' => __( 'Service Panels', 'booking' ), 'context' => 'appointment_services', 'class' => 'wpbc_appointment_services__rightbar_tabs', ) ); } /** * Render the right-sidebar Settings and Help inspector panels. * * @return void */ public function right_sidebar_content() { ?>
'wpbc_service__inspector_settings', 'labelledby' => 'wpbc_tab_service_settings', 'class' => 'wpbc_appointment_services__inspector_settings', ), 'wpbc_appointment_services_render_settings_panel' ); WPBC_UI_Sidebar_Panels::render_panel( array( 'id' => 'wpbc_service__inspector_help', 'labelledby' => 'wpbc_tab_service_help', 'class' => 'wpbc_appointment_services__inspector_help', 'hidden' => true, ), 'wpbc_appointment_services_render_help_panel' ); ?>
0