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
24 changes: 24 additions & 0 deletions .github/workflows/reusable/setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Build

on:
workflow_call:
inputs:
node-version:
description: Version of Node to use
default: "20.x"
pnpm-version:
description: Version of pnpm to use
default: "10.8.0"

jobs:
setup:
name: Setup
runs-on: ubuntu-latest
steps:
- name: 🏗 Checkout code
uses: actions/checkout@v4

- name: 🏗 Setup pnpm
uses: pnpm/action-setup@v4
with:
version: ${{ inputs.pnpm-version }}
2 changes: 0 additions & 2 deletions .github/workflows/wp-engine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ name: Deploy to WP Engine

on:
push:
branches:
- main

jobs:
build:
Expand Down
Binary file not shown.
Binary file added assets/img/wcpos-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/img/wcpos-pro-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion assets/js/indexeddb.worker.js

Large diffs are not rendered by default.

148 changes: 78 additions & 70 deletions includes/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* @author Paul Kilmurray <paul@kilbot.com>
*
* @see http://wcpos.com
* @package WCPOS\WooCommercePOS
*/

namespace WCPOS\WooCommercePOS;
Expand All @@ -17,10 +16,6 @@
use WP_REST_Response;
use WP_REST_Server;


/**
*
*/
class API {
/**
* WCPOS REST API namespaces and endpoints.
Expand Down Expand Up @@ -62,7 +57,7 @@ public function __construct() {
/**
* Register routes for all controllers.
*/
public function register_routes() {
public function register_routes(): void {
/**
* Filter the list of controller classes used in the WooCommerce POS REST API.
*
Expand All @@ -73,27 +68,27 @@ public function register_routes() {
* @since 1.5.0
*
* @param array $controllers Associative array of controller identifiers to their corresponding class names.
* - 'auth' => Fully qualified name of the class handling authentication.
* - 'settings' => Fully qualified name of the class handling settings.
* - 'stores' => Fully qualified name of the class handling stores management.
* - 'products' => Fully qualified name of the class handling products.
* - 'product_variations' => Fully qualified name of the class handling product variations.
* - 'orders' => Fully qualified name of the class handling orders.
* - 'customers' => Fully qualified name of the class handling customers.
* - 'product_tags' => Fully qualified name of the class handling product tags.
* - 'product_categories' => Fully qualified name of the class handling product categories.
* - 'taxes' => Fully qualified name of the class handling taxes.
* - 'shipping_methods' => Fully qualified name of the class handling shipping methods.
* - 'tax_classes' => Fully qualified name of the class handling tax classes.
* - 'order_statuses' => Fully qualified name of the class handling order statuses.
* - 'auth' => Fully qualified name of the class handling authentication.
* - 'settings' => Fully qualified name of the class handling settings.
* - 'cashier' => Fully qualified name of the class handling cashier management.
* - 'products' => Fully qualified name of the class handling products.
* - 'product_variations' => Fully qualified name of the class handling product variations.
* - 'orders' => Fully qualified name of the class handling orders.
* - 'customers' => Fully qualified name of the class handling customers.
* - 'product_tags' => Fully qualified name of the class handling product tags.
* - 'product_categories' => Fully qualified name of the class handling product categories.
* - 'taxes' => Fully qualified name of the class handling taxes.
* - 'shipping_methods' => Fully qualified name of the class handling shipping methods.
* - 'tax_classes' => Fully qualified name of the class handling tax classes.
* - 'order_statuses' => Fully qualified name of the class handling order statuses.
*/
$classes = apply_filters(
'woocommerce_pos_rest_api_controllers',
array(
// woocommerce pos rest api controllers.
'auth' => API\Auth::class,
'settings' => API\Settings::class,
'stores' => API\Stores::class,
'cashier' => API\Cashier::class,

// extend WC REST API controllers.
'products' => API\Products_Controller::class,
Expand All @@ -102,6 +97,7 @@ public function register_routes() {
'customers' => API\Customers_Controller::class,
'product_tags' => API\Product_Tags_Controller::class,
'product_categories' => API\Product_Categories_Controller::class,
'product_brands' => API\Product_Brands_Controller::class,
'taxes' => API\Taxes_Controller::class,
'shipping_methods' => API\Shipping_Methods_Controller::class,
'tax_classes' => API\Tax_Classes_Controller::class,
Expand Down Expand Up @@ -197,7 +193,7 @@ public function rest_authentication_errors( $errors ) {
/**
* Extract the Authorization Bearer token from the request.
*
* @return string|false
* @return false|string
*/
public function get_auth_header() {
// Check if HTTP_AUTHORIZATION is set in $_SERVER
Expand All @@ -222,7 +218,7 @@ public function get_auth_header() {
/**
* Adds info to the WP REST API index response.
* - UUID
* - Version Info
* - Version Info.
*
* @param WP_REST_Response $response Response data.
*
Expand All @@ -234,11 +230,20 @@ public function rest_index( WP_REST_Response $response ): WP_REST_Response {
$uuid = Uuid::uuid4()->toString();
update_option( 'woocommerce_pos_uuid', $uuid );
}
$response->data['uuid'] = $uuid;
$response->data['wp_version'] = get_bloginfo( 'version' );
$response->data['wc_version'] = WC()->version;
$response->data['uuid'] = $uuid;
$response->data['wp_version'] = get_bloginfo( 'version' );
$response->data['wc_version'] = WC()->version;
$response->data['wcpos_version'] = VERSION;
$response->data['use_jwt_as_param'] = woocommerce_pos_get_settings( 'tools', 'use_jwt_as_param' );

// Add wcpos authentication endpoint
if ( ! isset( $response->data['authentication'] ) ) {
$response->data['authentication'] = array();
}
$response->data['authentication']['wcpos'] = array(
'endpoints' => array(
'authorization' => home_url( 'wcpos-auth' ),
),
);

/**
* Remove the routes from the response.
Expand Down Expand Up @@ -289,44 +294,6 @@ public function rest_pre_dispatch( $result, $server, $request ) {
return $result;
}

/**
* Some servers have a limit on the number of include/exclude we can use in a request.
* Worst thing is there is often no error message, the request returns an empty response.
*
* For example, WP Engine has a limit of 1024 characters?
* https://wpengine.com/support/using-dev-tools/#Long_Queries_in_wp_db
*
* @TODO - For long queries, I should find a better solution than this.
*
* @param string|array $param_value
* @param int $max_length
* @return array
*/
private function shorten_param_array( $param_value, $max_length ) {
$param_array = is_array( $param_value ) ? $param_value : explode( ',', $param_value );
$param_string = implode( ',', $param_array );

if ( strlen( $param_string ) > $max_length ) {
shuffle( $param_array ); // Shuffle to randomize

$new_param_string = '';
$random_param_array = array();

foreach ( $param_array as $id ) {
if ( strlen( $new_param_string . $id ) < $max_length ) {
$new_param_string .= $id . ',';
$random_param_array[] = $id;
} else {
break; // Stop when maximum length is reached
}
}

return $random_param_array;
}

return $param_array;
}

/**
* Filters the REST API dispatch request result.
*
Expand All @@ -338,13 +305,13 @@ private function shorten_param_array( $param_value, $max_length ) {
* @return mixed
*/
public function rest_dispatch_request( $dispatch_result, $request, $route, $handler ) {
if ( isset( $handler['callback'] ) && is_array( $handler['callback'] ) && isset( $handler['callback'][0] ) ) {
if ( isset( $handler['callback'] ) && \is_array( $handler['callback'] ) && isset( $handler['callback'][0] ) ) {
$controller = $handler['callback'][0];

// Check if the controller object is one of our registered controllers.
foreach ( $this->controllers as $key => $wcpos_controller ) {
if ( $controller === $wcpos_controller ) {
/**
/*
* I'm adding some additional PHP settings before the response. Placing them here so they only apply to the POS API.
*
* - error_reporting(0) - Turn off error reporting
Expand All @@ -365,6 +332,7 @@ public function rest_dispatch_request( $dispatch_result, $request, $route, $hand
if ( method_exists( $controller, 'wcpos_dispatch_request' ) ) {
return $controller->wcpos_dispatch_request( $dispatch_result, $request, $route, $handler );
}

break;
}
}
Expand All @@ -373,6 +341,45 @@ public function rest_dispatch_request( $dispatch_result, $request, $route, $hand
return $dispatch_result;
}

/**
* Some servers have a limit on the number of include/exclude we can use in a request.
* Worst thing is there is often no error message, the request returns an empty response.
*
* For example, WP Engine has a limit of 1024 characters?
* https://wpengine.com/support/using-dev-tools/#Long_Queries_in_wp_db
*
* @TODO - For long queries, I should find a better solution than this.
*
* @param array|string $param_value
* @param int $max_length
*
* @return array
*/
private function shorten_param_array( $param_value, $max_length ) {
$param_array = \is_array( $param_value ) ? $param_value : explode( ',', $param_value );
$param_string = implode( ',', $param_array );

if ( \strlen( $param_string ) > $max_length ) {
shuffle( $param_array ); // Shuffle to randomize

$new_param_string = '';
$random_param_array = array();

foreach ( $param_array as $id ) {
if ( \strlen( $new_param_string . $id ) < $max_length ) {
$new_param_string .= $id . ',';
$random_param_array[] = $id;
} else {
break; // Stop when maximum length is reached
}
}

return $random_param_array;
}

return $param_array;
}

/**
* Check the Authorization header for a Bearer token.
*
Expand All @@ -383,25 +390,26 @@ public function rest_dispatch_request( $dispatch_result, $request, $route, $hand
private function authenticate( $user_id ) {
// check if there is an auth header
$auth_header = $this->get_auth_header();
if ( ! is_string( $auth_header ) ) {
if ( ! \is_string( $auth_header ) ) {
return $user_id;
}

// Extract Bearer token from Authorization Header
list($token) = sscanf( $auth_header, 'Bearer %s' );

if ( $token ) {
$auth_service = Auth::instance();
$auth_service = Auth::instance();
$decoded_token = $auth_service->validate_token( $token );

// Check if validate_token returned WP_Error and user_id is null
if ( is_wp_error( $decoded_token ) && $user_id === null ) {
return $decoded_token;
if ( is_wp_error( $decoded_token ) && null === $user_id ) {
return $decoded_token;
}

// If the token is valid, set the user_id
if ( ! is_wp_error( $decoded_token ) ) {
$user_id = $decoded_token->data->user->id;

return absint( $user_id );
}
}
Expand Down
Loading