public function get_columns()
 {
     $currency = MS_Plugin::instance()->settings->currency;
     $columns = apply_filters('ms_helper_listtable_billing_columns', array('cb' => '<input type="checkbox" />', 'invoice' => __('Invoice #', 'membership2'), 'user' => __('User', 'membership2'), 'membership' => __('Membership', 'membership2'), 'status' => __('Status', 'membership2'), 'total' => __('Total', 'membership2'), 'due_date' => __('Due date', 'membership2'), 'gateway_id' => __('Gateway', 'membership2')));
     $columns = apply_filters('ms_helper_listtable_billing_get_columns', $columns, $currency);
     return $columns;
 }
 /**
  * Defines the columns of the list table
  *
  * @since  1.0.0
  * @return array
  */
 public function get_columns()
 {
     $currency = MS_Plugin::instance()->settings->currency;
     $columns = apply_filters('ms_helper_listtable_transactionlog_columns', array('id' => __('ID', 'membership2'), 'date' => __('Time', 'membership2'), 'status' => '', 'method' => '', 'gateway' => __('Gateway', 'membership2'), 'amount' => __('Amount', 'membership2'), 'invoice' => __('Invoice', 'membership2'), 'note' => __('Details', 'membership2')));
     $columns = apply_filters('ms_helper_listtable_transactionlog_get_columns', $columns, $currency);
     return $columns;
 }
 /**
  * Prepare html fields.
  *
  * @since  1.0.0
  *
  * @return array
  */
 function prepare_fields()
 {
     $invoice = $this->data['invoice'];
     $currency = MS_Plugin::instance()->settings->currency;
     $user_name = '';
     $transaction_link = '';
     $user_id = 0;
     $user_list = array();
     if ($invoice->id) {
         $member = $invoice->get_member();
         $user_id = $member->id;
         $user_name = $member->name;
         $transaction_link = sprintf('<a href="%s" target="_blank">%s</a>', MS_Controller_Plugin::get_admin_url('billing', array('show' => 'logs', 'invoice' => $invoice->id)), __('Show Transactions', 'membership2'));
     } else {
         $user_list = MS_Model_Member::get_usernames(null, MS_Model_Member::SEARCH_ALL_USERS);
     }
     $fields = array('link_transactions' => array('id' => 'link_transactions', 'title' => $transaction_link, 'type' => MS_Helper_Html::TYPE_HTML_TEXT, 'wrapper_class' => 'ms-transactions-link'), 'txt_user' => array('id' => 'txt_user', 'title' => __('Invoice for member', 'membership2'), 'type' => MS_Helper_Html::TYPE_HTML_TEXT, 'value' => sprintf('<a href="%s">%s</a>', MS_Controller_Plugin::get_admin_url('add-member', array('user_id' => $user_id)), $user_name)), 'txt_membership' => array('id' => 'txt_membership', 'title' => __('Payment for membership', 'membership2'), 'type' => MS_Helper_Html::TYPE_HTML_TEXT), 'txt_created' => array('id' => 'txt_created', 'title' => __('Invoice created on', 'membership2'), 'type' => MS_Helper_Html::TYPE_HTML_TEXT), 'txt_separator' => array('type' => MS_Helper_Html::TYPE_HTML_SEPARATOR), 'status' => array('id' => 'status', 'title' => __('Invoice status', 'membership2'), 'type' => MS_Helper_Html::INPUT_TYPE_SELECT, 'field_options' => MS_Model_Invoice::get_status_types(true), 'value' => $invoice->status), 'user_id' => array('id' => 'user_id', 'title' => __('Invoice for member', 'membership2'), 'type' => MS_Helper_Html::INPUT_TYPE_SELECT, 'value' => $invoice->user_id, 'field_options' => $user_list), 'membership_id' => array('id' => 'membership_id', 'title' => __('Payment for membership', 'membership2'), 'type' => MS_Helper_Html::INPUT_TYPE_SELECT, 'value' => $invoice->membership_id, 'field_options' => $this->data['memberships']), 'amount' => array('id' => 'amount', 'title' => sprintf(__('Amount (%s)', 'membership2'), $currency), 'type' => MS_Helper_Html::INPUT_TYPE_NUMBER, 'value' => MS_Helper_Billing::format_price($invoice->amount), 'config' => array('step' => 'any', 'min' => 0)), 'discount' => array('id' => 'discount', 'title' => sprintf(__('Discount (%s)', 'membership2'), $currency), 'type' => MS_Helper_Html::INPUT_TYPE_NUMBER, 'value' => MS_Helper_Billing::format_price($invoice->discount), 'config' => array('step' => 'any', 'min' => 0)), 'due_date' => array('id' => 'due_date', 'title' => __('Due date', 'membership2'), 'type' => MS_Helper_Html::INPUT_TYPE_DATEPICKER, 'value' => $invoice->due_date), 'description' => array('id' => 'description', 'title' => __('Description', 'membership2'), 'type' => MS_Helper_Html::INPUT_TYPE_TEXT, 'class' => 'widefat', 'value' => $invoice->description), 'notes' => array('id' => 'notes', 'title' => __('Notes', 'membership2'), 'type' => MS_Helper_Html::INPUT_TYPE_TEXT_AREA, 'class' => 'widefat', 'value' => $invoice->get_notes_desc()), 'invoice_id' => array('id' => 'invoice_id', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $invoice->id), '_wpnonce' => array('id' => '_wpnonce', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => wp_create_nonce($this->data['action'])), 'action' => array('id' => 'action', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $this->data['action']), 'separator' => array('type' => MS_Helper_Html::TYPE_HTML_SEPARATOR), 'execute' => array('id' => 'execute', 'title' => __('Execute status change actions on Save (add/remove membership)', 'membership2'), 'type' => MS_Helper_Html::INPUT_TYPE_CHECKBOX, 'value' => true), 'cancel' => array('id' => 'cancel', 'type' => MS_Helper_Html::TYPE_HTML_LINK, 'title' => __('Cancel', 'membership2'), 'value' => __('Cancel', 'membership2'), 'url' => esc_url_raw(remove_query_arg(array('action', 'invoice_id'))), 'class' => 'wpmui-field-button button'), 'submit' => array('id' => 'submit', 'type' => MS_Helper_Html::INPUT_TYPE_SUBMIT, 'value' => __('Save Changes', 'membership2')));
     if ($invoice->id > 0) {
         $fields['user_id']['type'] = MS_Helper_Html::INPUT_TYPE_HIDDEN;
         $fields['membership_id']['type'] = MS_Helper_Html::INPUT_TYPE_HIDDEN;
         $fields['txt_membership']['value'] = $this->data['memberships'][$invoice->membership_id];
         $fields['txt_created']['value'] = MS_Helper_Period::format_date($invoice->invoice_date);
     } else {
         unset($fields['txt_user']);
         unset($fields['txt_membership']);
         unset($fields['txt_created']);
         unset($fields['txt_separator']);
     }
     return apply_filters('ms_view_billing_edit_prepare_fields', $fields, $this);
 }
 public function column_discount($item)
 {
     $html = '';
     if (MS_Addon_Coupon_Model::TYPE_VALUE == $item->discount_type) {
         $html = sprintf('%s %s', MS_Plugin::instance()->settings->currency, MS_Helper_Billing::format_price($item->discount));
     } elseif (MS_Addon_Coupon_Model::TYPE_PERCENT == $item->discount_type) {
         $html = $item->discount . ' %';
     } else {
         $html = apply_filters('ms_addon_coupon_helper_listtable_column_discount', $item->discount);
     }
     return $html;
 }
 /**
  * Sets the parent gateway of the API object.
  *
  * The parent gateway object is used to fetch the API keys.
  *
  * @since 1.0.1.0
  * @param MS_Gateway $gateway The parent gateway.
  */
 public function set_gateway($gateway)
 {
     static $Stripe_Loaded = false;
     if (!$Stripe_Loaded) {
         require_once MS_Plugin::instance()->dir . '/lib/stripe-php/lib/Stripe.php';
         do_action('ms_gateway_stripe_load_stripe_lib_after', $this);
         $Stripe_Loaded = true;
     }
     $this->_gateway = $gateway;
     $secret_key = $this->_gateway->get_secret_key();
     M2_Stripe::setApiKey($secret_key);
 }
 /**
  * Prepare html fields.
  *
  * @since  1.0.0
  *
  * @return array
  */
 function prepare_fields()
 {
     $invoice = $this->data['invoice'];
     $currency = MS_Plugin::instance()->settings->currency;
     $fields = array('txt_user' => array('id' => 'txt_user', 'title' => __('Username', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::TYPE_HTML_TEXT, 'value' => $this->data['users'][$invoice->user_id]), 'txt_membership' => array('id' => 'txt_membership', 'title' => __('Membership', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::TYPE_HTML_TEXT), 'txt_separator' => array('type' => MS_Helper_Html::TYPE_HTML_SEPARATOR), 'status' => array('id' => 'status', 'title' => __('Status', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::INPUT_TYPE_SELECT, 'field_options' => MS_Model_Invoice::get_status_types(), 'value' => $invoice->status), 'user_id' => array('id' => 'user_id', 'title' => __('Username', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::INPUT_TYPE_SELECT, 'value' => $invoice->user_id, 'field_options' => $this->data['users']), 'membership_id' => array('id' => 'membership_id', 'title' => __('Membership', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::INPUT_TYPE_SELECT, 'value' => $invoice->membership_id, 'field_options' => $this->data['memberships']), 'description' => array('id' => 'description', 'title' => __('Description', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::INPUT_TYPE_TEXT, 'value' => $invoice->description), 'amount' => array('id' => 'amount', 'title' => sprintf(__('Amount (%s)', MS_TEXT_DOMAIN), $currency), 'type' => MS_Helper_Html::INPUT_TYPE_TEXT, 'value' => $invoice->amount), 'discount' => array('id' => 'discount', 'title' => sprintf(__('Discount (%s)', MS_TEXT_DOMAIN), $currency), 'type' => MS_Helper_Html::INPUT_TYPE_TEXT, 'value' => $invoice->discount), 'due_date' => array('id' => 'due_date', 'title' => __('Due date', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::INPUT_TYPE_DATEPICKER, 'value' => $invoice->due_date), 'notes' => array('id' => 'notes', 'title' => __('Notes', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::INPUT_TYPE_TEXT_AREA, 'value' => $invoice->get_notes_desc()), 'invoice_id' => array('id' => 'invoice_id', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $invoice->id), '_wpnonce' => array('id' => '_wpnonce', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => wp_create_nonce($this->data['action'])), 'action' => array('id' => 'action', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $this->data['action']), 'separator' => array('type' => MS_Helper_Html::TYPE_HTML_SEPARATOR), 'execute' => array('id' => 'execute', 'title' => __('Execute status change actions on Save (add/remove membership)', MS_TEXT_DOMAIN), 'type' => MS_Helper_Html::INPUT_TYPE_CHECKBOX, 'value' => true), 'cancel' => array('id' => 'cancel', 'type' => MS_Helper_Html::TYPE_HTML_LINK, 'title' => __('Cancel', MS_TEXT_DOMAIN), 'value' => __('Cancel', MS_TEXT_DOMAIN), 'url' => esc_url_raw(remove_query_arg(array('action', 'invoice_id'))), 'class' => 'wpmui-field-button button'), 'submit' => array('id' => 'submit', 'type' => MS_Helper_Html::INPUT_TYPE_SUBMIT, 'value' => __('Save Changes', MS_TEXT_DOMAIN)));
     if ($invoice->id > 0) {
         $fields['user_id']['type'] = MS_Helper_Html::INPUT_TYPE_HIDDEN;
         $fields['membership_id']['type'] = MS_Helper_Html::INPUT_TYPE_HIDDEN;
         $fields['txt_membership']['value'] = $this->data['memberships'][$invoice->membership_id];
     } else {
         unset($fields['txt_user']);
         unset($fields['txt_membership']);
         unset($fields['txt_separator']);
     }
     return apply_filters('ms_view_billing_edit_prepare_fields', $fields, $this);
 }
 /**
  * Displays the settings form.
  *
  * @since  1.0.0
  * @return string
  */
 public function to_html()
 {
     if (!empty($_REQUEST['full_popup'])) {
         $show_wizard_done = true;
     } else {
         $show_wizard_done = MS_Plugin::instance()->settings->is_first_membership;
     }
     if ($show_wizard_done) {
         $this->form_type = 'full';
         $code = $this->html_full_form();
     } else {
         $this->form_type = 'short';
         $code = $this->html_short_form();
     }
     return $code;
 }
 /**
  * Get available tabs.
  *
  * @since  1.0.0
  *
  * @return array The tabs configuration.
  */
 public function get_tabs()
 {
     $tabs = array('general' => array('title' => __('General', MS_TEXT_DOMAIN)), 'shortcodes' => array('title' => __('Shortcodes', MS_TEXT_DOMAIN)), 'network' => array('title' => __('Network-Wide Protection', MS_TEXT_DOMAIN)), 'advanced' => array('title' => __('Advanced Settings', MS_TEXT_DOMAIN)), 'api' => array('title' => __('API Docs', MS_TEXT_DOMAIN), 'url' => MS_Plugin::instance()->url . 'docs/namespaces/default.html', 'target' => '_blank'));
     if (!is_multisite()) {
         unset($tabs['network']);
     }
     lib2()->array->equip_get('page');
     $def_key = MS_Controller_Plugin::MENU_SLUG . '-help';
     $page = sanitize_html_class($_GET['page'], $def_key);
     foreach ($tabs as $key => $tab) {
         if (empty($tabs[$key]['url'])) {
             $tabs[$key]['url'] = sprintf('admin.php?page=%1$s&tab=%2$s', esc_attr($page), esc_attr($key));
         }
     }
     return apply_filters('ms_controller_help_get_tabs', $tabs, $this);
 }
 /**
  * Initialize the Admin-Bar after we have determined the current user.
  *
  * @since  1.0.0
  */
 public function init_adminbar()
 {
     $this->simulate = MS_Factory::load('MS_Model_Simulate');
     // Hide WP toolbar in front end to not admin users
     if (!$this->is_admin_user() && MS_Plugin::instance()->settings->hide_admin_bar) {
         add_filter('show_admin_bar', '__return_false');
         $this->add_action('wp_before_admin_bar_render', 'customize_toolbar_front', 999);
     }
     // Customize WP toolbar for admin users
     if ($this->is_admin_user()) {
         $this->add_action('wp_before_admin_bar_render', 'customize_toolbar', 999);
         $this->add_action('add_admin_bar_menus', 'admin_bar_manager');
         $this->add_action('admin_enqueue_scripts', 'enqueue_scripts');
         $this->add_action('wp_enqueue_scripts', 'enqueue_scripts');
     }
 }
Example #10
0
    /**
     * Overrides parent's to_html() method.
     *
     * Creates an output buffer, outputs the HTML and grabs the buffer content before releasing it.
     * Creates a wrapper 'ms-wrap' HTML element to contain content and navigation. The content inside
     * the navigation gets loaded with dynamic method calls.
     * e.g. if key is 'settings' then render_settings() gets called, if 'bob' then render_bob().
     *
     * @since  1.0.0
     * @api
     *
     * @return string
     */
    public function to_html()
    {
        $form_fields = $this->prepare_fields();
        $setup_url = MS_Controller_Plugin::get_admin_url('setup');
        ob_start();
        // Render tabbed interface.
        ?>
		<div class="ms-wrap wrap">
			<form class="ms-welcome-box" action="<?php 
        echo esc_url($setup_url);
        ?>
" method="POST">
				<h2 class="ms-welcome-title">
					<?php 
        _e('Welcome!', MS_TEXT_DOMAIN);
        ?>
				</h2>

				<div class="ms-welcome-text">
					<?php 
        _e('Hello and welcome to <strong>Membership2</strong> by WPMU DEV. Please follow this simple set-up<br />wizard to help us determine the settings that are most relevant to your needs. Don\'t worry, you<br />can always change these settings in the future.', MS_TEXT_DOMAIN);
        ?>
				</div>

				<div class="ms-welcome-image-box">
					<img src="<?php 
        echo esc_attr(MS_Plugin::instance()->url);
        ?>
app/assets/images/welcome.png" class="ms-welcome-image" />
				</div>

				<?php 
        foreach ($form_fields as $field) {
            MS_Helper_Html::html_element($field);
        }
        ?>
			</form>
		</div>
		<?php 
        return ob_get_clean();
    }
 /**
  * Track wizard step.
  *
  * Save current step.
  *
  * since 1.0.0
  *
  * @param string $step Optional. The step to save. Default to current step.
  * @param boolean $end_wizard Optional. Whether end the wizard mode.
  * @return string The current step.
  */
 public function wizard_tracker($step = null, $end_wizard = false)
 {
     $settings = MS_Plugin::instance()->settings;
     if (empty($step)) {
         $step = $this->get_step();
     }
     if (MS_Plugin::is_wizard()) {
         $settings->wizard_step = $step;
         if ($end_wizard) {
             $settings->initial_setup = false;
         }
         $settings->save();
     }
     do_action('ms_controller_membership_wizard_tracker', $step, $end_wizard, $settings, $this);
 }
 /**
  * Appends classes to the HTML body that identify all memberships that the
  * current user is registered to. This allows webdesigners to adjust layout
  * or hide elements based on the membership a user has.
  *
  * @since  1.0.0
  *
  * @param  array $class Class-names to attach to the body.
  * @return array Modified class-names to attach to the body.
  */
 public function body_class($classes)
 {
     $member = MS_Model_Member::get_current_member();
     if (!$member->is_logged_in()) {
         $classes[] = 'ms-guest';
     } else {
         $classes[] = 'ms-member';
         $classes[] = 'ms-member-' . $member->id;
     }
     $info = MS_Plugin::instance()->controller->get_access_info();
     foreach ($info['memberships'] as $membership_id) {
         $classes[] = 'ms-' . absint($membership_id);
     }
     return $classes;
 }
 /**
  * Load Membership admin scripts.
  *
  * @since  1.0.0
  */
 public function enqueue_scripts()
 {
     $active_tab = $this->get_active_tab();
     do_action('ms_controller_settings_enqueue_scripts_' . $active_tab);
     $plugin_url = MS_Plugin::instance()->url;
     $version = MS_Plugin::instance()->version;
     $initial_url = MS_Controller_Plugin::get_admin_url();
     $data = array('ms_init' => array(), 'initial_url' => $initial_url);
     $data['ms_init'][] = 'view_settings';
     switch ($active_tab) {
         case self::TAB_PAYMENT:
             add_thickbox();
             $data['ms_init'][] = 'view_settings_payment';
             break;
         case self::TAB_MESSAGES:
             $data['ms_init'][] = 'view_settings_protection';
             break;
         case self::TAB_EMAILS:
             $data['ms_init'][] = 'view_settings_automated_msg';
             break;
         case self::TAB_GENERAL:
             $data['ms_init'][] = 'view_settings_setup';
             break;
     }
     lib3()->ui->data('ms_data', $data);
     wp_enqueue_script('ms-admin');
 }
 /**
  * Ajax action handler used by the transaction logs list to change a
  * transaction log entry.
  *
  * Returns a list of requested items
  *
  * @since  1.0.1.0
  */
 public function ajax_link_data_transaction()
 {
     $resp = array();
     $fields = array('get', 'for');
     if (self::validate_required($fields) && $this->verify_nonce()) {
         $type = $_POST['get'];
         $id = intval($_POST['for']);
         $settings = MS_Plugin::instance()->settings;
         if ('subscriptions' == $type) {
             $member = MS_Factory::load('MS_Model_Member', $id);
             $resp[0] = __('Select a subscription', 'membership2');
             $active = array();
             $inactive = array();
             foreach ($member->subscriptions as $subscription) {
                 if ($subscription->is_system()) {
                     continue;
                 }
                 $membership = $subscription->get_membership();
                 if ($membership->is_free()) {
                     $price = __('Free', 'membership2');
                 } else {
                     $price = sprintf('%s %s', $settings->currency, MS_Helper_Billing::format_price($membership->price));
                 }
                 $line = sprintf(__('Membership: %s, Base price: %s', 'membership2'), $membership->name, $price);
                 if ($subscription->is_expired()) {
                     $inactive[$subscription->id] = $line;
                 } else {
                     $active[$subscription->id] = $line;
                 }
             }
             if (!count($active) && !count($inactive)) {
                 $resp[0] = __('No subscriptions found', 'membership2');
             } else {
                 if (count($active)) {
                     $resp[__('Active Subscriptions', 'membership2')] = $active;
                 }
                 if (count($inactive)) {
                     $resp[__('Expired Subscriptions', 'membership2')] = $inactive;
                 }
             }
         } elseif ('invoices' == $type) {
             $subscription = MS_Factory::load('MS_Model_Relationship', $id);
             $invoices = $subscription->get_invoices();
             $resp[0] = __('Select an invoice', 'membership2');
             $unpaid = array();
             $paid = array();
             foreach ($invoices as $invoice) {
                 $line = sprintf(__('Invoice: %s from %s (%s)', 'membership2'), $invoice->get_invoice_number(), $invoice->due_date, $invoice->currency . ' ' . MS_Helper_Billing::format_price($invoice->total));
                 if ($invoice->is_paid()) {
                     $paid[$invoice->id] = $line;
                 } else {
                     $unpaid[$invoice->id] = $line;
                 }
             }
             if (!count($unpaid) && !count($paid)) {
                 $resp[0] = __('No invoices found', 'membership2');
             } else {
                 if (count($unpaid)) {
                     $resp[__('Unpaid Invoices', 'membership2')] = $unpaid;
                 }
                 if (count($paid)) {
                     $resp[__('Paid Invoices', 'membership2')] = $paid;
                 }
             }
         }
     }
     echo json_encode($resp);
     exit;
 }
 /**
  * Used when upgrading from Membership to M2. If both Membership and
  * Protected Content are installed when upgrading then the old
  * "protected-content" folder may survive the upgrade and needs to be
  * manually removed.
  *
  * @since  1.0.0
  */
 private static function remove_old_copy()
 {
     $new_dir = WP_PLUGIN_DIR . '/membership';
     $old_dir = WP_PLUGIN_DIR . '/protected-content';
     $old_plugins = array('protected-content/protected-content.php', 'membership/membershippremium.php');
     $new_plugin = plugin_basename(MS_Plugin::instance()->file);
     // Make sure that the current plugin is the official M2 one.
     if (false === strpos(MS_Plugin::instance()->dir, $new_dir)) {
         // Cancel: This plugin is not the official plugin (maybe a backup or beta version)
         if (false !== strpos(MS_Plugin::instance()->dir, $old_dir)) {
             lib3()->ui->admin_message(__('<b>Upgrade warning</b>:<br>The Membership 2 plugin is installed in an deprecated folder. Some users did report issues when the plugin is installed in this directory.<br>To fix this issue please follow these steps:<br><br>1. Delete* the old Membership Premium plugin if it is still installed.<br>2. Delete* the Membership 2 plugin.<br>3. Re-install Membership 2 from the WPMU Dashboard - your existing data is not affected by this.<br><br>*) <em>Only deactivating the plugins does not work, you have to delete them.</em>', 'membership2'), 'error');
         }
         return;
     }
     // 1. See if there is a old copy of the plugin directory. Delete it.
     if (is_dir($old_dir) && is_file($old_dir . '/protected-content.php')) {
         // Looks like the old version of this plugin is still installed. Remove it.
         try {
             unlink($old_dir . '/protected-content.php');
             array_map('unlink', glob("{$old_dir}/*.*"));
             rmdir($old_dir);
         } catch (Exception $e) {
             // Something went wrong when removing the old plugin.
         }
     }
     // 2. See if WordPress uses an old plugin in the DB. Update it.
     if (is_multisite()) {
         $global_plugins = (array) get_site_option('active_sitewide_plugins', array());
         foreach ($global_plugins as $key => $the_path) {
             if (in_array($the_path, $old_plugins)) {
                 $global_plugins[$key] = $new_plugin;
             }
         }
         update_site_option('active_sitewide_plugins', $global_plugins);
     }
     $site_plugins = (array) get_option('active_plugins', array());
     foreach ($site_plugins as $key => $the_path) {
         if (in_array($the_path, $old_plugins)) {
             $site_plugins[$key] = $new_plugin;
         }
     }
     update_option('active_plugins', $site_plugins);
 }
    public function to_html()
    {
        ob_start();
        ?>
		<div class="ms-account-wrapper">
			<?php 
        if (MS_Model_Member::is_logged_in()) {
            ?>
				<h2>
					<?php 
            _e('Invoice', MS_TEXT_DOMAIN);
            ?>
				</h2>
				<table>
					<thead>
						<tr>
							<th class="ms-col-invoice-no"><?php 
            _e('Invoice #', MS_TEXT_DOMAIN);
            ?>
</th>
							<th class="ms-col-invoice-status"><?php 
            _e('Status', MS_TEXT_DOMAIN);
            ?>
</th>
							<th class="ms-col-invoice-total"><?php 
            printf('%s (%s)', __('Total', MS_TEXT_DOMAIN), MS_Plugin::instance()->settings->currency);
            ?>
</th>
							<th class="ms-col-invoice-title"><?php 
            _e('Membership', MS_TEXT_DOMAIN);
            ?>
</th>
							<th class="ms-col-invoice-due"><?php 
            _e('Due date', MS_TEXT_DOMAIN);
            ?>
</th>
						</tr>
					</thead>
					<tbody>
					<?php 
            foreach ($this->data['invoices'] as $invoice) {
                $inv_membership = MS_Factory::load('MS_Model_Membership', $invoice->membership_id);
                $inv_classes = array('ms-invoice-' . $invoice->id, 'ms-subscription-' . $invoice->ms_relationship_id, 'ms-invoice-' . $invoice->status, 'ms-gateway-' . $invoice->gateway_id, 'ms-membership-' . $invoice->membership_id, 'ms-type-' . $inv_membership->type, 'ms-payment-' . $inv_membership->payment_type);
                ?>
						<tr class="<?php 
                echo esc_attr(implode(' ', $inv_classes));
                ?>
">
							<td class="ms-col-invoice-no"><?php 
                printf('<a href="%s">%s</a>', get_permalink($invoice->id), $invoice->get_invoice_number());
                ?>
</td>
							<td class="ms-col-invoice-status"><?php 
                echo esc_html($invoice->status_text());
                ?>
</td>
							<td class="ms-col-invoice-total"><?php 
                echo esc_html(MS_Helper_Billing::format_price($invoice->total));
                ?>
</td>
							<td class="ms-col-invoice-title"><?php 
                echo esc_html($inv_membership->name);
                ?>
</td>
							<td class="ms-col-invoice-due"><?php 
                echo esc_html(MS_Helper_Period::format_date($invoice->due_date, __('F j', MS_TEXT_DOMAIN)));
                ?>
</td>
						</tr>
					<?php 
            }
            ?>
					</tbody>
				</table>
			<?php 
        } else {
            ?>
				<?php 
            $redirect = esc_url_raw(add_query_arg(array()));
            $title = __('Your account', MS_TEXT_DOMAIN);
            echo do_shortcode("[ms-membership-login redirect='{$redirect}' title='{$title}']");
            ?>
			<?php 
        }
        ?>
		</div>
		<?php 
        $html = ob_get_clean();
        $html = apply_filters('ms_compact_code', $html);
        return $html;
    }
 /**
  * Returns the Taxamo REST API object.
  *
  * Important: All calls to `taxamo()->` functions must be wrapped in
  * try..catch because an invalid API token will result in a fatal error.
  *
  * @since  1.0.0
  * @return Taxamo
  */
 protected static function taxamo()
 {
     static $Taxamo = null;
     if (null === $Taxamo) {
         if (!class_exists('Taxamo')) {
             require_once MS_Plugin::instance()->dir . '/lib/taxamo/Taxamo.php';
         }
         // Initialize the Taxamo API connection
         $connection = new APIClient(MS_Addon_Taxamo::model()->get('private_key'), 'https://api.taxamo.com');
         // Initialize the Taxamo REST API wrapper.
         $Taxamo = new Taxamo($connection);
         // Initialize the API object.
         self::init();
     }
     return $Taxamo;
 }
    /**
     * Returns the contens of the dialog
     *
     * @since  1.0.0
     *
     * @return object
     */
    public function get_contents($data)
    {
        $member = $data['model'];
        $currency = MS_Plugin::instance()->settings->currency;
        $show_trial = MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_TRIAL);
        $all_subscriptions = MS_Model_Relationship::get_subscriptions(array('user_id' => $member->id, 'status' => 'all', 'meta_key' => 'expire_date', 'orderby' => 'meta_value', 'order' => 'DESC'));
        // Prepare the form fields.
        $inp_dialog = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => 'dialog', 'value' => 'View_Member_Dialog');
        $inp_id = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => 'member_id', 'value' => $member->id);
        $inp_nonce = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => '_wpnonce', 'value' => wp_create_nonce(self::ACTION_SAVE));
        $inp_action = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => 'dialog_action', 'value' => self::ACTION_SAVE);
        $inp_save = array('type' => MS_Helper_Html::INPUT_TYPE_SUBMIT, 'value' => __('Save', 'membership2'), 'class' => 'ms-submit-form', 'data' => array('form' => 'ms-edit-member'));
        $inp_cancel = array('type' => MS_Helper_Html::INPUT_TYPE_BUTTON, 'value' => __('Close', 'membership2'), 'class' => 'close');
        ob_start();
        ?>
		<div>
			<form class="ms-form wpmui-ajax-update ms-edit-member" data-wpmui-ajax="<?php 
        echo esc_attr('save');
        ?>
">
				<div class="ms-form wpmui-form wpmui-grid-8">
					<table class="widefat">
					<thead>
						<tr>
							<th class="column-membership">
								<?php 
        _e('Membership', 'membership2');
        ?>
							</th>
							<th class="column-status">
								<?php 
        _e('Status', 'membership2');
        ?>
							</th>
							<th class="column-start">
								<?php 
        _e('Subscribed on', 'membership2');
        ?>
							</th>
							<th class="column-expire">
								<?php 
        _e('Expires on', 'membership2');
        ?>
							</th>
							<?php 
        if ($show_trial) {
            ?>
							<th class="column-trialexpire">
								<?php 
            _e('Trial until', 'membership2');
            ?>
							</th>
							<?php 
        }
        ?>
							<th class="column-payments">
								<?php 
        _e('Payments', 'membership2');
        ?>
							</th>
						</tr>
					</thead>
					<tbody>
					<?php 
        foreach ($all_subscriptions as $subscription) {
            $membership = $subscription->get_membership();
            $payments = $subscription->get_payments();
            $num_payments = count($payments);
            $amount_payments = 0;
            foreach ($payments as $payment) {
                $amount_payments += $payment['amount'];
            }
            $subscription_info = array('subscription_id' => $subscription->id);
            $update_info = array('subscription_id' => $subscription->id, 'statuscheck' => 'yes');
            ?>
						<tr>
							<td class="column-membership">
								<?php 
            $membership->name_tag();
            ?>
							</td>
							<td class="column-status">
								<?php 
            printf('<a href="#" data-ms-dialog="View_Member_Subscription" data-ms-data="%2$s">%1$s</a>
									<a href="#" data-ms-dialog="View_Member_Subscription" data-ms-data="%3$s" title="%5$s">%4$s</a>', $subscription->status, esc_attr(json_encode($subscription_info)), esc_attr(json_encode($update_info)), '<i class="dashicons dashicons-update"></i>', __('Check and update subscription status', 'membership2'));
            ?>
							</td>
							<td class="column-start">
								<?php 
            echo $subscription->start_date;
            ?>
							</td>
							<td class="column-expire">
								<?php 
            echo $subscription->expire_date;
            ?>
							</td>
							<?php 
            if ($show_trial) {
                ?>
							<td class="column-trialexpire">
								<?php 
                if ($subscription->start_date == $subscription->trial_expire_date) {
                    echo '-';
                } else {
                    echo $subscription->trial_expire_date;
                }
                ?>
							</td>
							<?php 
            }
            ?>
							<td class="column-payments">
								<?php 
            $total = sprintf('<b>%1$s</b> (%3$s %2$s)', $num_payments, MS_Helper_Billing::format_price($amount_payments), $currency);
            printf('<a href="#" data-ms-dialog="View_Member_Payment" data-ms-data="%1$s">%2$s</a>', esc_attr(json_encode($subscription_info)), $total);
            ?>
							</td>
						</tr>
					<?php 
        }
        ?>
					</tbody>
					</table>
				</div>
				<?php 
        MS_Helper_Html::html_element($inp_id);
        MS_Helper_Html::html_element($inp_dialog);
        MS_Helper_Html::html_element($inp_nonce);
        MS_Helper_Html::html_element($inp_action);
        ?>
			</form>
			<div class="buttons">
				<?php 
        MS_Helper_Html::html_element($inp_cancel);
        // MS_Helper_Html::html_element( $inp_save );
        ?>
			</div>
		</div>
		<?php 
        $html = ob_get_clean();
        return apply_filters('ms_view_member_dialog_to_html', $html);
    }
 /**
  * Set initial protection.
  *
  * @since  1.0.0
  */
 public function protect_content()
 {
     parent::protect_content();
     // ********* COMMENTS **********
     // No comments on special pages (signup, account, ...)
     $this->add_filter('the_content', 'check_special_page');
     /*
      * We find the public comment access once.
      * This is the access ganted to guests or memberships that do not define
      * an explicit comment access rule.
      */
     if (null === self::$comment_public) {
         $base_rule = MS_Model_Membership::get_base()->get_rule($this->rule_type);
         if (null === $base_rule->get_rule_value(self::COMMENT_WRITE)) {
             self::$comment_public = self::COMMENT_WRITE;
         } elseif (null === $base_rule->get_rule_value(self::COMMENT_READ)) {
             self::$comment_public = self::COMMENT_READ;
         } else {
             self::$comment_public = self::COMMENT_NO_ACCESS;
         }
     }
     // Find the most generous comment access rule.
     $has_full = $this->get_rule_value(self::COMMENT_WRITE);
     $has_read = $this->get_rule_value(self::COMMENT_READ);
     $has_none = $this->get_rule_value(self::COMMENT_NO_ACCESS);
     if (true === $has_full) {
         // Membership allows full comment access.
         self::$comment_access = self::COMMENT_WRITE;
     } elseif (true === $has_read) {
         // Membership allows read-only access.
         if (self::$comment_access == self::COMMENT_NO_ACCESS) {
             self::$comment_access = self::COMMENT_READ;
         }
     } elseif (true === $has_none) {
         // Membership does not allow any comment access.
         // (no change, this is the default access level)
     } else {
         // This membership does not define a comment access: Use public access!
         self::$comment_access = self::$comment_public;
     }
     $this->add_action('ms_setup_protection_done', 'protect_comments');
     // ********** READ MORE **********
     $this->protection_message = MS_Plugin::instance()->settings->get_protection_message(MS_Model_Settings::PROTECTION_MSG_MORE_TAG, $this->membership_id);
     if (!parent::has_access(self::MORE_LIMIT)) {
         $this->add_filter('the_content_more_link', 'show_moretag_protection', 99, 2);
         $this->add_filter('the_content', 'replace_more_tag_content', 1);
         $this->add_filter('the_content_feed', 'replace_more_tag_content', 1);
     }
 }
 /**
  * Get a simple array of capabilties (e.g. for display in select lists)
  *
  * @since  1.0.0
  * @global array $menu
  *
  * @return array {
  *      @type string $id The id.
  *      @type string $name The name.
  * }
  */
 public function get_capabilities($args = null)
 {
     if (null === $this->_content_array) {
         $this->_content_array = array();
         $member = MS_Model_Member::get_current_member();
         $capslist = $member->wp_user->allcaps;
         $ignored_caps = array('level_10' => 1, 'level_9' => 1, 'level_8' => 1, 'level_7' => 1, 'level_6' => 1, 'level_5' => 1, 'level_4' => 1, 'level_3' => 1, 'level_2' => 1, 'level_1' => 1, 'level_0' => 1, 'administrator' => 1);
         $capslist = array_diff_assoc($capslist, $ignored_caps);
         $capslist = array_keys($capslist);
         /**
          * Exclude certain capabilities for security reasons.
          *
          * @since  1.0.0
          * @var array
          */
         $exclude = apply_filters('ms_rule_membercaps_model_exclude', array(MS_Plugin::instance()->controller->capability, 'edit_plugins', 'delete_plugins', 'edit_files', 'edit_users', 'delete_users', 'remove_users', 'promote_users', 'list_users'));
         $capslist = array_diff($capslist, $exclude);
         $this->_content_array = array_combine($capslist, $capslist);
         // Make sure the rule_value only contains valid items.
         $rule_value = array_intersect_key($this->rule_value, $this->_content_array);
         $this->rule_value = lib2()->array->get($rule_value);
         // If not visitor membership, just show Membership2
         if (!$this->get_membership()->is_base()) {
             $this->_content_array = array_intersect_key($this->_content_array, $this->rule_value);
         }
         $this->_content_array = apply_filters('ms_rule_membercaps_model_get_content_array', $this->_content_array, $this);
     }
     $contents = $this->_content_array;
     // Search the shortcode-tag...
     if (!empty($args['s'])) {
         foreach ($contents as $key => $name) {
             if (false === stripos($name, $args['s'])) {
                 unset($contents[$key]);
             }
         }
     }
     $filter = self::get_exclude_include($args);
     if (is_array($filter->include)) {
         $contents = array_intersect($contents, $filter->include);
     } elseif (is_array($filter->exclude)) {
         $contents = array_diff($contents, $filter->exclude);
     }
     // Pagination
     if (!empty($args['posts_per_page'])) {
         $total = $args['posts_per_page'];
         $offset = !empty($args['offset']) ? $args['offset'] : 0;
         $contents = array_slice($contents, $offset, $total);
     }
     return $contents;
 }
 /**
  * Verify is user is Admin user.
  *
  * @since  1.0.0
  * @api
  *
  * @param  int|false $user_id Optional. The user ID. Default to current user.
  * @param  bool $deprecated Do not use.
  * @return boolean True if user is admin.
  */
 public static function is_admin_user($user_id = false)
 {
     $cache_result = true;
     if (!isset(self::$_is_admin_user[$user_id])) {
         $is_admin = false;
         $default_user_id = null;
         if (empty($user_id)) {
             $default_user_id = $user_id;
             $user_id = self::get_user_id();
         }
         if (is_super_admin($user_id)) {
             // Superadmin always is considered admin user, no discussion...
             $is_admin = true;
         } else {
             /**
              * Use the capability defined by the main plugin controller.
              *
              * This capability defines which user is considered admin user.
              * An Admin user has full permissions to edit M2 settings.
              *
              * To modify the capability:
              *   Use filter `ms_admin_user_capability`  or
              *   define( 'MS_ADMIN_CAPABILITY', '...' )
              *
              * @var string|bool A WordPress capability or boolean false.
              */
             $controller = MS_Plugin::instance()->controller;
             if ($controller) {
                 $capability = $controller->capability;
             } else {
                 // This is used in case the function is called too early.
                 $capability = 'manage_options';
                 $cache_result = false;
             }
             if (!empty($capability)) {
                 if (empty($user_id)) {
                     $is_admin = current_user_can($capability);
                 } else {
                     $is_admin = user_can($user_id, $capability);
                 }
             }
             $is_admin = apply_filters('ms_model_member_is_admin_user', $is_admin, $user_id, $capability);
         }
         if ($cache_result) {
             self::$_is_admin_user[$user_id] = $is_admin;
             if (null !== $default_user_id) {
                 self::$_is_admin_user[$default_user_id] = $is_admin;
             }
         }
     } else {
         $is_admin = self::$_is_admin_user[$user_id];
     }
     return $is_admin;
 }
 /**
  * Register styles that are used on the front-end.
  *
  * @since  1.0.0
  */
 public function register_public_styles()
 {
     $plugin_url = MS_Plugin::instance()->url;
     $version = MS_Plugin::instance()->version;
     // The main plugin style.
     wp_register_style('ms-styles', $plugin_url . 'app/assets/css/ms-public.css', array(), $version);
 }
 public function column_price($item, $column_name)
 {
     $html = '';
     if (!$item->is_system()) {
         if (!$item->is_free()) {
             $html = sprintf('<span class="ms-currency">%1$s</span> <span class="ms-price">%2$s</span> (<span class="ms-payment">%3$s</span>)', MS_Plugin::instance()->settings->currency_symbol, MS_Helper_Billing::format_price($item->price), $item->get_payment_type_desc());
             $html = '<span class="ms-bold">' . $html . '</span>';
         } else {
             $html = sprintf('<span class="ms-bold">%1$s</span> (<span class="ms-payment">%2$s</span>)', __('Free', 'membership2'), $item->get_payment_type_desc());
         }
         $followup = MS_Factory::load('MS_Model_Membership', $item->on_end_membership_id);
         if ($followup->is_valid()) {
             $html .= '<div class="ms-followup">' . sprintf(__('Follow with: %1$s', 'membership2'), '<span class="ms-color" style="background:' . $followup->get_color() . '">&nbsp;</span>' . $followup->name) . '</div>';
         }
     }
     return $html;
 }
 /**
  * Load taxamo scripts.
  *
  * @since  1.0.0
  * @param  MS_Model_Invoice $invoice Optional. The invoice to edit.
  */
 public function tax_editor($invoice)
 {
     static $Done = false;
     // Only one tax-editor is possible per page.
     if ($Done) {
         return;
     }
     $Done = true;
     $this->add_action('wp_footer', 'tax_editor_footer');
     $plugin_url = MS_Plugin::instance()->url;
     wp_enqueue_style('ms-addon-taxamo', $plugin_url . '/app/addon/taxamo/assets/css/taxamo.css');
     wp_enqueue_script('ms-addon-taxamo', $plugin_url . '/app/addon/taxamo/assets/js/taxamo.js', array('jquery'));
     $view = MS_Factory::load('MS_Addon_Taxamo_Userprofile');
     $view->data = apply_filters('ms_addon_taxamo_editor_data', array('invoice' => $invoice), $this);
     self::$footer_html .= '<div id="ms-taxamo-wrapper">' . $view->to_html() . '</div>';
     do_action('ms_addon_taxamo_enqueue_scripts', $this);
 }
Example #25
0
 /**
  * Returns singleton instance of the plugin.
  *
  * @since  1.0.0
  *
  * @static
  * @access public
  *
  * @return MS_Plugin
  */
 public static function instance()
 {
     if (!self::$instance) {
         self::$instance = new MS_Plugin();
         self::$instance = apply_filters('ms_plugin_instance', self::$instance);
     }
     return self::$instance;
 }
 /**
  * Show no access image.
  *
  * @since  1.0.0
  */
 private function show_no_access_image()
 {
     $no_access_file = apply_filters('ms_rule_media_model_show_no_access_image_path', MS_Plugin::instance()->dir . 'app/assets/images/no-access.png');
     $this->output_file($no_access_file);
     do_action('ms_rule_show_no_access_image_after', $this);
 }
 /**
  * Associate a javascript file with the new TinyMCE button.
  *
  * Hooks Filters:
  * - mce_external_plugins
  *
  * @since  1.0.0
  *
  * @param  array $plugin_array List of default TinyMCE plugin scripts.
  * @return array Updated list of TinyMCE plugin scripts.
  */
 public static function add_variables_plugin($plugin_array)
 {
     $plugin_url = MS_Plugin::instance()->url;
     // This is a dummy reference (ms-admin.js is always loaded)!
     // Actually this line would not be needed, but WordPress will not show
     // our button when this is missing...
     $plugin_array['ms_variable'] = $plugin_url . 'app/assets/js/ms-admin.js';
     return $plugin_array;
 }
 /**
  * Load the Mailchimp API
  *
  * @since  1.0.0
  *
  * @return M2_Mailchimp Object
  */
 public static function load_mailchimp_api()
 {
     if (empty(self::$mailchimp_api)) {
         $options = apply_filters('ms_addon_mailchimp_load_mailchimp_api_options', array('timeout' => false, 'ssl_verifypeer' => false, 'ssl_verifyhost' => false, 'ssl_cainfo' => false, 'debug' => false));
         if (!class_exists('Mailchimp')) {
             require_once MS_Plugin::instance()->dir . '/lib/mailchimp-api/Mailchimp.php';
         }
         $api = new M2_Mailchimp(self::$settings->get_custom_setting('mailchimp', 'api_key'), $options);
         // Pinging the server
         $ping = $api->helper->ping();
         if (is_wp_error($ping)) {
             throw new Exception($ping);
         }
         self::$mailchimp_api = $api;
     }
     return self::$mailchimp_api;
 }
    public function to_html()
    {
        /**
         * Provide a customized invoice.
         *
         * @since  1.0.0
         */
        $html = apply_filters('ms_shortcode_custom_invoice', '', $this->data);
        if (!empty($html)) {
            return $html;
        } else {
            $html = '';
        }
        $invoice = $this->data['invoice'];
        $member = $this->data['member'];
        $subscription = $this->data['ms_relationship'];
        $membership = $this->data['membership'];
        $gateway = $this->data['gateway'];
        $is_free = false;
        $invoice_number = $invoice->get_invoice_number();
        $inv_title = sprintf('<a href="%s">%s</a>', get_permalink($invoice->id), esc_html(__('Invoice ', MS_TEXT_DOMAIN) . $invoice_number));
        if ($invoice->amount > 0) {
            $inv_amount = sprintf('%1$s %2$s', $invoice->currency, MS_Helper_Billing::format_price($invoice->amount));
        } else {
            $inv_amount = __('Free', MS_TEXT_DOMAIN);
            $is_free = true;
        }
        if ($invoice->tax) {
            $inv_taxes = sprintf('%s %s', $invoice->currency, MS_Helper_Billing::format_price($invoice->tax));
        } else {
            $inv_taxes = '';
        }
        if ($invoice->discount) {
            $inv_discount = sprintf('%s -%s', $invoice->currency, MS_Helper_Billing::format_price($invoice->discount));
        } else {
            $inv_discount = '';
        }
        if ($invoice->pro_rate) {
            $inv_pro_rate = sprintf('%s -%s', $invoice->currency, MS_Helper_Billing::format_price($invoice->pro_rate));
        } else {
            $inv_pro_rate = '';
        }
        $inv_total = sprintf('%s %s', $invoice->currency, MS_Helper_Billing::format_price($invoice->total));
        $inv_title = apply_filters('ms_invoice_title', $inv_title, $invoice);
        $inv_from = apply_filters('ms_invoice_sender', MS_Plugin::instance()->settings->invoice_sender_name, $invoice);
        $inv_to = apply_filters('ms_invoice_recipient', $member->username, $invoice, $member);
        $inv_status = apply_filters('ms_invoice_status', $invoice->status_text(), $invoice);
        $inv_item_name = apply_filters('ms_invoice_item_name', $membership->name, $invoice, $membership);
        $inv_amount = apply_filters('ms_invoice_amount', $inv_amount, $invoice);
        $inv_taxes = apply_filters('ms_invoice_taxes', $inv_taxes, $invoice);
        $inv_discount = apply_filters('ms_invoice_discount', $inv_discount, $invoice);
        $inv_pro_rate = apply_filters('ms_invoice_pro_rate', $inv_pro_rate, $invoice);
        $inv_total = apply_filters('ms_invoice_total', $inv_total, $invoice);
        $inv_details = apply_filters('ms_invoice_description', $invoice->description, $invoice, null);
        $inv_date = apply_filters('ms_invoice_date', MS_Helper_Period::format_date($invoice->invoice_date), $invoice, null);
        $inv_due_date = apply_filters('ms_invoice_due_date', MS_Helper_Period::format_date($invoice->due_date), $invoice, null);
        if ($invoice->uses_trial) {
            $trial_date = apply_filters('ms_invoice_trial_date', MS_Helper_Period::get_period_desc($membership->trial_period, true), $trial_invoice, $invoice);
            $trial_date .= sprintf(' <small>(%s %s)</small>', __('ends on', MS_TEXT_DOMAIN), MS_Helper_Period::format_date($invoice->trial_ends));
        } else {
            $trial_date = '';
        }
        ob_start();
        ?>
		<div class="entry-content ms-invoice" id="invoice">
			<?php 
        /**
         * We hardcode the CSS styles into this file, because the shortcode
         * is also used in Emails, which usually do not load remote CSS
         * files by default...
         */
        ?>
			<style>
			#invoice table, th, td { margin: 0; font-size: 14px; }
			#invoice table { padding: 0; width: 520px; border: 1px solid #DDD; background-color: #FFF; box-shadow: 0 1px 8px #F0F0F0; }
			#invoice th, td { border: 0; padding: 8px; }
			#invoice th { font-weight: bold; text-align: left; text-transform: none; font-size: 13px; }
			#invoice tr.alt { background-color: #F9F9F9; }
			#invoice tr.sep th,
			#invoice tr.sep td { border-top: 1px solid #DDD; padding-top: 16px; }
			#invoice tr.space th,
			#invoice tr.space td { padding-bottom: 16px; }
			#invoice tr.ms-inv-sep th,
			#invoice tr.ms-inv-sep td { line-height: 1px; height: 1px; padding: 0; border-bottom: 1px solid #DDD; background-color: #F9F9F9; }
			#invoice .ms-inv-total .ms-inv-price { font-weight: bold; font-size: 18px; text-align: right; }
			#invoice h2 { text-align: right; padding: 10px 10px 0 0; }
			#invoice h2 a { color: #000; }
			<?php 
        do_action('ms_invoice_css');
        ?>
			</style>

			<div class="ms-invoice-details ms-status-<?php 
        echo esc_attr($invoice->status);
        ?>
">
				<table class="ms-purchase-table">
					<tr class="ms-inv-title">
						<td colspan="2"><h2><?php 
        echo $inv_title;
        ?>
</h2></td>
					</tr>

					<?php 
        if (!empty($inv_from)) {
            ?>
						<tr class="ms-inv-from">
							<th><?php 
            _e('Sender', MS_TEXT_DOMAIN);
            ?>
</th>
							<td class="ms-inv-text"><?php 
            echo $inv_from;
            ?>
</td>
						</tr>
					<?php 
        }
        ?>

					<tr class="ms-inv-to">
						<th><?php 
        _e('Invoice to', MS_TEXT_DOMAIN);
        ?>
</th>
						<td class="ms-inv-text"><?php 
        echo $inv_to;
        ?>
</td>
					</tr>
					<tr class="ms-inv-invoice-date">
						<th><?php 
        _e('Invoice date', MS_TEXT_DOMAIN);
        ?>
</th>
						<td class="ms-inv-date"><?php 
        echo $inv_date;
        ?>
</td>
					</tr>
					<?php 
        if (!empty($trial_date)) {
            ?>
						<tr class="ms-inv-trial-end-date">
							<th><?php 
            _e('Trial period', MS_TEXT_DOMAIN);
            ?>
</th>
							<td class="ms-inv-date"><?php 
            echo $trial_date;
            ?>
</td>
						</tr>
					<?php 
        }
        ?>
					<tr class="ms-inv-status space">
						<th><?php 
        _e('Status', MS_TEXT_DOMAIN);
        ?>
</th>
						<td class="ms-inv-text"><?php 
        echo $inv_status;
        ?>
</td>
					</tr>
					<tr class="ms-inv-item-name alt sep">
						<th><?php 
        _e('Name', MS_TEXT_DOMAIN);
        ?>
</th>
						<td class="ms-inv-text"><?php 
        echo $inv_item_name;
        ?>
</td>
					</tr>

					<?php 
        if (!empty($inv_details)) {
            ?>
					<tr class="ms-inv-description alt">
						<th><?php 
            _e('Description', MS_TEXT_DOMAIN);
            ?>
</th>
						<td class="ms-inv-text"><?php 
            echo $inv_details;
            ?>
</td>
					</tr>
					<?php 
        }
        ?>

					<tr class="ms-inv-amount alt space">
						<th><?php 
        _e('Amount', MS_TEXT_DOMAIN);
        ?>
</th>
						<td class="ms-inv-price"><?php 
        echo $inv_amount;
        ?>
</td>
					</tr>

					<?php 
        $sep = 'sep';
        ?>

					<?php 
        if (!empty($inv_discount)) {
            ?>
						<tr class="ms-inv-discount <?php 
            echo esc_attr($sep);
            $sep = '';
            ?>
">
							<th><?php 
            _e('Coupon discount', MS_TEXT_DOMAIN);
            ?>
</th>
							<td class="ms-inv-price"><?php 
            echo $inv_discount;
            ?>
</td>
						</tr>
					<?php 
        }
        ?>

					<?php 
        if (!empty($inv_pro_rate)) {
            ?>
						<tr class="ms-inv-pro-rate <?php 
            echo esc_attr($sep);
            $sep = '';
            ?>
">
							<th><?php 
            _e('Pro rate discount', MS_TEXT_DOMAIN);
            ?>
</th>
							<td class="ms-inv-price"><?php 
            echo $inv_pro_rate;
            ?>
</td>
						</tr>
					<?php 
        }
        ?>

					<?php 
        if (!empty($inv_taxes)) {
            ?>
						<tr class="ms-inv-tax <?php 
            echo esc_attr($sep);
            $sep = '';
            ?>
">
							<th><?php 
            printf(__('Taxes %s', MS_TEXT_DOMAIN), '<small>(' . $invoice->tax_name . ')</small>');
            ?>
</th>
							<td class="ms-inv-price"><?php 
            echo $inv_taxes;
            ?>
</td>
						</tr>
					<?php 
        }
        ?>

					<?php 
        if (!$is_free) {
            ?>
						<tr class="ms-inv-due-date <?php 
            echo esc_attr($sep);
            $sep = '';
            ?>
">
							<th><?php 
            _e('Payment due', MS_TEXT_DOMAIN);
            ?>
</th>
							<td class="ms-inv-date"><?php 
            echo $inv_due_date;
            ?>
</td>
						</tr>
					<?php 
        }
        ?>
					<tr class="ms-inv-total <?php 
        echo esc_attr($sep);
        $sep = '';
        ?>
">
						<th><?php 
        _e('Total', MS_TEXT_DOMAIN);
        ?>
</th>
						<td class="ms-inv-price"><?php 
        echo $inv_total;
        ?>
</td>
					</tr>

					<?php 
        $show_button = lib2()->is_true($this->data['pay_button']);
        if ($invoice->is_paid()) {
            // Invoice is already paid. We don't need a payment
            // button...
            $show_button = false;
        }
        if ($show_button) {
            ?>
						<tr class="ms-inv-sep sep"><td colspan="2"></td></tr>
						<?php 
            do_action('ms_view_shortcode_invoice_purchase_button', $subscription, $invoice);
        }
        ?>
				</table>
			</div>
		</div>
		<?php 
        $html = ob_get_clean();
        $html = apply_filters('ms_compact_code', $html);
        return apply_filters('ms_shortcode_invoice', $html, $this->data);
    }
 /**
  * Enqueue admin scripts in the membership settings screen.
  *
  * @since  1.0.1.0
  */
 public function enqueue_membership_scripts()
 {
     $addon_url = MS_Plugin::instance()->url . '/app/addon/attributes/';
     lib3()->ui->add($addon_url . 'assets/css/attributes.css');
 }