From 07811c2c39ffc0ad712aae96e14ffe7b9d0c1124 Mon Sep 17 00:00:00 2001 From: kgkrishna Date: Wed, 6 Nov 2019 18:54:34 +0530 Subject: [PATCH] New feature (Automatic Updates) and bug fixes --- README.md | 32 +-- .../class-wc-order-view-admin-list-table.php | 20 +- admin/css/wc-order-view-admin.css | 12 + includes/class-wc-order-view-updater.php | 260 ++++++++++++++++++ woocommerce-order-view.php | 16 +- 5 files changed, 311 insertions(+), 29 deletions(-) create mode 100644 includes/class-wc-order-view-updater.php diff --git a/README.md b/README.md index a10f1c4..6790e40 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ -=== Plugin Name === -Contributors: (this should be a list of wordpress.org userid's) +=== WC Order View === + +Contributors: kggopal12 Donate link: https://kgopalkrishna.com Tags: woocommerce, order, view Requires at least: 5.0.0 Tested up to: 5.2.3 -Stable tag: 1.1.0 +Stable tag: 1.2.0 License: GPLv3 or later License URI: http://www.gnu.org/licenses/gpl-3.0.html @@ -12,20 +13,7 @@ This plugin gives a strict View-Only access to Woocommerce orders for specified == Description == -This is the long description. No limit, and you can use Markdown (as well as in the following sections). - -For backwards compatibility, if this section is missing, the full length of the short description will be used, and -Markdown parsed. - -A few notes about the sections above: - -* "Contributors" is a comma separated list of wp.org/wp-plugins.org usernames -* "Tags" is a comma separated list of tags that apply to the plugin -* "Requires at least" is the lowest version that the plugin will work on -* "Tested up to" is the highest version that you've *successfully used to test the plugin*. Note that it might work on -higher versions... this is just the highest one you've verified. -* Stable tag should indicate the Subversion "tag" of the latest stable version, or "trunk," if you use `/trunk/` for -stable. +This plugin gives a strict view only access to woocommerce orders. All you need to do is create a new user role 'products_admin' using any role editor plugin available. All users with this role will be able to view orders, the items in the order, total amount paid including taxes and shipping, and the order notes all in read-only mode. This plugin also provides support for select 3rd party Woocommerce premium plugins like Woocommerce Subscriptions, PDF Invoices and Woocommerce API Manager. Planned features include CSV Exporting options and Custom Order actions available only for 'products_admin' == Installation == @@ -42,18 +30,24 @@ stable. * Issue #3 - Fixed the total orders count shown in all orders page = 1.1.0 = -* Issue #5 - Fixed cancelled orders not visible +* Fix - Fixed cancelled orders not visible #5 * Feature - Support for 3rd party woocommerce plugins ( PDF Invoices, Woocommerce Subscriptions, Woocommerce API Mananger ) * Dev - New hooks added to the view order details page ( Details will be shared in a separate documentation ) += 1.2.0 = +* Feature - One click update option added in the plugins page +* Fix - Cancelled order status color doesn't match WooCommerce #8 +* Fix - Invoice date for all orders showing same date in All orders list #9 + == Features == 1. Strict view only access to orders. 1. View each orders individually. +1. Support for 3rd party woocommerce plugins ( PDF Invoices, Woocommerce Subscriptions, Woocommerce API Mananger ) +1. Automatic update notifications == Planned Features == -* hooks and filters for adding custom content in view order page * Export orders in CSV format * Custom order view actions diff --git a/admin/class-wc-order-view-admin-list-table.php b/admin/class-wc-order-view-admin-list-table.php index 47b2856..8239892 100644 --- a/admin/class-wc-order-view-admin-list-table.php +++ b/admin/class-wc-order-view-admin-list-table.php @@ -113,7 +113,7 @@ public function get_orders( $per_page = 5, $page_number = 1 ) { $shipping_address = WC()->countries->get_formatted_address( $shipping_address, ', ' ); $order_item[ 'order_id' ] = $order->get_id(); - $order_item[ 'name' ] = $order->get_billing_first_name() . " " . $order->get_billing_last_name(); + $order_item[ 'customer_name' ] = $order->get_billing_first_name() . " " . $order->get_billing_last_name(); $order_item[ 'date' ] = $result_item->post_date; $order_item[ 'status' ] = $result_item->post_status; $order_item[ 'billing_address' ] = $billing_address ? $billing_address : "–"; @@ -212,7 +212,7 @@ function get_columns() { $columns = array( 'cb' => __( '', 'wc-order-view' ), 'order_id' => __( 'Order', 'wc-order-view' ), - 'name' => __( 'Name', 'wc-order-view' ) + 'customer_name' => __( 'Name', 'wc-order-view' ) ); if( get_option( 'wcov_pdf_invoices' ) == "enabled" ) { @@ -226,7 +226,7 @@ function get_columns() { if( get_option( 'wcov_subscriptions' ) == "enabled" ) { - $columns[ 'subscription_relationship' ] = '
' . esc_attr__( 'Subscription Relationship', 'wc-order-view' ) . '' . esc_attr__( 'Subscription Relationship', 'wc-order-view' ) . '
'; + $columns[ 'subscription_relationship' ] = '
' . esc_attr__( 'Subscription Relationship', 'wc-order-view' ) . '
'; } $columns[ 'total' ] = __( 'Total', 'wc-order-view' ); @@ -264,7 +264,7 @@ public function get_sortable_columns() { */ public function get_hidden_columns() { - $hidden_columns = array( 'name', 'billing_address', 'shipping_address' ); + $hidden_columns = array( 'customer_name', 'billing_address', 'shipping_address' ); return $hidden_columns; @@ -283,7 +283,7 @@ public function column_default( $item, $column_name ) { switch ( $column_name ) { case 'order_id' : - case 'name' : + case 'customer_name' : case 'status' : case 'date' : case 'billing_address' : @@ -323,7 +323,7 @@ function column_order_id( $item ) { $order_id = ""; $order_id .= 'Preview'; - $order_id .= '#' . $item[ 'order_id' ] .' '. $item[ 'name' ] . ''; + $order_id .= '#' . $item[ 'order_id' ] .' '. $item[ 'customer_name' ] . ''; return $order_id; @@ -417,7 +417,7 @@ function column_pdf_invoice( $item ) { $invoice_number_display = get_post_meta( $order_id, '_invoice_number_display', true ); $invoice_date = get_post_meta( $order_id, '_invoice_date', true ); - $invoice = '' . $invoice_number_display . '
' . date( 'j F, Y' ) . '
'; + $invoice = '' . $invoice_number_display . '
' . date( 'j F, Y', strtotime( $invoice_date ) ) . '
'; return $invoice; @@ -497,7 +497,11 @@ function usort_reorder( $a, $b ) { */ public function prepare_items() { - $this->_column_headers = $this->get_column_info(); + //$this->_column_headers = $this->get_column_info(); + $columns = $this->get_columns(); + $hidden = $this->get_hidden_columns(); + $sortable = $this->get_sortable_columns(); + $this->_column_headers = array($columns, $hidden, $sortable); /** Process bulk action */ //$this->process_bulk_action(); diff --git a/admin/css/wc-order-view-admin.css b/admin/css/wc-order-view-admin.css index fd05d6c..71e1e0b 100644 --- a/admin/css/wc-order-view-admin.css +++ b/admin/css/wc-order-view-admin.css @@ -72,6 +72,8 @@ display: -webkit-inline-box; display: -webkit-inline-flex; display: inline-flex; + color: #777; + background: #e5e5e5; line-height: 2.5em; border-radius: 4px; border-bottom: 1px solid @@ -98,6 +100,16 @@ color: #94660c; } +.order-view-admin .order-status.status-failed { + background: #eba3a3; + color: #761919; +} + +.order-view-admin .order-status.status-processing { + background: #c6e1c6; + color: #5b841b; +} + .order-view-admin .wp-list-table .column-order_id { width: 20ch; } diff --git a/includes/class-wc-order-view-updater.php b/includes/class-wc-order-view-updater.php new file mode 100644 index 0000000..12379b3 --- /dev/null +++ b/includes/class-wc-order-view-updater.php @@ -0,0 +1,260 @@ + + */ +class Wc_Order_View_Updater { + + /** + * The file path passed to the constructor of this class. + * + * @since 1.2.0 + * @access protected + * @var string $file The file path passed to the constructor of this class. + */ + protected $file; + + /** + * Contains the plugin data retrieved from get_plugin_data() method. + * + * @since 1.2.0 + * @access protected + * @var array $plugin Contains the plugin data retrieved from get_plugin_data() method. + */ + protected $plugin; + + /** + * Contains the basename of the plugin retrieved from plugin_basename() method. + * + * @since 1.2.0 + * @access protected + * @var string $basename Contains the basename of the plugin retrieved from plugin_basename() method. + */ + protected $basename; + + /** + * Tracks the plugin's active/inactive status. + * + * @since 1.2.0 + * @access protected + * @var boolean $active Tracks the plugin's active/inactive status. + */ + protected $active; + + /** + * Github Username. + * + * @since 1.2.0 + * @access private + * @var string $username Github Username. + */ + private $username; + + /** + * Github Repository Name. + * + * @since 1.2.0 + * @access private + * @var string $repository Github Repository Name. + */ + private $repository; + + /** + * Github Response. + * + * @since 1.2.0 + * @access private + * @var string $github_response Github Response. + */ + private $github_response; + + /** + * Initialize the class and set its properties. + * + * @since 1.2.0 + * @param string $file The file path of this plugin. + */ + public function __construct( $file ) { + + $this->file = $file; + + add_action( 'admin_init', array( $this, 'set_plugin_properties' ) ); + + return $this; + + } + + /** + * Retrieving the plugin properties and setting them to the protected properties in this class. + * + * @since 1.2.0 + */ + public function set_plugin_properties() { + + $this->plugin = get_plugin_data( $this->file ); + $this->basename = plugin_basename( $this->file ); + $this->active = is_plugin_active( $this->basename ); + + } + + /** + * Sets the GitHub Username property in this class. + * + * @since 1.2.0 + * @param string $username The username passed will be set to the corresponding property in this class. + */ + public function set_username( $username ) { + $this->username = $username; + } + + /** + * Sets the GitHub Repository Name property in this class. + * + * @since 1.2.0 + * @param string $repository The repository name passed will be set to the corresponding property in this class. + */ + public function set_repository( $repository ) { + $this->repository = $repository; + } + + /** + * Retrieves the repository information and sets the GitHub Response property in this class. + * + * @since 1.2.0 + */ + private function get_repository_info() { + if ( is_null( $this->github_response ) ) { // Do we have a response? + $request_uri = sprintf( 'https://api.github.com/repos/%s/%s/releases', $this->username, $this->repository ); // Build URI + + $response = json_decode( wp_remote_retrieve_body( wp_remote_get( $request_uri ) ), true ); // Get JSON and parse it + if( is_array( $response ) ) { // If it is an array + $response = current( $response ); // Get the first item + } + + $this->github_response = $response; // Set it to our property + } + } + + /** + * Initializes the updater + * + * @since 1.2.0 + */ + public function initialize() { + add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'modify_transient' ), 10, 1 ); + add_filter( 'plugins_api', array( $this, 'plugin_popup' ), 10, 3); + add_filter( 'upgrader_post_install', array( $this, 'after_install' ), 10, 3 ); + } + + + /** + * Updates the WordPress Transient based on changes detected in GitHub Repository + * + * @since 1.2.0 + * @param string $transient The transient option passed by WordPress + */ + public function modify_transient( $transient ) { + if( property_exists( $transient, 'checked') ) { // Check if transient has a checked property + if( $checked = $transient->checked ) { // Did WordPress check for updates? + $this->get_repository_info(); // Get the repo info + $out_of_date = version_compare( $this->github_response['tag_name'], $checked[$this->basename], 'gt' ); // Check if we're out of date + if( $out_of_date ) { + $new_files = $this->github_response['zipball_url']; // Get the ZIP + $slug = current( explode('/', $this->basename ) ); // Create valid slug + $plugin = array( // setup our plugin info + 'url' => $this->plugin["PluginURI"], + 'slug' => $slug, + 'package' => $new_files, + 'new_version' => $this->github_response['tag_name'] + ); + $transient->response[ $this->basename ] = (object) $plugin; // Return it in response + } + } + } + return $transient; // Return filtered transient + } + + /** + * Content for the update popup with relevant plugin information and release notes from GitHub + * + * @since 1.2.0 + * @param (false|object|array) $result The result object or array. Default false. + * @param string $action The type of information being requested from the Plugin Installation API. + * @param object $args Plugin API arguments. + */ + public function plugin_popup( $result, $action, $args ) { + if( ! empty( $args->slug ) ) { // If there is a slug + if( $args->slug == current( explode( '/' , $this->basename ) ) ) { // And it's our slug + $this->get_repository_info(); // Get our repo info + // Set it to an array + $plugin = array( + 'name' => $this->plugin["Name"], + 'slug' => $this->basename, + 'version' => $this->github_response['tag_name'], + 'author' => $this->plugin["AuthorName"], + 'author_profile' => $this->plugin["AuthorURI"], + 'last_updated' => $this->github_response['published_at'], + 'homepage' => $this->plugin["PluginURI"], + 'short_description' => $this->plugin["Description"], + 'sections' => array( + 'Description' => $this->plugin["Description"], + 'Updates' => $this->github_response['body'], + ), + 'download_link' => $this->github_response['zipball_url'] + ); + return (object) $plugin; // Return the data + } + } + return $result; // Otherwise return default + } + + /** + * Actions to be performed after the plugin is updated + * + * @since 1.2.0 + * @param bool $response Installation response. + * @param array $hook_extra Extra arguments passed to hooked filters. + * @param array $result Installation result data. + */ + public function after_install( $response, $hook_extra, $result ) { + global $wp_filesystem; // Get global FS object + + $install_directory = plugin_dir_path( $this->file ); // Our plugin directory + $wp_filesystem->move( $result['destination'], $install_directory ); // Move files to the plugin dir + $result['destination'] = $install_directory; // Set the destination for the rest of the stack + + if ( $this->active ) { // If it was active + activate_plugin( $this->basename ); // Reactivate + } + return $result; + } + + /** + * Short Description. (use period) + * + * Long Description. + * + * @since 1.2.0 + */ + public static function update() { + + } + +} diff --git a/woocommerce-order-view.php b/woocommerce-order-view.php index 1b7a413..246f920 100644 --- a/woocommerce-order-view.php +++ b/woocommerce-order-view.php @@ -16,7 +16,7 @@ * Plugin Name: Woocommerce Order View * Plugin URI: https://kgopalkrishna.com/wc-order-view/ * Description: This plugin gives a strict View-Only access to Woocommerce orders for specified user roles. - * Version: 1.1.0 + * Version: 1.2.0 * Author: K Gopal Krishna * Author URI: https://kgopalkrishna.com * License: GPL-3.0+ @@ -35,7 +35,7 @@ * Start at version 1.0.0 and use SemVer - https://semver.org * Rename this for your plugin and update it as you release new versions. */ -define( 'WC_ORDER_VIEW_VERSION', '1.1.0' ); +define( 'WC_ORDER_VIEW_VERSION', '1.2.0' ); /** * The code that runs during plugin activation. @@ -46,6 +46,18 @@ function activate_wc_order_view() { Wc_Order_View_Activator::activate(); } +/** + * The code that runs during plugin update. + * This action is documented in includes/class-wc-order-view-updater.php + */ +function update_wc_order_view() { + require_once plugin_dir_path( __FILE__ ) . 'includes/class-wc-order-view-updater.php'; + $updater = new Wc_Order_View_Updater( __FILE__ ); + $updater->set_username( 'vbiweb' ); + $updater->set_repository( 'wc-order-view' ); + $updater->initialize(); +} + /** * The code that runs during plugin deactivation. * This action is documented in includes/class-wc-order-view-deactivator.php