register_main_settings(); $this->register_zoho_settings(); $this->register_stripe_settings(); } protected function register_main_settings() { add_settings_section( self::SETTINGS_SECTION_MAIN, fqp__( 'General Settings' ), function () { echo ''; /* section description */ }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php' ); add_settings_field( "fqp-main-offline-payment-fee", fqp__( 'Offline Payment Fee' ), function () { $value = esc_attr( get_option( "fqp-main-offline-payment-fee" ) ); echo "CHF"; }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php', self::SETTINGS_SECTION_MAIN ); register_setting( self::SETTINGS_GROUP, "fqp-main-offline-payment-fee", [ $this, 'sanitize_price' ] ); $langs = FQP::get_lang_list(); foreach ( $langs as $lang ) { $lang_code = esc_html( $lang['code'] ); $lang_title = esc_html( $lang['translated_name'] ); // thanks page add_settings_field( "fqp-main-thanks-page-{$lang_code}", fqp__( 'Thanks Page URL' ) . " ({$lang_title})", function () use ( $lang_code ) { $value = esc_attr( get_option( "fqp_main_thanks_page_{$lang_code}" ) ); echo ""; }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php', self::SETTINGS_SECTION_MAIN ); register_setting( self::SETTINGS_GROUP, "fqp_main_thanks_page_{$lang_code}", [ $this, 'sanitize_page_url' ] ); // cancel page add_settings_field( "fqp-main-cancel-page-{$lang_code}", fqp__( 'Cancel Page URL' ) . " ({$lang_title})", function () use ( $lang_code ) { $value = esc_attr( get_option( "fqp_main_cancel_page_{$lang_code}" ) ); echo ""; }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php', self::SETTINGS_SECTION_MAIN ); register_setting( self::SETTINGS_GROUP, "fqp_main_cancel_page_{$lang_code}", [ $this, 'sanitize_page_url' ] ); } foreach ( $langs as $lang ) { $lang_code = esc_html( $lang['code'] ); $lang_title = esc_html( $lang['translated_name'] ); add_settings_field( "fqp-main-form-intro-{$lang_code}", fqp__( 'Form Introduction' ) . " ({$lang_title})", function () use ( $lang_code ) { wp_editor( get_option( "fqp_main_form_intro_{$lang_code}" ), "fqp-main-form-intro-{$lang_code}", [ 'textarea_name' => "fqp_main_form_intro_{$lang_code}", 'textarea_rows' => 10, ] ); }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php', self::SETTINGS_SECTION_MAIN ); register_setting( self::SETTINGS_GROUP, "fqp_main_form_intro_{$lang_code}" ); } foreach ( $langs as $lang ) { $lang_code = esc_html( $lang['code'] ); $lang_title = esc_html( $lang['translated_name'] ); add_settings_field( "fqp-main-specific-services-info-{$lang_code}", fqp__( 'Specific Services Information' ) . " ({$lang_title})", function () use ( $lang_code ) { wp_editor( get_option( "fqp_main_specific_services_info_{$lang_code}" ), "fqp-main-specific-services-info-{$lang_code}", [ 'textarea_name' => "fqp_main_specific_services_info_{$lang_code}", 'textarea_rows' => 10, ] ); }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php', self::SETTINGS_SECTION_MAIN ); register_setting( self::SETTINGS_GROUP, "fqp_main_specific_services_info_{$lang_code}" ); } } public function sanitize_page_url( $value ) { $value = trim( $value ); if ( ! preg_match( '/(?:http|https):\/\/((?:[\w-]+)(?:\.[\w-]+)+)(?:[\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/', $value ) ) { return ''; } return $value; } public static function get_thanks_url( $lang = null ) { if ( null == $lang ) { $lang = FQP::get_curr_lang(); } return get_option( "fqp_main_thanks_page_{$lang}" ); } public static function get_cancel_url( $lang = null ) { if ( null == $lang ) { $lang = FQP::get_curr_lang(); } return get_option( "fqp_main_cancel_page_{$lang}" ); } public static function get_zoho_fileds() { $fields = [ [ 'id' => 'fqp-zoho-client-id', 'name' => 'fqp_zoho_client_id', 'label' => 'Client ID' ], [ 'id' => 'fqp-zoho-client-secret', 'name' => 'fqp_zoho_client_secret', 'label' => 'Client Secret' ], [ 'id' => 'fqp-zoho-user-email', 'name' => 'fqp_zoho_user_email', 'label' => 'User Email' ], [ 'id' => 'fqp-zoho-authorized-redirect-uri', 'name' => 'fqp_zoho_authorized_redirect_uri', 'label' => 'Aauthorized Redirect URI', 'sanitize_callback' => [ self::class, 'sanitize_page_url' ], 'default_value' => admin_url( 'admin-post.php') . '?action=zoho-auth', ], [ 'id' => 'fqp-zoho-grant-token', 'name' => 'fqp_zoho_grant_token', 'label' => 'Grant Token' ], ]; return $fields; } protected function register_zoho_settings() { add_settings_section( self::SETTINGS_SECTION_ZOHO, fqp__( 'ZOHO Settings' ), function () { echo ''; /* section description */ }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php' ); $is_zoho_authorized = get_option( 'fqp_zoho_authorized' ); $fields = self::get_zoho_fileds(); foreach ( $fields as $field ) { add_settings_field( $field['id'], fqp__( $field['label'] ), function () use ( $field, $is_zoho_authorized ) { $disabled = ( $is_zoho_authorized ) ? ' readonly="readonly"' : ''; $value = esc_attr( get_option( $field['name'] ) ); if (!$value && !empty( $field['default_value'] ) ) { $value = $field['default_value']; } echo ""; }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php', self::SETTINGS_SECTION_ZOHO ); if ( array_key_exists( 'sanitize_callback', $field ) && is_callable( $field['sanitize_callback'] ) ) { $sanitize_callback = $field['sanitize_callback']; } else { $sanitize_callback = [ $this, 'sanitize_zoho_field' ]; } register_setting( self::SETTINGS_GROUP, $field['name'], $sanitize_callback ); } add_settings_field( 'zoho-authorized', ' ', function () use ($is_zoho_authorized) { if ($is_zoho_authorized) { $url = admin_url( 'admin.php' ) . '?page=' . urlencode( 'fasoon-quote-a-price/admin/settings.php' ) . '&revoke_token=1'; echo '' . __( 'Revoke Token', FQP::TEXT_DOMAIN ) . ''; } else { ?> 'fqp-stripe-api-key', 'name' => 'fqp_stripe_api_key', 'label' => 'API Key' ], [ 'id' => 'fqp-stripe-secret-key', 'name' => 'fqp_stripe_secret_key', 'label' => 'Secret Key' ], [ 'id' => 'fqp-stripe-webhooks-secret', 'name' => 'fqp_stripe_webhooks_secret', 'label' => 'Webhooks Signing Secret' ], ]; return $fields; } protected function register_stripe_settings() { add_settings_section( self::SETTINGS_SECTION_STRIPE, fqp__( 'Stripe Settings' ), function () { echo ''; /* section description */ }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php' ); $fields = self::get_stripe_fields(); foreach ( $fields as $field ) { add_settings_field( $field['id'], fqp__( $field['label'] ), function () use ( $field ) { $value = esc_attr( get_option( $field['name'] ) ); echo ""; }, dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php', self::SETTINGS_SECTION_STRIPE ); if ( array_key_exists( 'sanitize_callback', $field ) && is_callable( $field['sanitize_callback'] ) ) { $sanitize_callback = $field['sanitize_callback']; } else { $sanitize_callback = [ $this, 'sanitize_zoho_field' ]; } register_setting( self::SETTINGS_GROUP, $field['name'], $sanitize_callback ); } } public function sanitize_zoho_field( $value ) { $value = trim( $value ); return $value; } public function validatePrice( $price ) { $error = false; if ( '' == $price ) { $error = fqp__( '%s is required' ); } elseif ( !is_numeric( $price ) ) { $error = fqp__( '%s is in wrong format' ); } elseif ( floatval( $price ) < 0 ) { $error = fqp__( '%s is wrong' ); } return $error; } public function sanitize_prices( $data ) { if ( empty( $data ) ) { return $data; } $errors = []; $entry_types = DB::get_entry_types(); $backing_types = DB::get_backing_types(); $lang = FQP::get_curr_lang(); foreach ( $entry_types as $entry_id => $entry ) { if ( 'y' == $entry['hasBacking'] ) { foreach ( $backing_types as $backing_id => $backing ) { $backing_price = $this->sanitize_price( @$data['price'][$entry_id][$backing_id][$lang] ); $data['price'][$entry_id][$backing_id][$lang] = $backing_price; $error = $this->validatePrice( $backing_price ); if ( $error ) { $key = $entry_id . '-' . $backing_id; $title = $entry['title'] . ' ' . fqp__( 'with' ) . ' ' . $backing['title'] . ' ' . fqp__( 'Price' ); $errors[$key] = sprintf( $error, $title ); } } } else { $entry_price = $this->sanitize_price( @$data['price'][$entry_id][$lang] ); $data['price'][$entry_id][$lang] = $entry_price; $error = $this->validatePrice( $entry_price ); if ( $error ) { $key = $entry_id; $title = $entry['title'] . ' ' . fqp__( 'Price' ); $errors[$key] = sprintf( $error, $title ); } } } if ( !empty( $errors ) ) { if ( function_exists( 'add_settings_error' ) ) { foreach ( $errors as $key => $error ) { add_settings_error( self::OPTION_PRICES, "invalid_{$key}", $error ); } } set_transient( 'settings_errors', get_settings_errors(), 30 ); set_transient( self::OPTION_PRICES, $data, 30 ); $back_url = add_query_arg( 'settings-updated', 'false', wp_get_referer() ); wp_redirect( $back_url ); exit; } $db_data = get_option( self::OPTION_PRICES, [] ); return self::mergeRecursive( $db_data, $data ); } public function allowed_options( $options ) { if ( array_key_exists( self::OPTION_GROUP, $options ) ) { foreach ( $options[self::OPTION_GROUP] as $key => $option) { if ( !array_key_exists( $option, $_POST ) ) { unset( $options[self::OPTION_GROUP][$key] ); } } } return $options; } public function sanitize_emails( $data ) { if (empty($data)) { return $data; } $errors = []; $data['emails'] = join( ', ', $this->sanitize_emails_list( $data['emails'] ) ); if ( empty( $data['emails'] ) ) { $errors[] = fqp__( 'Notification Email is required.' ); } $data['subject'] = sanitize_text_field( $data['subject'] ); if ( empty( $data['subject'] ) ) { $errors[] = fqp__( 'Notification Subject is required.' ); } if ( empty( $data['body'] ) ) { $errors[] = fqp__( 'Notification Body is required.' ); } if ( !empty( $errors ) ) { if ( function_exists( 'add_settings_error' ) ) { foreach ( $errors as $key => $error ) { add_settings_error( self::OPTION_EMAILS, "invalid_{$key}", $error ); } } set_transient( 'settings_errors', get_settings_errors(), 30 ); set_transient( self::OPTION_EMAILS, $data, 30 ); $back_url = add_query_arg( 'settings-updated', 'false', wp_get_referer() ); wp_redirect( $back_url ); exit; } $db_data = get_option( self::OPTION_EMAILS, [] ); return self::mergeRecursive( $db_data, $data ); } public static function mergeRecursive($firstArray, $secondArray) { if (is_array($firstArray) && is_array($secondArray)) { foreach ($secondArray as $key => $value) { if (isset($firstArray[$key])) { $firstArray[$key] = self::mergeRecursive($firstArray[$key], $value); } else { $firstArray[$key] = $value; } } } else { $firstArray = $secondArray; } return $firstArray; } public function admin_menu() { add_menu_page( fqp__( 'Fasoon' ), fqp__( 'Fasoon' ), 'manage_options', 'fasoon-quote-price', [ $this, 'price_menu' ], plugins_url( 'img/icon.png', FQP_PLUGIN_BASE_NAME ) ); add_submenu_page( 'fasoon-quote-price', fqp__( 'Submissions' ), fqp__( 'Submissions' ), 'manage_options', dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/submissions.php' ); add_submenu_page( 'fasoon-quote-price', fqp__( 'Pricing' ), fqp__( 'Pricing' ), 'manage_options', dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/prices.php' ); add_submenu_page( 'fasoon-quote-price', fqp__( 'Emails' ), fqp__( 'Emails' ), 'manage_options', dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/emails.php' ); add_submenu_page( 'fasoon-quote-price', fqp__( 'Partners' ), fqp__( 'Partners' ), 'manage_options', 'edit.php?post_type=' . FQP::PARTNER_POST_TYPE ); add_submenu_page( 'fasoon-quote-price', fqp__( 'Products' ), fqp__( 'Products' ), 'manage_options', 'edit.php?post_type=' . Product::POST_TYPE ); add_submenu_page( 'fasoon-quote-price', fqp__( 'Cantonal Partners' ), fqp__( 'Cantonal Partners' ), 'manage_options', 'edit.php?post_type=' . Bank::POST_TYPE ); add_submenu_page( 'fasoon-quote-price', fqp__( 'Settings' ), fqp__( 'Settings' ), 'manage_options', dirname( FQP_PLUGIN_BASE_NAME ) . '/admin/settings.php' ); remove_submenu_page('fasoon-quote-price', 'fasoon-quote-price'); } public function price_menu() { wp_redirect( dirname( FQP_PLUGIN_BASE_NAME ) . '/admin-options.php' ); } public function sanitize_price( $price ) { return preg_replace( '/[^\.0-9]+/', '', $price ); } public function sanitize_emails_list( $emails ) { $emails = preg_split( '/[\s, ]+/', $emails ); $emails = array_filter( $emails ); foreach ( $emails as &$email ) { $email = sanitize_email( trim( $email ) ); } unset( $email ); $emails = array_filter( $emails ); return $emails; } public static function get_prices() { $prices = get_option( Settings::OPTION_PRICES ); $prices['partner_discount'] = []; $partners = DB::get_partners(); if ( $partners ) { /** @var \WP_post $partner */ foreach ( $partners as $partner ) { $prices['partner_discount'][$partner->ID] = $partner->acf['partner_discount']; } } return $prices; } }