/** * Create an Upgrade record. * * @since 1.0 * * @param Activation $activation * @param Release $release * @param \DateTime $update_date * @param string $previous_version * * @return Update|null * @throws DB_Exception */ public static function create(Activation $activation, Release $release, \DateTime $update_date = null, $previous_version = '') { if ($update_date === null) { $update_date = make_date_time(); } if (empty($previous_version) && $activation->get_release()) { $previous_version = $activation->get_release()->get_version(); } $data = array('activation' => $activation->get_id(), 'release_id' => $release->get_ID(), 'update_date' => $update_date->format("Y-m-d H:i:s"), 'previous_version' => $previous_version); $db = Manager::make_simple_query_object('itelic-updates'); $ID = $db->insert($data); $update = self::get($ID); if ($update) { $activation->set_release($release); /** * Fires when an update record is created. * * @since 1.0 * * @param Update $update */ do_action('itelic_create_update', $update); Cache::add($update); } return $update; }
/** * Render the notification editor. * * @since 1.0 */ protected function render_notification_editor() { $editor = new Editor(Factory::make('itelic-outdated-customers'), array('mustSelectItem' => __("You must select an item", Plugin::SLUG), 'selectTemplateTag' => __("Select Template Tag", Plugin::SLUG), 'templateTag' => __("Template Tag", Plugin::SLUG), 'selectATag' => __("Select a tag", Plugin::SLUG), 'insertTag' => __("Insert", Plugin::SLUG), 'cancel' => __("Cancel", Plugin::SLUG), 'insertTemplateTag' => __("Insert Template Tag", Plugin::SLUG))); $editor->thickbox(); ?> <div class="spacing-wrapper hidden notifications-editor"> <h4><?php _e("Send Update Reminders", Plugin::SLUG); ?> </h4> <p class="description"> <?php printf(__('Email your customers who have not yet updated to version %1$s of %2$s.', Plugin::SLUG), $this->release->get_version(), $this->release->get_product()->post_title); ?> </p> <div class="notification-editor-fields-container"> <input type="text" id="notification-subject" placeholder="<?php esc_attr_e("Enter your subject", Plugin::SLUG); ?> "> <?php $editor->display_template_tag_button(); ?> <?php wp_editor('', 'notification-body', array('teeny' => true, 'media_buttons' => false, 'editor_height' => '250px')); ?> <p class="clearfix notification-buttons"> <a href="javascript:" class="button button-secondary" id="cancel-notification"> <?php _e("Cancel", Plugin::SLUG); ?> </a> <a href="javascript:" class="button button-primary" id="send-notification"> <?php _e("Send", Plugin::SLUG); ?> </a> </p> </div> </div> <?php }
/** * Parse the status query. * * @since 1.0 * * @return Where|null */ protected function parse_type() { if ($this->args['type'] === 'any') { return null; } else { $white_list = Release::get_types(); $types = (array) $this->args['type']; foreach ($types as $type) { if (!isset($white_list[$type])) { throw new \InvalidArgumentException("Invalid type {$type}"); } } return new Where('type', true, (array) $this->args['type']); } }
/** * Set the current version installed on this location. * * @since 1.0 * * @param Release $release */ public function set_release(Release $release) { $this->release = $release; $this->update('release_id', $this->release->get_pk()); }
public function test_types_exist() { $types = Release::get_types(); $this->assertArrayHasKey('major', $types, 'Major type does not exist.'); $this->assertArrayHasKey('minor', $types, 'Minor type does not exist.'); $this->assertArrayHasKey('security', $types, 'Security type does not exist.'); $this->assertArrayHasKey('pre-release', $types, 'Pre-release type does not exist.'); }
/** * Save post data to a new release. * * @since 1.0 */ public function save_new_release() { if (!isset($_POST['itelic-action']) || $_POST['itelic-action'] != 'add-new-release') { return; } if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'itelic-add-new-release')) { $this->errors[] = __("Request expired. Please try again.", Plugin::SLUG); return; } if (!isset($_POST['type-select']) || !array_key_exists($_POST['type-select'], Release::get_types())) { $this->errors[] = __("Invalid release type selected.", Plugin::SLUG); return; } $type = $_POST['type-select']; if (empty($_POST['product'])) { $this->errors[] = __("You must select a product.", Plugin::SLUG); return; } try { $product = itelic_get_product($_POST['product']); } catch (\Exception $e) { $this->errors[] = $e->getMessage(); return; } if (!$product->has_feature('licensing')) { $this->errors[] = __("Product selected does not support licensing.", Plugin::SLUG); return; } if (empty($_POST['version'])) { $this->errors[] = __("Invalid version number entered.", Plugin::SLUG); return; } $version = sanitize_text_field($_POST['version']); if (empty($_POST['upload-file'])) { $this->errors[] = __("No software file selected.", Plugin::SLUG); return; } $attachment = get_post($_POST['upload-file']); $changelog = empty($_POST['whats-changed']) ? '' : stripslashes($_POST['whats-changed']); $security_message = empty($_POST['security-message']) ? '' : stripslashes($_POST['security-message']); if (!current_user_can('unfiltered_html')) { $changelog = wp_kses($changelog, wp_kses_allowed_html()); $security_message = wp_kses($security_message, wp_kses_allowed_html()); } $action = isset($_POST['release']) && $_POST['release'] ? 'release' : 'draft'; $status = 'release' == $action ? Release::STATUS_ACTIVE : Release::STATUS_DRAFT; try { $args = array('product' => $product, 'file' => $attachment, 'version' => $version, 'type' => $type, 'status' => $status, 'changelog' => $changelog, 'security-message' => $security_message); /** * Filters the add new release args. * * @since 1.0 * * @param array $args */ $args = apply_filters('itelic_add_new_release_args', $args); $release = itelic_create_release($args); if (is_wp_error($release)) { $this->errors[] = $release->get_error_message(); return; } if ($release) { /** * Fires when a new release is saved. * * @since 1.0 * * @param Release $release */ do_action('itelic_add_new_release_save', $release); $url = add_query_arg('new', true, itelic_get_admin_edit_release_link($release->get_pk())); wp_redirect($url); die; } } catch (\Exception $e) { $this->errors[] = $e->getMessage(); } }
/** * When a release is paused, set the last updated value to the previous release * in the readme product feature. * * @internal * * @since 1.0 * * @param Release $release * @param Release|null $prev_release */ function set_last_updated_value_in_readme_on_pause(Release $release, Release $prev_release = null) { if ($prev_release && $release->get_product()->has_feature('licensing-readme')) { $release->get_product()->update_feature('licensing-readme', array('last_updated' => $prev_release->get_start_date()->getTimestamp())); } }
/** * Render the types selector. * * @since 1.0 * * @param string $selected */ protected function render_types_tab($selected = '') { ?> <ul class="release-types"> <?php foreach (Release::get_types(true) as $type => $label) { ?> <li class="<?php echo $type == $selected ? 'selected' : ''; ?> "> <input type="radio" name="type-select" <?php checked($selected, $type); ?> id="type-select-<?php echo $type; ?> " value="<?php echo $type; ?> "> <label for="type-select-<?php echo $type; ?> "> <span class="dashicons <?php echo $this->get_icon_for_type($type); ?> "></span> <span class="type-description"><?php echo $label; ?> </span> </label> </li> <?php } ?> </ul> <?php }
/** * Create a release. * * @api * * @since 1.0 * * @param array $args * * @return \ITELIC\Release|WP_Error */ function itelic_create_release($args) { $defaults = array('product' => '', 'file' => '', 'version' => '', 'type' => '', 'status' => '', 'changelog' => ''); $args = wp_parse_args($args, $defaults); if (is_numeric($args['product'])) { $product = itelic_get_product($args['product']); } else { $product = $args['product']; } if (!$product) { return new WP_Error('invalid_product', __('Invalid Product', \ITELIC\Plugin::SLUG)); } if (is_numeric($args['file'])) { $file = get_post($args['file']); } else { $file = $args['file']; } if (!$file || get_post_type($file) != 'attachment') { return new WP_Error('invalid_file', __("Invalid File", \ITELIC\Plugin::SLUG)); } $version = $args['version']; $type = $args['type']; $status = $args['status']; $changelog = $args['changelog']; try { $release = \ITELIC\Release::create($product, $file, $version, $type, $status, $changelog); if (isset($args['security-message'])) { $release->add_meta('security-message', $args['security-message']); } return $release; } catch (InvalidArgumentException $e) { return new WP_Error('exception', $e->getMessage()); } }
/** * Prepare an individual key view. * * @since 1.0 * * @param Release $release * * @return array */ protected function prepare_record(Release $release) { if ($release->get_start_date()) { $start_date = $release->get_start_date()->format(get_option('date_format')); } else { $start_date = '-'; } $updated = $release->get_total_updated(); $total_activations = $release->get_total_active_activations(); $total_activations = max(1, $total_activations); $percent = min(number_format($updated / $total_activations * 100, 0), 100); $data = array('ID' => $release->get_ID(), 'release' => (string) $release, 'status' => $release->get_status(false), 'type' => $release->get_type(true), 'updated' => "{$percent}%", 'start_date' => $start_date); /** * Filter the columns on the releases list table. * * @since 1.0 * * @param array $data * @param Release $release */ $data = apply_filters('itelic_releases_list_table_columns', $data, $release); return $data; }
/** * Extra controls to be displayed between bulk actions and pagination * * @since 1.0 * @access protected * * @param string $which */ protected function extra_tablenav($which) { if ($which !== 'top') { return; } $selected_product = isset($_GET['prod']) ? absint($_GET['prod']) : 0; $selected_type = isset($_GET['type']) ? $_GET['type'] : ''; ?> <div class="product-filter-container"> <label for="filter-by-product" class="screen-reader-text"> <?php _e("Filter by product", Plugin::SLUG); ?> </label> <select name="prod" id="filter-by-product" style="width:300px;margin-left:-8px;"> <option value=""><?php _e("All products", Plugin::SLUG); ?> </option> <?php foreach ($this->products as $product) { ?> <option value="<?php echo esc_attr($product->ID); ?> " <?php selected($selected_product, $product->ID); ?> > <?php echo $product->post_title; ?> </option> <?php } ?> </select> </div> <div class="type-filter-container"> <label for="filter-by-type" class="screen-reader-text"> <?php _e("Filter by type", Plugin::SLUG); ?> </label> <select name="type" id="filter-by-type"> <option value=""><?php _e("All types", Plugin::SLUG); ?> </option> <?php foreach (Release::get_types(true) as $type => $label) { ?> <option value="<?php echo esc_attr($type); ?> " <?php selected($selected_type, $type); ?> > <?php echo $label; ?> </option> <?php } ?> </select> </div> <?php submit_button(__('Filter'), 'button', 'filter_action', false); }
/** * Get data to display for a single key. * * @param \ITELIC\Activation|\ITELIC\Release $release * @param bool $raw * * @return array */ protected function get_fields_for_object(\ITELIC\Release $release, $raw = false) { if ($release->get_start_date()) { $started = $release->get_start_date()->format(DateTime::ISO8601); } else { $started = '-'; } return array('ID' => $release->get_ID(), 'product' => $raw ? $release->get_product()->ID : $release->get_product()->post_title, 'version' => $release->get_version(), 'type' => $release->get_type(!$raw), 'status' => $release->get_status(!$raw), 'download' => $raw ? $release->get_download()->ID : $release->get_download()->post_title, 'started' => $started, 'changelog' => $release->get_changelog()); }
/** * Get the chart for displaying the previous version being upgrade from. * * @since 1.0 * * @param Release $release * * @return Chart\Base */ private function get_version_chart(Release $release) { if ($release->get_status() == Release::STATUS_DRAFT) { return null; } $results = $release->get_top_5_previous_versions(); $chart = new Chart\Pie(698, 200, array('ibdLoadOn' => 'loadVersionsChart', 'ibdShowLegend' => '#pie-chart-legend', 'tooltipTemplate' => '<%= value %> install<%if (value != 1){%>s<%}%>', 'responsive' => true)); $colors = array(array('color' => '#E94F37', 'highlight' => '#FF6951'), array('color' => '#393E41', 'highlight' => '#53585B'), array('color' => '#3F88C5', 'highlight' => '#59A2DF'), array('color' => '#44BBA4', 'highlight' => '#5ED5BE'), array('color' => '#EDDDD4', 'highlight' => '#D4C4BB')); $i = 0; foreach ($results as $version => $count) { $label = empty($version) ? __("Unknown", Plugin::SLUG) : "v{$version}"; $chart->add_data_set($count, $label, $colors[$i]); $i++; } return $chart; }