$controller = new $controller(); $this->$controller->register_routes(); } } /** * Filter REST API endpoints. * * @param array $endpoints List of endpoints. * @return array */ public static function filter_rest_endpoints( $endpoints ) { // Override GET /wc/v3/system_status/tools. if ( isset( $endpoints['/wc/v3/system_status/tools'] ) && isset( $endpoints['/wc/v3/system_status/tools'][1] ) && isset( $endpoints['/wc/v3/system_status/tools'][0] ) && $endpoints['/wc/v3/system_status/tools'][1]['callback'][0] instanceof WC_Admin_REST_System_Status_Tools_Controller ) { $endpoints['/wc/v3/system_status/tools'][0] = $endpoints['/wc/v3/system_status/tools'][1]; } // // Override GET & PUT for /wc/v3/system_status/tools. if ( isset( $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'] ) && isset( $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][3] ) && isset( $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][2] ) && $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][2]['callback'][0] instanceof WC_Admin_REST_System_Status_Tools_Controller && $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][3]['callback'][0] instanceof WC_Admin_REST_System_Status_Tools_Controller ) { $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][0] = $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][2]; $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][1] = $endpoints['/wc/v3/system_status/tools/(?P[\w-]+)'][3]; } // Override GET /wc/v3/reports. if ( isset( $endpoints['/wc/v3/reports'] ) && isset( $endpoints['/wc/v3/reports'][1] ) && isset( $endpoints['/wc/v3/reports'][0] ) && $endpoints['/wc/v3/reports'][1]['callback'][0] instanceof WC_Admin_REST_Reports_Controller ) { $endpoints['/wc/v3/reports'][0] = $endpoints['/wc/v3/reports'][1]; } // Override /wc/v3/products. if ( isset( $endpoints['/wc/v3/products'] ) && isset( $endpoints['/wc/v3/products'][3] ) && isset( $endpoints['/wc/v3/products'][2] ) && $endpoints['/wc/v3/products'][2]['callback'][0] instanceof WC_Admin_REST_Products_Controller && $endpoints['/wc/v3/products'][3]['callback'][0] instanceof WC_Admin_REST_Products_Controller ) { $endpoints['/wc/v3/products'][0] = $endpoints['/wc/v3/products'][2]; $endpoints['/wc/v3/products'][1] = $endpoints['/wc/v3/products'][3]; } // Override /wc/v3/customers. if ( isset( $endpoints['/wc/v3/customers'] ) && isset( $endpoints['/wc/v3/customers'][3] ) && isset( $endpoints['/wc/v3/customers'][2] ) && $endpoints['/wc/v3/customers'][2]['callback'][0] instanceof WC_Admin_REST_Customers_Controller && $endpoints['/wc/v3/customers'][3]['callback'][0] instanceof WC_Admin_REST_Customers_Controller ) { $endpoints['/wc/v3/customers'][0] = $endpoints['/wc/v3/customers'][2]; $endpoints['/wc/v3/customers'][1] = $endpoints['/wc/v3/customers'][3]; } // Override /wc/v3/products/$id. if ( isset( $endpoints['/wc/v3/products/(?P[\d]+)'] ) && isset( $endpoints['/wc/v3/products/(?P[\d]+)'][5] ) && isset( $endpoints['/wc/v3/products/(?P[\d]+)'][4] ) && isset( $endpoints['/wc/v3/products/(?P[\d]+)'][3] ) && $endpoints['/wc/v3/products/(?P[\d]+)'][3]['callback'][0] instanceof WC_Admin_REST_Products_Controller && $endpoints['/wc/v3/products/(?P[\d]+)'][4]['callback'][0] instanceof WC_Admin_REST_Products_Controller && $endpoints['/wc/v3/products/(?P[\d]+)'][5]['callback'][0] instanceof WC_Admin_REST_Products_Controller ) { $endpoints['/wc/v3/products/(?P[\d]+)'][0] = $endpoints['/wc/v3/products/(?P[\d]+)'][3]; $endpoints['/wc/v3/products/(?P[\d]+)'][1] = $endpoints['/wc/v3/products/(?P[\d]+)'][4]; $endpoints['/wc/v3/products/(?P[\d]+)'][2] = $endpoints['/wc/v3/products/(?P[\d]+)'][5]; } // Override /wc/v3/products/reviews. if ( isset( $endpoints['/wc/v3/products/reviews'] ) && isset( $endpoints['/wc/v3/products/reviews'][3] ) && isset( $endpoints['/wc/v3/products/reviews'][2] ) && $endpoints['/wc/v3/products/reviews'][2]['callback'][0] instanceof WC_Admin_REST_Product_Reviews_Controller && $endpoints['/wc/v3/products/reviews'][3]['callback'][0] instanceof WC_Admin_REST_Product_Reviews_Controller ) { $endpoints['/wc/v3/products/reviews'][0] = $endpoints['/wc/v3/products/reviews'][2]; $endpoints['/wc/v3/products/reviews'][1] = $endpoints['/wc/v3/products/reviews'][3]; } return $endpoints; } /** * Regenerate data for reports. */ public static function regenrate_report_data() { WC_Admin_Reports_Orders_Data_Store::queue_order_stats_repopulate_database(); self::order_product_lookup_store_init(); } /** * Adds regenerate tool. * * @param array $tools List of tools. * @return array */ public static function add_regenerate_tool( $tools ) { return array_merge( $tools, array( 'rebuild_stats' => array( 'name' => __( 'Rebuild reports data', 'wc-admin' ), 'button' => __( 'Rebuild reports', 'wc-admin' ), 'desc' => __( 'This tool will rebuild all of the information used by the reports.', 'wc-admin' ), 'callback' => array( 'WC_Admin_Api_Init', 'regenrate_report_data' ), ), ) ); } /** * Init orders data store. */ public static function orders_data_store_init() { WC_Admin_Reports_Orders_Data_Store::init(); } /** * Init orders product lookup store. * * @param WC_Background_Updater|null $updater Updater instance. * @return bool */ public static function order_product_lookup_store_init( $updater = null ) { // TODO: this needs to be updated a bit, as it no longer runs as a part of WC_Install, there is no bg updater. global $wpdb; $orders = get_transient( 'wc_update_350_all_orders' ); if ( false === $orders ) { $orders = wc_get_orders( array( 'limit' => -1, 'return' => 'ids', ) ); set_transient( 'wc_update_350_all_orders', $orders, DAY_IN_SECONDS ); } // Process orders until close to running out of memory timeouts on large sites then requeue. foreach ( $orders as $order_id ) { $order = wc_get_order( $order_id ); if ( ! $order ) { continue; } foreach ( $order->get_items() as $order_item ) { $wpdb->replace( $wpdb->prefix . 'wc_order_product_lookup', array( 'order_item_id' => $order_item->get_id(), 'order_id' => $order->get_id(), 'product_id' => $order_item->get_product_id( 'edit' ), 'variation_id' => $order_item->get_variation_id( 'edit' ), 'customer_id' => ( 0 < $order->get_customer_id( 'edit' ) ) ? $order->get_customer_id( 'edit' ) : null, 'product_qty' => $order_item->get_quantity( 'edit' ), 'product_net_revenue' => $order_item->get_subtotal( 'edit' ), 'date_created' => date( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ), ), array( '%d', '%d', '%d', '%d', '%d', '%d', '%f', '%s', ) ); } // Pop the order ID from the array for updating the transient later should we near memory exhaustion. unset( $orders[ $order_id ] ); if ( $updater instanceof WC_Background_Updater && $updater->is_memory_exceeded() ) { // Update the transient for the next run to avoid processing the same orders again. set_transient( 'wc_update_350_all_orders', $orders, DAY_IN_SECONDS ); return true; } } return true; } /** * Adds data stores. * * @param array $data_stores List of data stores. * @return array */ public static function add_data_stores( $data_stores ) { return array_merge( $data_stores, array( 'report-revenue-stats' => 'WC_Admin_Reports_Orders_Data_Store', 'report-orders-stats' => 'WC_Admin_Reports_Orders_Data_Store', 'report-products' => 'WC_Admin_Reports_Products_Data_Store', 'report-variations' => 'WC_Admin_Reports_Variations_Data_Store', 'report-products-stats' => 'WC_Admin_Reports_Products_Stats_Data_Store', 'report-categories' => 'WC_Admin_Reports_Categories_Data_Store', 'report-taxes' => 'WC_Admin_Reports_Taxes_Data_Store', 'report-taxes-stats' => 'WC_Admin_Reports_Taxes_Stats_Data_Store', 'report-coupons' => 'WC_Admin_Reports_Coupons_Data_Store', 'report-coupons-stats' => 'WC_Admin_Reports_Coupons_Stats_Data_Store', 'report-downloads' => 'WC_Admin_Reports_Downloads_Data_Store', 'admin-note' => 'WC_Admin_Notes_Data_Store', ) ); } /** * Adds new tables. * * @param array $wc_tables List of WooCommerce tables. * @return array */ public static function add_tables( $wc_tables ) { global $wpdb; return array_merge( $wc_tables, array( // TODO: will this work on multisite? "{$wpdb->prefix}wc_order_stats", "{$wpdb->prefix}wc_order_product_lookup", "{$wpdb->prefix}wc_order_tax_lookup", "{$wpdb->prefix}wc_order_coupon_lookup", "{$wpdb->prefix}woocommerce_admin_notes", "{$wpdb->prefix}woocommerce_admin_note_actions", ) ); } /** * Get database schema. * * @return string */ private static function get_schema() { global $wpdb; if ( $wpdb->has_cap( 'collation' ) ) { $collate = $wpdb->get_charset_collate(); } $tables = " CREATE TABLE {$wpdb->prefix}wc_order_stats ( order_id bigint(20) unsigned NOT NULL, date_created timestamp DEFAULT '0000-00-00 00:00:00' NOT NULL, num_items_sold int(11) UNSIGNED DEFAULT 0 NOT NULL, gross_total double DEFAULT 0 NOT NULL, coupon_total double DEFAULT 0 NOT NULL, refund_total double DEFAULT 0 NOT NULL, tax_total double DEFAULT 0 NOT NULL, shipping_total double DEFAULT 0 NOT NULL, net_total double DEFAULT 0 NOT NULL, returning_customer boolean DEFAULT 0 NOT NULL, PRIMARY KEY (order_id), KEY date_created (date_created) ) $collate; CREATE TABLE {$wpdb->prefix}wc_order_product_lookup ( order_item_id BIGINT UNSIGNED NOT NULL, order_id BIGINT UNSIGNED NOT NULL, product_id BIGINT UNSIGNED NOT NULL, variation_id BIGINT UNSIGNED NOT NULL, customer_id BIGINT UNSIGNED NULL, date_created timestamp DEFAULT '0000-00-00 00:00:00' NOT NULL, product_qty INT UNSIGNED NOT NULL, product_net_revenue double DEFAULT 0 NOT NULL, PRIMARY KEY (order_item_id), KEY order_id (order_id), KEY product_id (product_id), KEY customer_id (customer_id), KEY date_created (date_created) ) $collate; CREATE TABLE {$wpdb->prefix}wc_order_tax_lookup ( order_id BIGINT UNSIGNED NOT NULL, tax_rate_id BIGINT UNSIGNED NOT NULL, date_created timestamp DEFAULT '0000-00-00 00:00:00' NOT NULL, shipping_tax double DEFAULT 0 NOT NULL, order_tax double DEFAULT 0 NOT NULL, total_tax double DEFAULT 0 NOT NULL, KEY order_id (order_id), KEY tax_rate_id (tax_rate_id), KEY date_created (date_created) ) $collate; CREATE TABLE {$wpdb->prefix}wc_order_coupon_lookup ( order_id BIGINT UNSIGNED NOT NULL, coupon_id BIGINT UNSIGNED NOT NULL, date_created timestamp DEFAULT '0000-00-00 00:00:00' NOT NULL, discount_amount double DEFAULT 0 NOT NULL, PRIMARY KEY (order_id, coupon_id), KEY coupon_id (coupon_id), KEY date_created (date_created) ) $collate; CREATE TABLE {$wpdb->prefix}woocommerce_admin_notes ( note_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL, type varchar(20) NOT NULL, locale varchar(20) NOT NULL, title longtext NOT NULL, content longtext NOT NULL, icon varchar(200) NOT NULL, content_data longtext NULL default null, status varchar(200) NOT NULL, source varchar(200) NOT NULL, date_created datetime NOT NULL default '0000-00-00 00:00:00', date_reminder datetime NULL default null, PRIMARY KEY (note_id) ) $collate; CREATE TABLE {$wpdb->prefix}woocommerce_admin_note_actions ( action_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, note_id BIGINT UNSIGNED NOT NULL, name varchar(255) NOT NULL, label varchar(255) NOT NULL, query longtext NOT NULL, PRIMARY KEY (action_id), KEY note_id (note_id) ) $collate; "; return $tables; } /** * Create database tables. */ public static function create_db_tables() { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( self::get_schema() ); } /** * Install plugin. */ public static function install() { // Create tables. self::create_db_tables(); // Initialize report tables. add_action( 'woocommerce_after_register_post_type', array( 'WC_Admin_Api_Init', 'order_product_lookup_store_init' ), 20 ); } /** * Enables the WP REST API for product categories * * @param array $args Default arguments for product_cat taxonomy. * @return array */ public static function show_product_categories_in_rest( $args ) { $args['show_in_rest'] = true; return $args; } /** * Increase per page limit for product categories * * @param array $prepared_args Prepared arguments for query. * @return array */ public static function increase_per_page_limit( $prepared_args ) { $prepared_args['number'] = PHP_INT_MAX; return $prepared_args; } } new WC_Admin_Api_Init();