Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions classic-commerce.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ function cc_wc_activate_attempted_notice() {
////////////////////////////////////////////

// Load the Update Client to manage Classic Commerce updates.
include_once dirname( __FILE__ ) . '/includes/class-wc-update-client-config.php';
include_once dirname( __FILE__ ) . '/includes/class-wc-update-client.php';

// Define WC_PLUGIN_FILE.
Expand Down
37 changes: 37 additions & 0 deletions includes/class-wc-update-client-config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace ClassicCommerce\ClassicCommerce;

// Prevent direct access.
if (!defined('ABSPATH')) {
die();
}


class UpdateClientConfig {

public function __construct() {

// Deal with privacy options.
add_filter( 'codepotent_update_manager_filter_classic-commerce/classic-commerce.php_client_request', array( $this, 'client_request' ) );

// Deal with images in a custom location.
add_filter( 'codepotent_update_manager_classic-commerce/classic-commerce.php_image_path', array( $this, 'patch_paths' ) );
add_filter( 'codepotent_update_manager_classic-commerce/classic-commerce.php_image_url' , array( $this, 'patch_paths' ) );

}

public function client_request( $config ) {
if ( 'no' === get_option( 'cc_usage_tracking', 'no' ) ) {
$config['sfum'] = 'no-log';
}
return $config;
}

public function patch_paths( $path ) {
return preg_replace( '/images$/', 'assets/images', $path );
}

}

new UpdateClientConfig;
77 changes: 49 additions & 28 deletions includes/class-wc-update-client.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,31 @@
/**
* -----------------------------------------------------------------------------
* Purpose: Remote client to communicate with the Update Manager plugin.
* Author: Code Potent
* Author: John Alarcon
* Author URI: https://codepotent.com
* API Version: 2.0.0
* Last modified on Update Manager release: 2.4.0
* -----------------------------------------------------------------------------
* This is free software released under the terms of the General Public License,
* version 2, or later. It is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Full
* text of the license is available at https://www.gnu.org/licenses/gpl-2.0.txt.
* -----------------------------------------------------------------------------
* Copyright 2020, Code Potent
* Copyright 2021, John Alarcon (Code Potent)
* 2021, Simone Fioravanti
* -----------------------------------------------------------------------------
*/

// EDIT: Make this unique. Example: YourDevName\YourPluginName;
namespace ClassicCommerce\ClassicCommerce;

// EDIT: URL where Update Manager is installed; with trailing slash!
const UPDATE_SERVER = 'https://officialplugins.classicpress.net/';
const UPDATE_SERVER = 'https://classiccommerce.cc/';

// EDIT: Comment this out and fill with the first part of the url
// of your Download link to make sure that updates
// are served from your trusted source.
// const SECURE_SOURCE = 'https://github.com/ClassicPress-plugins/classic-commerce';

// EDIT: plugin or theme?
const UPDATE_TYPE = 'plugin';
Expand Down Expand Up @@ -49,16 +57,7 @@ class UpdateClient {
private $config;

/**
* Default CP version.
*
* This value is used for comparison in the updates list table by core. This
* property can be set to 4.9.x (whatever x might be at the time,) if you're
* wanting to be exact. The issue with doing that is that you'd have to bump
* that number with every new release of 4.9.x to ensure that core indicates
* 100% compatibility in the table. If your plugin or theme is compatible to
* WordPress 4.9.x, it is compatible with ClassicPress 1.x.x, so, there will
* not be a need for this. Setting it to 4.9.99 ensures don't have to update
* it again.
* Latest CP version.
*/
private $cp_latest_version = '4.9.99';

Expand Down Expand Up @@ -96,7 +95,7 @@ private function __construct() {
];

// Find and store the latest CP version during update process.
$this->cp_latest_version = get_option('cp_latest_version', '');
$this->cp_latest_version = $this->get_latest_version_number();

// Hook the update client into the system.
$this->init();
Expand Down Expand Up @@ -227,15 +226,18 @@ public function filter_component_update_transient($value) {
// Is there a response?
if (isset($value->response)) {

// Ensure the latest ClassicPress version number is available.
$this->get_latest_version_number();

// Get the installed components.
$components = $this->get_component_data('query_'.$this->config['type'].'s');

// Iterate over installed components.
foreach($components as $component=>$data) {

// If necessary check if the new package come from the right source.
if (defined(__NAMESPACE__.'\SECURE_SOURCE') && isset($data['package']) && strpos($data['package'], SECURE_SOURCE) !== 0) {
unset($value->response[$component]);
continue;
}

// Is there a new version?
if (isset($data['id'], $data['new_version'], $data['package'])) {

Expand Down Expand Up @@ -327,6 +329,11 @@ public function filter_components_api_result($res, $action, $args) {
// Get the component's information.
$info = $this->get_component_data($action, $list_components[$args->slug]);

// If the request failed, pass through an informative error message.
if (is_wp_error($info)) {
return $info;
}

// If the response has all the right properties, cast $info to object.
if (isset($info['name'], $info['slug'], $info['external'], $info['sections'])) {
$res = (object)$info;
Expand Down Expand Up @@ -375,7 +382,7 @@ public function filter_component_row_meta($component_meta, $component_file) {
$anchors_string = implode('', $component_meta);
$anchor_text = esc_html__('View details');
if (!preg_match('|(\<a[ \s\S\d]*)('.$anchor_text.')(<\/a>)|', $anchors_string)) {
$component_meta[] = '<a class="thickbox" href="'.admin_url('/'.$this->config['type'].'-install.php?tab='.$this->config['type'].'-information&'.$this->config['type'].'='.$this->server_slug.'&TB_iframe=true&width=600&height=550').'">'.$anchor_text.'</a>';
$component_meta[] = '<a class="thickbox open-plugin-details-modal" href="'.admin_url('/'.$this->config['type'].'-install.php?tab='.$this->config['type'].'-information&'.$this->config['type'].'='.$this->server_slug.'&TB_iframe=true&width=600&height=550').'">'.$anchor_text.'</a>';
}
}

Expand Down Expand Up @@ -566,7 +573,7 @@ private function get_component_data($action, $component='') {
global $cp_version;

// Initialize the data to be posted.
$body = $this->config['post'];
$body = apply_filters('codepotent_update_manager_filter_'.$this->config['id'].'_client_request', $this->config['post']);

if ($action === 'plugin_information') {

Expand Down Expand Up @@ -651,13 +658,22 @@ private function get_component_data($action, $component='') {
}

// Still an error? Hey, you tried. Bail.
if (is_wp_error($raw_response) || 200 != wp_remote_retrieve_response_code($raw_response)) {
return [];
if (is_wp_error($raw_response)) {
return new \WP_Error('update_manager_http_error', __('HTTP error.') . ' ' . $raw_response->get_error_message(), ['original_error' => $raw_response]);
}
$response_code = wp_remote_retrieve_response_code($raw_response);
if (200 != $response_code) {
return new \WP_Error('update_manager_http_error', __('HTTP error.') . ' ' . $response_code, compact('raw_response'));
}

// Get the response body; decode it as an array.
$data = json_decode(trim(wp_remote_retrieve_body($raw_response)), true);

// If decoding fails, bail.
if ($data === null) {
return new \WP_Error('update_manager_http_error', __('Invalid API response (invalid JSON)'), $raw_response);
}

// Set retrieved data to the object for reuse elsewhere.
$this->component_data = is_array($data) ? $data : [];

Expand Down Expand Up @@ -713,13 +729,17 @@ public function get_plugin_images($type, $plugin) {
}

// Set path and URL to this plugin's own images directory.
$image_path = untrailingslashit(WP_PLUGIN_DIR).'/'.$plugin.'/assets/images';
$image_url = untrailingslashit(WP_PLUGIN_URL).'/'.$plugin.'/assets/images';
$image_path = untrailingslashit(WP_PLUGIN_DIR).'/'.$plugin.'/images';
$image_url = untrailingslashit(WP_PLUGIN_URL).'/'.$plugin.'/images';

// Allow directory location to be filtered.
// Allow directory location to be filtered. DEPRECATED FILTERS.
$image_path = apply_filters('codepotent_update_manager_image_path', $image_path);
$image_url = apply_filters('codepotent_update_manager_image_url', $image_url);

// Allow directory location to be filtered. NEW FILTERS.
$image_path = apply_filters('codepotent_update_manager_'.$this->config['id'].'_image_path', $image_path);
$image_url = apply_filters('codepotent_update_manager_'.$this->config['id'].'_image_url', $image_url);

// Banner and icon images are keyed differently; it's a core thing.
$image_qualities = [
'icon' => ['default', '1x', '2x'],
Expand Down Expand Up @@ -814,7 +834,7 @@ public function get_latest_version_number() {
$version = get_transient('codepotent_update_manager_cp_version');

// Return version number, if now known.
if (!empty($version)) {
if (false !== $version) {
return $version;
}

Expand Down Expand Up @@ -848,8 +868,9 @@ public function get_latest_version_number() {
$version = str_replace('.json', '', $version);
}

// A transient ensures the query is not run more than every 10 minutes.
set_transient('codepotent_update_manager_cp_version', $version, MINUTE_IN_SECONDS * 10);
// A transient ensures the query is not run more than every 6 hours.
set_transient('codepotent_update_manager_cp_version', $version, HOUR_IN_SECONDS * 6);
update_option('cp_latest_version', $version);

// Return the version string.
return $version;
Expand All @@ -859,4 +880,4 @@ public function get_latest_version_number() {
}

// Run it!
UpdateClient::get_instance();
UpdateClient::get_instance();