/**
  * Filter that is called when Appointment settings are saved.
  *
  * We use this filter to save all custom settings that we added via the
  * settings_form() function.
  * Note that we store the payment settings in the Membership object as
  * custom_data and not in the Appointments option structure!
  *
  * @since  1.0.0
  * @param  array $settings Appointments Settings collection.
  * @return array Modified Appointments Settings collection.
  */
 public function settings_save($settings)
 {
     $data = false;
     if (isset($_POST['ms_appointment_data'])) {
         $data = $_POST['ms_appointment_data'];
     }
     if (is_array($data)) {
         foreach ($data as $id => $item) {
             $item['discount'] = empty($item['discount']) ? 0 : $item['discount'];
             $item['type'] = empty($item['type']) ? 'per' : $item['type'];
             $item['no_advance'] = !empty($item['no_advance']);
             $membership = $this->api->get_membership($id);
             $membership->set_custom_data('app_discount_value', $item['discount']);
             $membership->set_custom_data('app_discount_type', $item['type']);
             $membership->set_custom_data('app_no_advance_payment', $item['no_advance']);
             $membership->save();
         }
     }
     return $settings;
 }
 /**
  * Constructs the primary Plugin controller.
  *
  * Created by the MS_Plugin object during the setup_theme action.
  *
  * @since  1.0.0
  */
 public function __construct()
 {
     parent::__construct();
     /**
      * Fix for IE: This is a privacy policy which states, that we do not
      * collect personal contact information without consent.
      *
      * Note that other plugins that output this header later will overwrite
      * it! So this is a default value if no other file sends the P3P header.
      *
      * @since  1.0.2.2
      */
     $p3p_done = false;
     foreach (headers_list() as $header) {
         if (false !== stripos($header, 'P3P:')) {
             $p3p_done = true;
             break;
         }
     }
     if (!$p3p_done) {
         header('P3P:CP="NOI"');
     }
     /*
      * Remove the "&msg" attribute from the URL if it was already present in
      * the previous request.
      */
     if (empty($_POST)) {
         /*
          * No form was submitted:
          * It's save to redirect the request without losing form-data.
          */
         if (isset($_GET['msg']) && isset($_SERVER['HTTP_REFERER']) && MS_Helper_Utility::is_current_url($_SERVER['HTTP_REFERER'])) {
             // A msg is set AND the referer URL has the same msg flag!
             $url = esc_url_raw(remove_query_arg(array('msg')));
             wp_safe_redirect($url);
             exit;
         }
     }
     /**
      * We allow two ways to modify the default Admin-Capability setting:
      *
      * Either by defining the constant in wp-config or by using the filter.
      * The constant takes priority over the filter.
      *
      * @since  1.0.0
      */
     if (defined('MS_ADMIN_CAPABILITY')) {
         $this->capability = MS_ADMIN_CAPABILITY;
     } else {
         $this->capability = apply_filters('ms_admin_user_capability', $this->capability);
     }
     // Create core controllers that are available on every page.
     $this->model = MS_Factory::load('MS_Model_Plugin');
     $this->dialogs = MS_Factory::load('MS_Controller_Dialog');
     $this->controllers['widget'] = MS_Factory::load('MS_Controller_Widget');
     $this->controllers['membership'] = MS_Factory::load('MS_Controller_Membership');
     $this->controllers['protection'] = MS_Factory::load('MS_Controller_Protection');
     $this->controllers['rule'] = MS_Factory::load('MS_Controller_Rule');
     $this->controllers['member'] = MS_Factory::load('MS_Controller_Member');
     $this->controllers['billing'] = MS_Factory::load('MS_Controller_Billing');
     $this->controllers['addon'] = MS_Factory::load('MS_Controller_Addon');
     $this->controllers['pages'] = MS_Factory::load('MS_Controller_Pages');
     $this->controllers['settings'] = MS_Factory::load('MS_Controller_Settings');
     $this->controllers['communication'] = MS_Factory::load('MS_Controller_Communication');
     $this->controllers['gateway'] = MS_Factory::load('MS_Controller_Gateway');
     $this->controllers['admin_bar'] = MS_Factory::load('MS_Controller_Adminbar');
     $this->controllers['membership_metabox'] = MS_Factory::load('MS_Controller_Metabox');
     $this->controllers['membership_shortcode'] = MS_Factory::load('MS_Controller_Shortcode');
     $this->controllers['frontend'] = MS_Factory::load('MS_Controller_Frontend');
     $this->controllers['import'] = MS_Factory::load('MS_Controller_Import');
     $this->controllers['help'] = MS_Factory::load('MS_Controller_Help');
     // API should be the last Controller to create.
     $this->controllers['api'] = MS_Controller_Api::instance();
     // Register all available styles and scripts. Nothing is enqueued.
     $this->add_action('wp_loaded', 'wp_loaded');
     // Setup plugin admin UI.
     $this->add_action('admin_menu', 'add_menu_pages');
     if (MS_Plugin::is_network_wide()) {
         $this->add_action('network_admin_menu', 'add_menu_pages');
     }
     // Select the right page to display.
     $this->add_action('admin_init', 'route_submenu_request');
     // This will do the ADMIN-SIDE initialization of the controllers
     $this->add_action('ms_plugin_admin_setup', 'run_admin_init');
     // Changes the current themes "single" template to the invoice form when an invoice is displayed.
     $this->add_filter('single_template', 'custom_single_template');
     $this->add_filter('page_template', 'custom_page_template');
     // Register styles and javascripts for use in front-end
     $this->add_action('ms_register_public_scripts', 'register_public_scripts');
     $this->add_action('ms_register_public_scripts', 'register_public_styles');
     $this->add_action('wp_enqueue_scripts', 'enqueue_plugin_styles');
     $this->add_action('wp_enqueue_scripts', 'enqueue_plugin_scripts');
 }
 /**
  * Procedural way to load the API instance.
  *
  * Call this function inside the init hook or later. Using it earlier might
  * cause problems because other parts of M2 might not be completely
  * initialized.
  *
  * @since  1.0.1.2
  * @api
  * @return MS_Controller_Api
  */
 function ms_api()
 {
     if (!did_action('init')) {
         _doing_it_wrong('ms_api', 'ms_api() is called before the "init" hook, this is too early!', '1.0.1.2');
     }
     return MS_Controller_Api::instance();
 }