Skip to content

Commit 22571d9

Browse files
committed
add cashier api endpoint
1 parent 65e4849 commit 22571d9

File tree

6 files changed

+535
-214
lines changed

6 files changed

+535
-214
lines changed

includes/API.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function register_routes(): void {
7070
* @param array $controllers Associative array of controller identifiers to their corresponding class names.
7171
* - 'auth' => Fully qualified name of the class handling authentication.
7272
* - 'settings' => Fully qualified name of the class handling settings.
73-
* - 'stores' => Fully qualified name of the class handling stores management.
73+
* - 'cashier' => Fully qualified name of the class handling cashier management.
7474
* - 'products' => Fully qualified name of the class handling products.
7575
* - 'product_variations' => Fully qualified name of the class handling product variations.
7676
* - 'orders' => Fully qualified name of the class handling orders.
@@ -88,7 +88,7 @@ public function register_routes(): void {
8888
// woocommerce pos rest api controllers.
8989
'auth' => API\Auth::class,
9090
'settings' => API\Settings::class,
91-
'stores' => API\Stores::class,
91+
'cashier' => API\Cashier::class,
9292

9393
// extend WC REST API controllers.
9494
'products' => API\Products_Controller::class,

includes/API/Cashier.php

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
<?php
2+
/**
3+
* Cashier API.
4+
*/
5+
6+
namespace WCPOS\WooCommercePOS\API;
7+
8+
\defined( 'ABSPATH' ) || die;
9+
10+
if ( ! class_exists( 'WP_REST_Controller' ) ) {
11+
return;
12+
}
13+
14+
use Exception;
15+
use WCPOS\WooCommercePOS\Abstracts\Store;
16+
use WCPOS\WooCommercePOS\Services\Cashier as CashierService;
17+
use const WCPOS\WooCommercePOS\SHORT_NAME;
18+
use WP_Error;
19+
use WP_REST_Controller;
20+
use WP_REST_Request;
21+
use WP_REST_Response;
22+
use WP_REST_Server;
23+
use WP_User;
24+
25+
/**
26+
* Cashier API Controller.
27+
*/
28+
class Cashier extends WP_REST_Controller {
29+
/**
30+
* Endpoint namespace.
31+
*
32+
* @var string
33+
*/
34+
protected $namespace = SHORT_NAME . '/v1';
35+
36+
/**
37+
* Route base.
38+
*
39+
* @var string
40+
*/
41+
protected $rest_base = 'cashier';
42+
43+
/**
44+
* Register the routes for the cashier controller.
45+
*/
46+
public function register_routes(): void {
47+
// Get cashier data: /wcpos/v1/cashier/{id}
48+
register_rest_route(
49+
$this->namespace,
50+
'/' . $this->rest_base . '/(?P<id>[\d]+)',
51+
array(
52+
'methods' => WP_REST_Server::READABLE,
53+
'callback' => array( $this, 'get_cashier' ),
54+
'permission_callback' => array( $this, 'check_cashier_permissions' ),
55+
'args' => array(
56+
'id' => array(
57+
'description' => __( 'Unique identifier for the cashier (WordPress user ID).', 'woocommerce-pos' ),
58+
'type' => 'integer',
59+
'required' => true,
60+
),
61+
),
62+
)
63+
);
64+
65+
// Get cashier stores: /wcpos/v1/cashier/{id}/stores
66+
register_rest_route(
67+
$this->namespace,
68+
'/' . $this->rest_base . '/(?P<id>[\d]+)/stores',
69+
array(
70+
'methods' => WP_REST_Server::READABLE,
71+
'callback' => array( $this, 'get_cashier_stores' ),
72+
'permission_callback' => array( $this, 'check_cashier_permissions' ),
73+
'args' => array(
74+
'id' => array(
75+
'description' => __( 'Unique identifier for the cashier (WordPress user ID).', 'woocommerce-pos' ),
76+
'type' => 'integer',
77+
'required' => true,
78+
),
79+
),
80+
)
81+
);
82+
83+
// Get specific store for cashier: /wcpos/v1/cashier/{id}/stores/{store_id}
84+
register_rest_route(
85+
$this->namespace,
86+
'/' . $this->rest_base . '/(?P<id>[\d]+)/stores/(?P<store_id>[\d]+)',
87+
array(
88+
'methods' => WP_REST_Server::READABLE,
89+
'callback' => array( $this, 'get_cashier_store' ),
90+
'permission_callback' => array( $this, 'check_cashier_permissions' ),
91+
'args' => array(
92+
'id' => array(
93+
'description' => __( 'Unique identifier for the cashier (WordPress user ID).', 'woocommerce-pos' ),
94+
'type' => 'integer',
95+
'required' => true,
96+
),
97+
'store_id' => array(
98+
'description' => __( 'Unique identifier for the store.', 'woocommerce-pos' ),
99+
'type' => 'integer',
100+
'required' => true,
101+
),
102+
),
103+
)
104+
);
105+
}
106+
107+
/**
108+
* Check permissions for cashier endpoints.
109+
*
110+
* Ensures the user is authenticated and can only access their own data.
111+
*
112+
* @param WP_REST_Request $request The REST request object.
113+
*
114+
* @return bool|WP_Error True if authorized, WP_Error otherwise.
115+
*/
116+
public function check_cashier_permissions( WP_REST_Request $request ) {
117+
// Check if user is authenticated
118+
if ( ! is_user_logged_in() ) {
119+
return new WP_Error(
120+
'woocommerce_pos_rest_unauthorized',
121+
__( 'Authentication required.', 'woocommerce-pos' ),
122+
array( 'status' => 401 )
123+
);
124+
}
125+
126+
$current_user_id = get_current_user_id();
127+
$requested_id = (int) $request->get_param( 'id' );
128+
129+
// Check if the requested user exists
130+
$user = get_user_by( 'id', $requested_id );
131+
if ( ! $user ) {
132+
return new WP_Error(
133+
'woocommerce_pos_cashier_not_found',
134+
__( 'Cashier not found.', 'woocommerce-pos' ),
135+
array( 'status' => 404 )
136+
);
137+
}
138+
139+
$cashier_service = CashierService::instance();
140+
141+
// Check if user has POS cashier permissions
142+
if ( ! $cashier_service->has_cashier_permissions( $user ) ) {
143+
return new WP_Error(
144+
'woocommerce_pos_rest_forbidden',
145+
__( 'User does not have POS cashier permissions.', 'woocommerce-pos' ),
146+
array( 'status' => 403 )
147+
);
148+
}
149+
150+
// Validate access permissions
151+
if ( ! $cashier_service->validate_cashier_access( $current_user_id, $requested_id ) ) {
152+
return new WP_Error(
153+
'woocommerce_pos_rest_forbidden',
154+
__( 'You can only access your own cashier data.', 'woocommerce-pos' ),
155+
array( 'status' => 403 )
156+
);
157+
}
158+
159+
return true;
160+
}
161+
162+
/**
163+
* Get cashier data.
164+
*
165+
* @param WP_REST_Request $request The REST request object.
166+
*
167+
* @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
168+
*/
169+
public function get_cashier( WP_REST_Request $request ) {
170+
$user_id = (int) $request->get_param( 'id' );
171+
$user = get_user_by( 'id', $user_id );
172+
173+
if ( ! $user ) {
174+
return new WP_Error(
175+
'woocommerce_pos_cashier_not_found',
176+
__( 'Cashier not found.', 'woocommerce-pos' ),
177+
array( 'status' => 404 )
178+
);
179+
}
180+
181+
$cashier_service = CashierService::instance();
182+
$data = $cashier_service->get_cashier_data( $user, true );
183+
184+
/**
185+
* Filter cashier data for REST API response.
186+
*
187+
* @param array $data Cashier data.
188+
* @param WP_User $user User object.
189+
* @param WP_REST_Request $request Request object.
190+
*/
191+
$data = apply_filters( 'woocommerce_pos_rest_prepare_cashier', $data, $user, $request );
192+
193+
return rest_ensure_response( $data );
194+
}
195+
196+
/**
197+
* Get stores accessible by the cashier.
198+
*
199+
* @param WP_REST_Request $request The REST request object.
200+
*
201+
* @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
202+
*/
203+
public function get_cashier_stores( WP_REST_Request $request ) {
204+
$user_id = (int) $request->get_param( 'id' );
205+
$user = get_user_by( 'id', $user_id );
206+
207+
if ( ! $user ) {
208+
return new WP_Error(
209+
'woocommerce_pos_cashier_not_found',
210+
__( 'Cashier not found.', 'woocommerce-pos' ),
211+
array( 'status' => 404 )
212+
);
213+
}
214+
215+
try {
216+
$cashier_service = CashierService::instance();
217+
$stores = $cashier_service->get_accessible_stores( $user );
218+
$response = array();
219+
220+
foreach ( $stores as $store ) {
221+
$data = $this->prepare_store_for_response( $store, $request );
222+
$response[] = $this->prepare_response_for_collection( $data );
223+
}
224+
225+
$response = rest_ensure_response( $response );
226+
$response->header( 'X-WP-Total', \count( $stores ) );
227+
$response->header( 'X-WP-TotalPages', 1 );
228+
229+
return $response;
230+
} catch ( Exception $e ) {
231+
return new WP_Error(
232+
'woocommerce_pos_stores_retrieval_failed',
233+
__( 'Failed to retrieve store data.', 'woocommerce-pos' ),
234+
array( 'status' => 500 )
235+
);
236+
}
237+
}
238+
239+
/**
240+
* Get a specific store for the cashier.
241+
*
242+
* @param WP_REST_Request $request The REST request object.
243+
*
244+
* @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
245+
*/
246+
public function get_cashier_store( WP_REST_Request $request ) {
247+
$user_id = (int) $request->get_param( 'id' );
248+
$store_id = (int) $request->get_param( 'store_id' );
249+
250+
$user = get_user_by( 'id', $user_id );
251+
if ( ! $user ) {
252+
return new WP_Error(
253+
'woocommerce_pos_cashier_not_found',
254+
__( 'Cashier not found.', 'woocommerce-pos' ),
255+
array( 'status' => 404 )
256+
);
257+
}
258+
259+
$cashier_service = CashierService::instance();
260+
$store = $cashier_service->get_accessible_store( $user, $store_id );
261+
262+
if ( ! $store ) {
263+
return new WP_Error(
264+
'woocommerce_pos_store_not_found',
265+
__( 'Store not found or not accessible by this cashier.', 'woocommerce-pos' ),
266+
array( 'status' => 404 )
267+
);
268+
}
269+
270+
$data = $this->prepare_store_for_response( $store, $request );
271+
272+
return rest_ensure_response( $data );
273+
}
274+
275+
276+
277+
/**
278+
* Prepare store data for response.
279+
*
280+
* @param Store $store Store object.
281+
* @param WP_REST_Request $request Request object.
282+
*
283+
* @return array Prepared store data.
284+
*/
285+
protected function prepare_store_for_response( Store $store, WP_REST_Request $request ): array {
286+
$data = $store->get_data();
287+
288+
/*
289+
* Filter store data for REST API response.
290+
*
291+
* @param array $data Store data.
292+
* @param Store $store Store object.
293+
* @param WP_REST_Request $request Request object.
294+
*/
295+
return apply_filters( 'woocommerce_pos_rest_prepare_store', $data, $store, $request );
296+
}
297+
}

0 commit comments

Comments
 (0)