/** * Toggle whether renewal discounts should be enabled globally. * * @param bool $enable */ protected function _toggle_global_renewal_discount($enable) { $options = it_exchange_get_option('addon_itelic', true, true); $options['enable-renewal-discounts'] = $enable; it_exchange_save_option('addon_itelic', $options); it_exchange_get_option('addon_itelic', true, true); }
/** * Get information about the licensing add-on. */ public function info() { $settings = it_exchange_get_option('addon_itelic'); if ($settings['renewal-discount-type'] == 'percent') { $discount = $settings['renewal-discount-amount'] . '%'; } else { $discount = it_exchange_format_price($settings['renewal-discount-amount']); } $info = array('version' => ITELIC\Plugin::VERSION, 'online_software_enabled' => $settings['sell-online-software'] ? 'yes' : 'no', 'remote_activation_enabled' => $settings['enable-remote-activation'] ? 'yes' : 'no', 'remote_deactivation_enabled' => $settings['enable-remote-deactivation'] ? 'yes' : 'no', 'renewal_discounts_enabled' => $settings['enable-renewal-discounts'] ? 'yes' : 'no', 'renewal_discount' => $discount, 'renewal_discount_expiry' => sprintf("%d days", $settings['renewal-discount-expiry'])); $args = array('fields' => array_keys($info)); $formatter = new \WP_CLI\Formatter($args); $formatter->display_item($info); }
/** * Check if the discount is disabled for this product. * * @since 1.0 * * @return bool */ public function is_disabled() { $options = it_exchange_get_option('addon_itelic'); if (!empty($this->feature_data['override'])) { return false; } if (!empty($this->feature_data['disable'])) { return true; } if (!$options['enable-renewal-discounts']) { return true; } return false; }
/** * Do custom initialization. */ public function setUp() { parent::setUp(); it_exchange_temporarily_load_addon('guest-checkout'); it_exchange_temporarily_load_addon('digital-downloads-product-type'); it_exchange_add_feature_support_to_product_type('recurring-payments', 'digital-downloads-product-type'); $null = null; $this->exchange_admin = new IT_Exchange_Admin($null); it_exchange_save_option('settings_general', $this->exchange_admin->set_general_settings_defaults(array())); it_exchange_get_option('settings_general', true); $this->product_factory = new ITELIC_UnitTest_Factory_For_Products(); $this->key_factory = new ITELIC_UnitTest_Factory_For_Keys($this->factory); $this->activation_factory = new ITELIC_UnitTest_Factory_For_Activations($this->factory); $this->release_factory = new ITELIC_UnitTest_Factory_For_Releases($this->factory); $this->update_factory = new ITELIC_UnitTest_Factory_For_Updates($this->factory); WP_Mock::setUp(); }
/** * Get the chart for this report. * * @since 1.0 * * @param string $date_type * @param int $product * * @return Base */ public function get_chart($date_type = 'this_year', $product = 0) { $start = date('Y-m-d H:i:s', $this->convert_date($date_type)); $end = date('Y-m-d H:i:s', $this->convert_date($date_type, true)); $grouping = self::get_grouping_for_date_type($date_type); $sql = self::get_group_by($grouping, 'r.renewal_date'); $group = $sql['group']; $per = $sql['per']; if ($per) { $per .= ' AS d, '; } if ($group) { $group = "GROUP BY {$group}"; } /** * @var \wpdb $wpdb */ global $wpdb; $rtn = Manager::get('itelic-renewals')->get_table_name($wpdb); $ktn = Manager::get('itelic-keys')->get_table_name($wpdb); if ($product) { $raw = "SELECT {$per}SUM(revenue) as c FROM {$rtn} r JOIN {$ktn} k ON(k.lkey = r.lkey AND k.product = %d) WHERE r.renewal_date BETWEEN %s AND %s"; $raw .= $group; $revenue = $wpdb->get_results($wpdb->prepare($raw, $product, $start, $end)); } else { $raw = "SELECT {$per}SUM(revenue) as c FROM {$rtn} r WHERE r.renewal_date BETWEEN %s AND %s"; $raw .= $group; $revenue = $wpdb->get_results($wpdb->prepare($raw, $start, $end)); } $revenue = self::fill_gaps(self::translate_results($revenue), $start, $end, $grouping); $labels = self::get_labels($revenue, $date_type); $before = $after = ''; $settings = it_exchange_get_option('settings_general'); $currency = html_entity_decode(it_exchange_get_currency_symbol($settings['default-currency'])); if ('after' === $settings['currency-symbol-position']) { $after = $currency; } else { $before = $currency; } $chart = new Line($labels, 600, 200, array('responsive' => true, 'tooltipTemplate' => "{$before}<%= value %>{$after}")); $chart->add_data_set(array_values($revenue), __("Revenue", Plugin::SLUG), array('fillColor' => "rgba(140,197,62,0.2)", 'strokeColor' => "rgba(140,197,62,1)", 'pointColor' => "rgba(140,197,62,1)", 'pointStrokeColor' => "#fff", 'pointHighlightFill' => "#fff", 'pointHighlightStroke' => "rgba(140,197,62,1)")); return $chart; }
/** * Create a license key. * * @api * * @param array $args { * * @type string $key The license key to be used. If empty, one will be * generated. * @type int $transaction Transaction ID. If empty, one will be manually * generated * @type int $product Product ID. * @type int $customer Customer ID. * @type string $status The key's status. Accepts 'active', 'expired', * 'disabled' * @type float $paid If manually generating a transaction, the amount * paid. * @type int $limit Activation limit. * @type string $expires Expiration date. Pass null or empty string for * forever. * @type string $date When the transaction occurred. GMT. * } * * @return \ITELIC\Key|WP_Error */ function itelic_create_key($args) { $defaults = array('key' => '', 'transaction' => '', 'product' => '', 'customer' => '', 'status' => '', 'paid' => ''); $args = ITUtility::merge_defaults($args, $defaults); $product = itelic_get_product($args['product']); if (!$product->has_feature('licensing')) { return new WP_Error('invalid_product', __("Product does not have licensing enabled.", \ITELIC\Plugin::SLUG)); } $customer = it_exchange_get_customer($args['customer']); if (!$customer) { return new WP_Error('invalid_customer', __("Invalid customer", \ITELIC\Plugin::SLUG)); } $transaction = it_exchange_get_transaction($args['transaction']); if (!$args['transaction']) { if (!function_exists('it_exchange_manual_purchases_addon_transaction_uniqid')) { return new WP_Error('no_manual_purchases', __("Manual purchases add-on is not installed.", \ITELIC\Plugin::SLUG)); } // Grab default currency $settings = it_exchange_get_option('settings_general'); $currency = $settings['default-currency']; $description = array(); $product_id = $product->ID; $itemized_data = apply_filters('it_exchange_add_itemized_data_to_cart_product', array(), $product_id); if (!is_serialized($itemized_data)) { $itemized_data = maybe_serialize($itemized_data); } $key = $product_id . '-' . md5($itemized_data); $products[$key]['product_base_price'] = $product->get_feature('base-price'); $products[$key]['product_subtotal'] = $products[$key]['product_base_price']; //need to add count $products[$key]['product_name'] = get_the_title($product_id); $products[$key]['product_id'] = $product_id; $products[$key]['count'] = 1; $description[] = $products[$key]['product_name']; $description = apply_filters('it_exchange_get_cart_description', join(', ', $description), $description); // Package it up and send it to the transaction method add-on $total = empty($args['paid']) ? 0 : it_exchange_convert_to_database_number($args['paid']); $object = new stdClass(); $object->total = number_format(it_exchange_convert_from_database_number($total), 2, '.', ''); $object->currency = $currency; $object->description = $description; $object->products = $products; remove_action('it_exchange_add_transaction_success', 'ITELIC\\on_add_transaction_generate_license_keys'); $uniquid = it_exchange_manual_purchases_addon_transaction_uniqid(); $txn_args = array(); if (isset($args['date'])) { $date = \ITELIC\make_date_time($args['date']); $txn_args['post_date'] = \ITELIC\convert_gmt_to_local($date)->format('Y-m-d H:i:s'); $txn_args['post_date_gmt'] = $date->format('Y-m-d H:i:s'); } $tid = it_exchange_add_transaction('manual-purchases', $uniquid, 'Completed', $customer->id, $object, $txn_args); add_action('it_exchange_add_transaction_success', 'ITELIC\\on_add_transaction_generate_license_keys'); $transaction = it_exchange_get_transaction($tid); } $factory = new \ITELIC\Key\Factory($product, $customer, $transaction); $key = \ITELIC\generate_key_for_transaction_product($transaction, $product, $factory, $args['status'], $args['key']); if (isset($args['limit'])) { if (empty($args['limit']) || $args['limit'] == '-') { $limit = ''; } else { $limit = $args['limit']; } $key->set_max($limit); } if (isset($args['expires'])) { if (is_string($args['expires'])) { $expires = \ITELIC\make_date_time($args['expires']); } else { $expires = $args['expires']; } if (!$expires instanceof DateTime) { $expires = null; } $key->set_expires($expires); } return $key; }
/** * Return the product's features * * @since 1.0 * * @param mixed $existing the values passed in by the WP Filter API. * Ignored here. * @param integer $product_id the WordPress post ID * @param array $options * * @return string product feature */ public function get_feature($existing, $product_id, $options = array()) { $settings = it_exchange_get_option('addon_itelic'); $defaults = array('enabled' => false, 'online-software' => $settings['sell-online-software'], 'limit' => '', 'key-type' => '', 'update-file' => '', 'version' => '', 'enabled_variant_activations' => false, 'activation_variant' => array()); $values = get_post_meta($product_id, '_it_exchange_itelic_feature', true); $raw_meta = \ITUtility::merge_defaults($values, $defaults); if (!function_exists('it_exchange_variants_addon_create_inital_presets')) { $raw_meta['enabled_variant_activations'] = false; } if (!isset($options['field'])) { // if we aren't looking for a particular field return $raw_meta; } if ($options['field'] == 'limit' && isset($options['for_hash'])) { $hash = $options['for_hash']; if (isset($raw_meta['activation_variant'][$hash])) { return $raw_meta['activation_variant'][$hash]; } else { $atts = it_exchange_get_variant_combo_attributes_from_hash($product_id, $hash); $alt_hashes = it_exchange_addon_get_selected_variant_alts($atts['combo'], $product_id); foreach ($alt_hashes as $alt_hash) { if (isset($raw_meta['activation_variant'][$alt_hash])) { return $raw_meta['activation_variant'][$alt_hash]; } } return null; } } $field = $options['field']; if (isset($raw_meta[$field])) { // if the field exists with that name just return it return $raw_meta[$field]; } else { if (strpos($field, ".") !== false) { // if the field name was passed using array dot notation $pieces = explode('.', $field); $context = $raw_meta; foreach ($pieces as $piece) { if (!is_array($context) || !array_key_exists($piece, $context)) { // error occurred return null; } $context =& $context[$piece]; } return $context; } else { return null; // we didn't find the data specified } } }
/** * Create a renewal transaction key. * * @api * * @param array $args { * * @type string $key The license key to be used. If empty, one will be * generated. * @type float $paid If manually generating a transaction, the amount paid. * @tpye string $date When the transaction occurred. GMT. * } * * @return IT_Exchange_Transaction */ function itelic_create_renewal_transaction($args) { $defaults = array('key' => '', 'paid' => '', 'date' => ''); $args = ITUtility::merge_defaults($args, $defaults); $key = itelic_get_key($args['key']); if (!$key) { return new WP_Error('invalid_key', __("Invalid key", \ITELIC\Plugin::SLUG)); } $product = $key->get_product(); if (!function_exists('it_exchange_manual_purchases_addon_transaction_uniqid')) { return new WP_Error('no_manual_purchases', __("Manual purchases add-on is not installed.", \ITELIC\Plugin::SLUG)); } // Grab default currency $settings = it_exchange_get_option('settings_general'); $currency = $settings['default-currency']; $description = array(); $product_id = $product->ID; $itemized_data = apply_filters('it_exchange_add_itemized_data_to_cart_product', array(), $product_id); if (!is_serialized($itemized_data)) { $itemized_data = maybe_serialize($itemized_data); } $i = $product_id . '-' . md5($itemized_data); $discounted = new \ITELIC\Renewal\Discount($key); $discounted = $discounted->get_discount_price(); $products[$i]['product_base_price'] = $discounted; $products[$i]['product_subtotal'] = $products[$i]['product_base_price']; //need to add count $products[$i]['product_name'] = get_the_title($product_id); $products[$i]['product_id'] = $product_id; $products[$i]['count'] = 1; $description[] = $products[$i]['product_name']; $description = apply_filters('it_exchange_get_cart_description', join(', ', $description), $description); // Package it up and send it to the transaction method add-on $total = empty($args['paid']) ? $discounted : it_exchange_convert_to_database_number($args['paid']); $object = new stdClass(); $object->total = number_format(it_exchange_convert_from_database_number($total), 2, '.', ''); $object->currency = $currency; $object->description = $description; $object->products = $products; remove_action('it_exchange_add_transaction_success', 'ITELIC\\renew_key_on_renewal_purchase'); $uniquid = it_exchange_manual_purchases_addon_transaction_uniqid(); $txn_args = array(); if (isset($args['date'])) { $date = \ITELIC\make_date_time($args['date']); $txn_args['post_date'] = \ITELIC\convert_gmt_to_local($date)->format('Y-m-d H:i:s'); $txn_args['post_date_gmt'] = $date->format('Y-m-d H:i:s'); } $customer = $key->get_customer()->id; $tid = it_exchange_add_transaction('manual-purchases', $uniquid, 'Completed', $customer, $object, $txn_args); add_action('it_exchange_add_transaction_success', 'ITELIC\\renew_key_on_renewal_purchase'); return it_exchange_get_transaction($tid); }
/** * Display a notice to register this add-on. * * @since 1.0 */ public function display_register_notice() { $options = it_exchange_get_option('addon_itelic'); if (!empty($options['license']) && !empty($options['activation'])) { return; } $ID = self::ID; echo '</tr><tr class="plugin-update-tr"><td colspan="3" class="plugin-update"><div class="update-message">'; echo sprintf(esc_html__('%sRegister%s this add-on to receive access to automatic upgrades and support. Need a license key? %sPurchase one now%s.', self::SLUG), '<a href="' . admin_url() . 'admin.php?page=it-exchange-addons&add-on-settings=licensing">', '</a>', "<a href=\"https://ironbounddesigns.com?p={$ID}\">", '</a>'); echo '</div></td>'; }
/** * Render the page. * * @since 1.0 */ public function render() { $df = it_exchange_php_date_format_to_jquery_datepicker_format(get_option('date_format')); $options = it_exchange_get_option('settings_general'); $position = $options['currency-symbol-position']; $decimals = $options['currency-decimals-separator']; $thousands = $options['currency-thousands-separator']; $symbol = it_exchange_get_currency_symbol($options['default-currency']); $form = \ITUtility::merge_defaults($_POST, array('product' => '', 'customer' => '', 'username' => '', 'email' => '', 'first' => '', 'last' => '', 'activations' => '', 'expiration' => '', 'license' => '', 'paid' => '', 'customer-type' => 'existing')); ?> <form method="POST" action="<?php echo esc_attr(add_query_arg('view', 'add-new', Dispatch::get_tab_link('licenses'))); ?> "> <div class="main-editor"> <?php do_action('itelic_add_new_license_screen_before_steps'); ?> <ol> <?php do_action('itelic_add_new_license_screen_begin_steps'); ?> <li> <label for="product"><?php _e("Select a Product", Plugin::SLUG); ?> </label> <div class="product-container"> <select id="product" name="product"> <?php foreach ($this->products as $product) { ?> <option value="<?php echo $product->ID; ?> " <?php selected($form['product'], $product->ID); ?> > <?php echo $product->post_title; ?> </option> <?php } ?> </select> </div> </li> <li> <fieldset id="customer-type"> <label><?php _e("Select a Customer", Plugin::SLUG); ?> </label> <div class="new-customer-container"> <p> <input type="radio" id="new-customer" name="customer-type" value="new" <?php checked($form['customer-type'], 'new'); ?> > <label for="new-customer"><?php _e("New Customer", Plugin::SLUG); ?> </label> </p> </div> <div class="existing-customer-container"> <p> <input type="radio" id="existing-customer" name="customer-type" value="existing" <?php checked($form['customer-type'], 'existing'); ?> > <label for="existing-customer"><?php _e("Existing Customer", Plugin::SLUG); ?> </label> </p> </div> </fieldset> <fieldset class="new-customer-form <?php echo $form['customer-type'] == 'new' ? '' : 'hide-if-js'; ?> "> <p> <label for="username"><?php _e("Username", Plugin::SLUG); ?> </label> <input type="text" id="username" name="username" value="<?php echo $form['username']; ?> "> </p> <p> <label for="email"><?php _e("Email", Plugin::SLUG); ?> </label> <input type="email" id="email" name="email" value="<?php echo $form['email']; ?> "> </p> <p> <label for="first"><?php _e("First Name", Plugin::SLUG); ?> </label> <input type="text" id="first" name="first" value="<?php echo $form['first']; ?> "> </p> <p> <label for="last"><?php _e("Last Name", Plugin::SLUG); ?> </label> <input type="text" id="last" name="last" value="<?php echo $form['last']; ?> "> </p> </fieldset> <fieldset class="existing-customer-form <?php echo $form['customer-type'] == 'existing' ? '' : 'hide-if-js'; ?> "> <p> <label for="customer" class="screen-reader-text"><?php _e('Customer', Plugin::SLUG); ?> </label> <select id="customer" name="customer"> <?php foreach (get_users() as $user) { ?> <option value="<?php echo $user->ID; ?> " <?php selected($form['customer'], $user->ID); ?> > <?php echo $user->user_login; ?> </option> <?php } ?> </select> </p> </fieldset> </li> <li> <div class="activations-container"> <label for="activations"><?php _e("Activation Limit", Plugin::SLUG); ?> </label> <input type="number" id="activations" name="activations" min="0" value="<?php echo $form['activations']; ?> "> <p class="description"><?php _e("Leave blank for unlimited activations."); ?> </p> </div> </li> <li> <div class="expiration-container"> <label for="expiration"><?php _e("Expiration Date", Plugin::SLUG); ?> </label> <input type="date" id="expiration" name="expiration" value="<?php echo $form['expiration']; ?> " data-format="<?php echo esc_attr($df); ?> "> </div> </li> <li> <div class="key-container"> <label for="license"><?php _e('License Key', Plugin::SLUG); ?> </label> <p> <a href="javascript:" id="trigger-manual-key" class="<?php echo empty($form['license']) ? '' : 'hide-if-js'; ?> "> <?php _e("Set the license key manually.", Plugin::SLUG); ?> </a> <a href="javascript:" id="trigger-automatic-key" class="<?php echo empty($form['license']) ? 'hide-if-js' : ''; ?> "> <?php _e("Let Exchange automatically generate a license key for you.", Plugin::SLUG); ?> </a> </p> <input type="text" name="license" id="license" value="<?php echo $form['license']; ?> " class="<?php echo empty($form['license']) ? 'hide-if-js' : ''; ?> "> </div> </li> <li> <div class="paid-container"> <label for="paid"><?php _e("Amount Paid", Plugin::SLUG); ?> </label> <input type="text" name="paid" id="paid" value="<?php echo $form['paid']; ?> " data-symbol="<?php echo $symbol; ?> " data-symbol-position="<?php echo $position; ?> " data-thousands-separator="<?php echo $thousands; ?> " data-decimals-separator="<?php echo $decimals; ?> "> </div> </li> <?php do_action('itelic_add_new_license_screen_end_steps'); ?> </ol> <?php do_action('itelic_add_new_license_screen_after_steps'); ?> <p class="buttons"> <?php submit_button(__("Create", Plugin::SLUG), 'primary', 'itelic-add-new-key', false); ?> </p> </div> <?php wp_nonce_field('itelic-add-new-key'); ?> </form> <?php }
/** * Check if we can remotely deactivate this license key. * * @since 1.0 * * @param array $options * * @return bool */ public function can_remote_deactivate($options = array()) { if (!$this->license) { return false; } $settings = it_exchange_get_option('addon_itelic'); return $settings['enable-remote-deactivation'] && $this->license->get_product()->get_feature('licensing', array('field' => 'online-software')); }
/** * Get info about the key. * * @since 1.0.2 * * @param bool $break_cache * * @return object|bool */ protected function get_key_info($break_cache = false) { $options = it_exchange_get_option('addon_itelic'); $key = $options['license']; if ($break_cache || false === ($data = get_transient('itelic_key_info'))) { $data = Plugin::$updater->get_info($key); if (!is_wp_error($data)) { set_transient('itelic_key_info', $data, DAY_IN_SECONDS); } } return $data; }
/** * Get tags that are shared between managers. * * @internal * * @since 1.0 * * @return Listener[] */ function get_shared_tags() { return array(new Listener('full_customer_name', function (\WP_User $to) { return $to->first_name . " " . $to->last_name; }), new Listener('customer_first_name', function (\WP_User $to) { return $to->first_name; }), new Listener('customer_last_name', function (\WP_User $to) { return $to->last_name; }), new Listener('customer_email', function (\WP_User $to) { return $to->user_email; }), new Listener('store_name', function () { $settings = it_exchange_get_option('settings_general'); return $settings['company-name']; })); }
/** * Return the product's features * * @since 1.0 * * @param mixed $existing the values passed in by the WP Filter API. Ignored here. * @param integer $product_id the WordPress post ID * @param array $options * * @return string product feature */ public function get_feature($existing, $product_id, $options = array()) { $defaults = array('override' => false, 'disable' => false, 'type' => 'percent', 'amount' => '', 'expiry' => ''); $values = get_post_meta($product_id, '_it_exchange_itelic_renewal_discount', true); $raw_meta = \ITUtility::merge_defaults($values, $defaults); if (!$raw_meta['override'] && empty($options['db'])) { $settings = it_exchange_get_option('addon_itelic', true); $raw_meta['type'] = $settings['renewal-discount-type']; $raw_meta['amount'] = $settings['renewal-discount-amount']; $raw_meta['expiry'] = $settings['renewal-discount-expiry']; } if (!isset($options['field'])) { // if we aren't looking for a particular field return $raw_meta; } $field = $options['field']; if (isset($raw_meta[$field])) { // if the field exists with that name just return it return $raw_meta[$field]; } else { if (strpos($field, ".") !== false) { // if the field name was passed using array dot notation $pieces = explode('.', $field); $context = $raw_meta; foreach ($pieces as $piece) { if (!is_array($context) || !array_key_exists($piece, $context)) { // error occurred return null; } $context =& $context[$piece]; } return $context; } else { return null; // we didn't find the data specified } } }