/**
  * Auto setup settings.
  *
  * Fires after a membership setup is completed.
  * This hook is executed every time a new membership is created.
  *
  * Related Action Hooks:
  * - ms_controller_membership_setup_completed
  *
  * @since  1.0.0
  *
  * @param MS_Model_Membership $membership
  */
 public function auto_setup_settings($membership)
 {
     $settings = $this->get_model();
     // Create special pages.
     MS_Model_Pages::create_missing_pages();
     $pg_prot_cont = MS_Model_Pages::get_page(MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT);
     $pg_acco = MS_Model_Pages::get_page(MS_Model_Pages::MS_PAGE_ACCOUNT);
     $pg_regi = MS_Model_Pages::get_page(MS_Model_Pages::MS_PAGE_REGISTER);
     $pg_regi_comp = MS_Model_Pages::get_page(MS_Model_Pages::MS_PAGE_REG_COMPLETE);
     $pg_memb = MS_Model_Pages::get_page(MS_Model_Pages::MS_PAGE_MEMBERSHIPS);
     // Publish special pages.
     // Tip: Only pages must be published that are added to the menu.
     wp_publish_post($pg_acco->ID);
     if (!$membership->private) {
         wp_publish_post($pg_memb->ID);
         wp_publish_post($pg_regi->ID);
     }
     // Create new WordPress menu-items.
     MS_Model_Pages::create_menu(MS_Model_Pages::MS_PAGE_ACCOUNT);
     if (!$membership->private) {
         MS_Model_Pages::create_menu(MS_Model_Pages::MS_PAGE_MEMBERSHIPS);
         MS_Model_Pages::create_menu(MS_Model_Pages::MS_PAGE_REGISTER);
     }
     // Enable Membership2.
     $settings->plugin_enabled = true;
     $settings->save();
     // Enable the "Allow user registration" setting of WordPress
     MS_Model_Member::allow_registration();
 }
 /**
  * Ajax handler. Used by shortcode `ms-membership-login` to recover password
  *
  * @since  1.0.0
  * @access public
  */
 public function ajax_lostpass()
 {
     global $wpdb, $wp_hasher;
     $resp = array();
     // First check the nonce, if it fails the function will break
     check_ajax_referer('ms-ajax-lostpass');
     // Nonce is checked, get the POST data and sign user on
     $errors = new WP_Error();
     if (empty($_POST['user_login'])) {
         $resp['error'] = __('Enter a username or e-mail address.', MS_TEXT_DOMAIN);
     } else {
         if (strpos($_POST['user_login'], '@')) {
             $user_data = get_user_by('email', trim($_POST['user_login']));
             if (empty($user_data)) {
                 $resp['error'] = __('There is no user registered with that email address.', MS_TEXT_DOMAIN);
             }
         } else {
             $login = trim($_POST['user_login']);
             $user_data = get_user_by('login', $login);
         }
     }
     do_action('lostpassword_post');
     if (!empty($resp['error'])) {
         $this->respond($resp);
     }
     if (!$user_data) {
         $resp['error'] = __('Invalid username or e-mail.', MS_TEXT_DOMAIN);
         $this->respond($resp);
     }
     // Redefining user_login ensures we return the right case in the email.
     $user_login = $user_data->user_login;
     $user_email = $user_data->user_email;
     do_action('retreive_password', $user_login);
     // Legacy (misspelled)
     do_action('retrieve_password', $user_login);
     $allow = apply_filters('allow_password_reset', true, $user_data->ID);
     if (!$allow) {
         $resp['error'] = __('Password reset is not allowed for this user', MS_TEXT_DOMAIN);
         $this->respond($resp);
     } else {
         if (is_wp_error($allow)) {
             return $allow;
         }
     }
     // Generate something random for a password reset key.
     $key = wp_generate_password(20, false);
     do_action('retrieve_password_key', $user_login, $key);
     // Now insert the key, hashed, into the DB.
     if (empty($wp_hasher)) {
         require_once ABSPATH . WPINC . '/class-phpass.php';
         $wp_hasher = new PasswordHash(8, true);
     }
     $hashed = $wp_hasher->HashPassword($key);
     $wpdb->update($wpdb->users, array('user_activation_key' => $hashed), array('user_login' => $user_login));
     MS_Model_Pages::create_missing_pages();
     $reset_url = MS_Model_Pages::get_page_url(MS_Model_Pages::MS_PAGE_ACCOUNT);
     $reset_url = esc_url_raw(add_query_arg(array('action' => MS_Controller_Frontend::ACTION_VIEW_RESETPASS, 'key' => $key, 'login' => rawurlencode($user_login)), $reset_url));
     $message = __('Someone requested that the password be reset for the following account:') . "\r\n\r\n";
     $message .= network_home_url('/') . "\r\n\r\n";
     $message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n";
     $message .= __('If this was a mistake, just ignore this email and nothing will happen.') . "\r\n\r\n";
     $message .= __('To reset your password, visit the following address:') . "\r\n\r\n";
     $message .= '<' . $reset_url . ">\r\n";
     if (is_multisite()) {
         $blogname = $GLOBALS['current_site']->site_name;
     } else {
         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
     }
     $title = sprintf(__('[%s] Password Reset'), $blogname);
     $title = apply_filters('retrieve_password_title', $title);
     $message = apply_filters('retrieve_password_message', $message, $key, $reset_url);
     if ($message && !wp_mail($user_email, wp_specialchars_decode($title), $message)) {
         $resp['error'] = __('The e-mail could not be sent.') . '<br />' . __('Possible reason: your host may have disabled the mail() function.');
     } else {
         $resp['success'] = __('Check your e-mail for the confirmation link.', MS_TEXT_DOMAIN);
     }
     $this->respond($resp);
 }
 /**
  * Creates a new password-reset key and stores it in the DB.
  *
  * @since  1.0.2.3
  * @return object {
  *         The reset-key that can be sent to the user.
  *
  *         @var  key   The reset key
  *         @var  url   The full reset URL
  *  }
  */
 public function new_password_reset_key()
 {
     global $wpdb, $wp_hasher;
     // Generate something random for a password reset key.
     $key = wp_generate_password(20, false);
     do_action('retrieve_password_key', $this->username, $key);
     // Now insert a hashed version of the key into the DB.
     // Important: The has needs to include the time() value!
     if (empty($wp_hasher)) {
         require_once ABSPATH . WPINC . '/class-phpass.php';
         $wp_hasher = new PasswordHash(8, true);
     }
     $hashed = time() . ':' . $wp_hasher->HashPassword($key);
     $wpdb->update($wpdb->users, array('user_activation_key' => $hashed), array('user_login' => $this->username));
     MS_Model_Pages::create_missing_pages();
     $reset_url = MS_Model_Pages::get_page_url(MS_Model_Pages::MS_PAGE_ACCOUNT);
     $reset_url = esc_url_raw(add_query_arg(array('action' => MS_Controller_Frontend::ACTION_VIEW_RESETPASS, 'key' => $key, 'login' => rawurlencode($this->username)), $reset_url));
     return (object) array('key' => $key, 'url' => $reset_url);
 }
 /**
  * Upgrade database.
  *
  * @since  1.0.0
  * @param  bool $force Also execute update logic when version did not change.
  */
 public static function update($force = false)
 {
     static $Done = false;
     if ($Done && !$force) {
         return;
     }
     // Migration handler has its own valid_user check.
     self::check_migration_handler();
     // Updates are only triggered from Admin-Side by an Admin user.
     if (!self::valid_user()) {
         return;
     }
     // Check for correct network-wide protection setup.
     self::check_settings();
     $settings = MS_Factory::load('MS_Model_Settings');
     $old_version = $settings->version;
     // Old: The version in DB.
     $new_version = MS_Plugin::instance()->version;
     // New: Version in file.
     $is_new_setup = empty($old_version);
     // Compare current src version to DB version:
     // We only do UP-grades but no DOWN-grades!
     if ($old_version) {
         $version_changed = version_compare($old_version, $new_version, 'lt');
     } else {
         $version_changed = true;
     }
     if ($force || $version_changed) {
         $Done = true;
         $msg = array();
         /*
          * ----- General update logic, executed on every update ------------
          */
         do_action('ms_model_upgrade_before_update', $settings, $old_version, $new_version, $force);
         // Prepare the Update message.
         if (!$version_changed) {
             $msg[] = sprintf(__('<strong>Membership 2</strong> is set up for version %1$s!', 'membership2'), $new_version);
         } else {
             $msg[] = sprintf(__('<strong>Membership 2</strong> was updated to version %1$s!', 'membership2'), $new_version);
         }
         // Every time the plugin is updated we clear the cache.
         MS_Factory::clear();
         // Create missing Membership pages.
         $new_pages = MS_Model_Pages::create_missing_pages();
         if (!empty($new_pages)) {
             $msg[] = sprintf(__('New Membership pages created: "%1$s".', 'membership2'), implode('", "', $new_pages));
         }
         // Remove an old version of Protected Content
         // TODO: REMOVE THIS BLOCK/FUNCTION END OF 2015
         if ($version_changed) {
             self::remove_old_copy();
         }
         // Note: We do not create menu items on upgrade! Users might have
         // intentionally removed the items from the menu...
         /*
          * ----- Version-Specific update logic -----------------------------
          */
         // Upgrade from a 1.0.0.x version to 1.0.1.0 or higher
         if (version_compare($old_version, '1.0.1.0', 'lt')) {
             self::_upgrade_1_0_1_0();
         }
         // Upgrade from 1.0.1.0 version to 1.0.1.1 or higher
         if (version_compare($old_version, '1.0.1.1', 'lt')) {
             self::_upgrade_1_0_1_1();
         }
         // Upgrade from 1.0.1.x version to 1.0.2.0 or higher
         if (version_compare($old_version, '1.0.2.0', 'lt')) {
             self::_upgrade_1_0_2_0();
         }
         // Upgrade from 1.0.2.x version to 1.0.2.4 or higher
         if (version_compare($old_version, '1.0.2.4', 'lt')) {
             self::_upgrade_1_0_2_4();
         }
         /*
          * ----- General update logic, executed on every update ------------
          */
         $settings->version = $new_version;
         $settings->save();
         // Display a message after the page is reloaded.
         if (!$is_new_setup) {
             lib3()->ui->admin_message(implode('<br>', $msg), '', '', 'ms-update');
         }
         do_action('ms_model_upgrade_after_update', $settings, $old_version, $new_version, $force);
         $addons = MS_Factory::load('MS_Model_Addon');
         $addons->flush_list();
         // This will reload the current page.
         MS_Plugin::flush_rewrite_rules();
     }
 }
 /**
  * Prepare the HTML fields that can be displayed
  *
  * @since  1.0.0
  *
  * @return array
  */
 protected function prepare_fields()
 {
     // Prepare the return value.
     $nav = array();
     $pages = array();
     MS_Model_Pages::create_missing_pages();
     $page_types = MS_Model_Pages::get_page_types();
     $page_types_menu = array('memberships', 'register', 'account');
     $page_types_rest = array_diff($page_types, $page_types_menu);
     // Prepare NAV fields.
     $menu_action = MS_Controller_Pages::AJAX_ACTION_TOGGLE_MENU;
     $menu_nonce = wp_create_nonce($menu_action);
     foreach ($page_types_menu as $type) {
         $nav_exists = MS_Model_Pages::has_menu($type);
         $nav[$type] = array('type' => MS_Helper_Html::INPUT_TYPE_RADIO_SLIDER, 'id' => 'nav_' . $type, 'value' => $nav_exists, 'title' => $page_types[$type], 'ajax_data' => array('action' => $menu_action, 'item' => $type, '_wpnonce' => $menu_nonce));
     }
     $nav['sep'] = array('type' => MS_Helper_Html::TYPE_HTML_SEPARATOR);
     // Prepare PAGES fields.
     $pages_action = MS_Controller_Pages::AJAX_ACTION_UPDATE_PAGES;
     $pages_nonce = wp_create_nonce($pages_action);
     foreach ($page_types as $type => $label) {
         $page_id = MS_Model_Pages::get_setting($type);
         $title = sprintf('<strong>%1$s</strong><span class="lbl-details">: %2$s</span>', $label, MS_Model_Pages::get_description($type));
         $pages[$type] = array('id' => $type, 'type' => MS_Helper_Html::INPUT_TYPE_WP_PAGES, 'title' => $title, 'value' => $page_id, 'field_options' => array('no_item' => __('- Select a page -', MS_TEXT_DOMAIN)), 'ajax_data' => array('field' => $type, 'action' => $pages_action, '_wpnonce' => $pages_nonce));
     }
     $fields = array('nav' => $nav, 'pages' => $pages);
     return apply_filters('ms_view_settings_page_setup_prepare_fields', $fields, $this);
 }
 /**
  * Checks member permissions and protects current page.
  *
  * Related Action Hooks:
  * - template_redirect
  *
  * @since  1.0.0
  */
 public function protect_current_page()
 {
     do_action('ms_model_plugin_protect_current_page_before', $this);
     // Admin user has access to everything
     if ($this->member->is_normal_admin()) {
         return;
     }
     $access = $this->get_access_info();
     if (!$access['has_access']) {
         MS_Model_Pages::create_missing_pages();
         $no_access_page_url = MS_Model_Pages::get_page_url(MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT, false);
         $current_page_url = MS_Helper_Utility::get_current_url();
         // Don't (re-)redirect the protection page.
         if (!MS_Model_Pages::is_membership_page(null, MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT)) {
             $no_access_page_url = esc_url_raw(add_query_arg(array('redirect_to' => urlencode($current_page_url)), $no_access_page_url));
             $no_access_page_url = apply_filters('ms_model_plugin_protected_content_page', $no_access_page_url);
             wp_safe_redirect($no_access_page_url);
             exit;
         }
     }
     do_action('ms_model_plugin_protect_current_page_after', $this);
 }