Skip to content

Commit 30577f8

Browse files
authored
Update/dokan core store and api (#3053)
* update: User meta api response for dokan core store * fix: Add resolver method for vendor id in core data * docs: update Dokan Core Store documentation with complete API reference * fix: correct comments in resolvers and ApiMeta class * docs: fix stale comments and add missing JSDoc descriptions * fix: correct return type annotation and improve docblock formatting
1 parent 9a44aa3 commit 30577f8

File tree

6 files changed

+276
-6
lines changed

6 files changed

+276
-6
lines changed

docs/frontend/stores.md

Lines changed: 122 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,27 +225,145 @@ the global `dokan.{store-name}-store` when your code is bundled.
225225

226226
The `Dokan Core Store` is a `WordPress Data Store` that provides access to the core data of the `Dokan` plugin. This store is available in the `@dokan/stores/core` package.
227227

228+
## Available Selectors
229+
230+
The core store provides the following selectors:
231+
232+
- `getCurrentUser()` - Get the current user object
233+
- `hasCap(capability)` - Check if the current user has a specific capability
234+
- `isVendor()` - Check if the current user is a vendor
235+
- `isVendorStaff()` - Check if the current user is a vendor staff
236+
- `getStoreSettings()` - Get the store settings
237+
- `getGlobalSettings()` - Get the global settings
238+
- `getVendorId()` - Get the vendor ID for the current user
239+
240+
## Available Actions
241+
242+
- `setCurrentUser(user)` - Set the current user
243+
- `setStoreSettings(settings)` - Set the store settings
244+
- `setGlobalSettings(settings)` - Set the global settings
245+
246+
## Usage Examples
247+
248+
### Using Selectors
249+
228250
```js
229251
import { useSelect } from '@wordpress/data';
230252
import coreStore from '@dokan/stores/core';
231253

232254
const App = () => {
255+
// Get current user
256+
const currentUser = useSelect( ( select ) => {
257+
return select( coreStore ).getCurrentUser();
258+
}, [] );
259+
260+
// Check if user is a vendor
261+
const isVendor = useSelect( ( select ) => {
262+
return select( coreStore ).isVendor();
263+
}, [] );
264+
265+
// Check if user is a vendor staff
233266
const isVendorStaff = useSelect( ( select ) => {
234267
return select( coreStore ).isVendorStaff();
235268
}, [] );
236-
237-
const getStoreSettings = useSelect( ( select ) => {
269+
270+
// Check if user has a specific capability
271+
const hasCapability = useSelect( ( select ) => {
272+
return select( coreStore ).hasCap( 'dokandar' );
273+
}, [] );
274+
275+
// Get store settings
276+
const storeSettings = useSelect( ( select ) => {
238277
return select( coreStore ).getStoreSettings();
239278
}, [] );
240279

241-
const currentUser = useSelect( ( select ) => {
242-
return select( coreStore ).getCurrentUser();
280+
// Get global settings
281+
const globalSettings = useSelect( ( select ) => {
282+
return select( coreStore ).getGlobalSettings();
243283
}, [] );
284+
285+
// Get vendor ID
286+
const vendorId = useSelect( ( select ) => {
287+
return select( coreStore ).getVendorId();
288+
}, [] );
289+
};
290+
```
291+
292+
### Using Actions
293+
294+
```js
295+
import { useDispatch } from '@wordpress/data';
296+
import coreStore from '@dokan/stores/core';
297+
298+
const App = () => {
299+
const { setCurrentUser, setStoreSettings, setGlobalSettings } = useDispatch( coreStore );
300+
301+
// Update current user
302+
const updateUser = ( user ) => {
303+
setCurrentUser( user );
304+
};
305+
306+
// Update store settings
307+
const updateStoreSettings = ( settings ) => {
308+
setStoreSettings( settings );
309+
};
310+
311+
// Update global settings
312+
const updateGlobalSettings = ( settings ) => {
313+
setGlobalSettings( settings );
314+
};
315+
};
316+
```
317+
318+
### Using Resolvers (Async Data Fetching)
319+
320+
```js
321+
import { resolveSelect } from '@wordpress/data';
322+
import coreStore from '@dokan/stores/core';
323+
324+
const App = () => {
325+
// Fetch current user asynchronously
326+
const fetchCurrentUser = async () => {
327+
await resolveSelect( coreStore ).getCurrentUser();
328+
};
329+
330+
// Fetch store settings asynchronously
331+
const fetchStoreSettings = async () => {
332+
const settings = await resolveSelect( coreStore ).getStoreSettings();
333+
return settings;
334+
};
335+
336+
// Fetch global settings asynchronously
337+
const fetchGlobalSettings = async () => {
338+
await resolveSelect( coreStore ).getGlobalSettings();
339+
};
340+
341+
// Check capability (triggers user fetch if needed)
342+
const checkCapability = async ( capability ) => {
343+
await resolveSelect( coreStore ).hasCap( capability );
344+
};
345+
346+
// Check if vendor (triggers user fetch if needed)
347+
const checkIsVendor = async () => {
348+
await resolveSelect( coreStore ).isVendor();
349+
};
350+
351+
// Check if vendor staff (triggers user fetch if needed)
352+
const checkIsVendorStaff = async () => {
353+
await resolveSelect( coreStore ).isVendorStaff();
354+
};
355+
356+
// Get vendor ID (triggers user fetch if needed)
357+
const fetchVendorId = async () => {
358+
await resolveSelect( coreStore ).getVendorId();
359+
};
244360
};
245361
```
246362

247363
## Use Dokan Hooks
248364

365+
For convenience, you can also use the Dokan hooks which provide a simpler API:
366+
249367
```js
250368
import { usePermission, useCurrentUser } from '@dokan/hooks';
251369

@@ -259,5 +377,4 @@ const App = () => {
259377
const isDokandar = usePermission('dokandar'); // you can pass string as single permission or pass string[] array for multiple permission checking
260378
const currentUser = useCurrentUser();
261379
}
262-
263380
```

includes/DependencyManagement/Providers/CommonServiceProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class CommonServiceProvider extends BaseServiceProvider {
2525
\WeDevs\Dokan\Order\RefundHandler::class,
2626
\WeDevs\Dokan\Exceptions\Handler::class,
2727
\WeDevs\Dokan\Shortcodes\FullWidthVendorLayout::class,
28+
\WeDevs\Dokan\Vendor\ApiMeta::class,
2829
];
2930

3031
/**

includes/Utilities/VendorUtil.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class VendorUtil {
88
*
99
* @since 4.0.6
1010
*
11-
* @return void
11+
* @return string The default store banner URL.
1212
*/
1313
public static function get_vendor_default_banner_url(): string {
1414
// Define the default store banner URL from plugin assets
@@ -52,4 +52,38 @@ public static function get_vendor_default_avatar_url(): string {
5252
*/
5353
return apply_filters( 'dokan_get_vendor_default_avatar_url', $avatar_url );
5454
}
55+
56+
57+
/**
58+
* Get the vendor/store ID associated with a user.
59+
*
60+
* This method determines the vendor ID based on the user's role:
61+
* - Vendors: Returns their own user ID as the vendor ID
62+
* - Vendor staff: Returns their parent vendor's ID (stored in user meta)
63+
* - Other users: Returns 0 if not associated with any vendor
64+
*
65+
* @since DOKAN_SINCE
66+
*
67+
* @param int $user_id Optional. The user ID to get the vendor ID for. Defaults to 0 (current user).
68+
*
69+
* @return int The vendor/store ID. Returns 0 if the user is not a vendor or vendor staff,
70+
* or if vendor ID cannot be determined.
71+
*/
72+
public static function get_vendor_id_for_user( int $user_id = 0 ): int {
73+
if ( empty( $user_id ) ) {
74+
$user_id = dokan_get_current_user_id();
75+
}
76+
77+
if ( dokan_is_user_seller( $user_id, true ) ) {
78+
return (int) $user_id;
79+
}
80+
81+
if ( user_can( $user_id, 'vendor_staff' ) ) {
82+
$vendor_id = (int) get_user_meta( $user_id, '_vendor_id', true );
83+
84+
return $vendor_id;
85+
}
86+
87+
return 0;
88+
}
5589
}

includes/Vendor/ApiMeta.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
namespace WeDevs\Dokan\Vendor;
4+
5+
use WeDevs\Dokan\Utilities\VendorUtil;
6+
7+
/**
8+
* ApiMeta Class.
9+
*
10+
* Handles Dokan vendor user meta registration for the REST API.
11+
*/
12+
class ApiMeta {
13+
/**
14+
* Constructor.
15+
*/
16+
public function __construct() {
17+
add_action( 'rest_api_init', array( $this, 'register_user_data' ) );
18+
}
19+
20+
/**
21+
* Registers Dokan specific user data to the WordPress user API.
22+
*
23+
* @since DOKAN_SINCE
24+
*
25+
* @return void
26+
*/
27+
public function register_user_data() {
28+
register_rest_field(
29+
'user',
30+
'dokan_meta',
31+
array(
32+
'get_callback' => array( $this, 'get_user_data_values' ),
33+
'schema' => null,
34+
)
35+
);
36+
}
37+
38+
/**
39+
* Fetches the vendor-specific user data values for returning via the REST API.
40+
*
41+
* @since DOKAN_SINCE
42+
*
43+
* @param array $user Current user data from REST API.
44+
* @return array Vendor-specific user data including vendor_id.
45+
*/
46+
public function get_user_data_values( $user ) {
47+
$values = [
48+
'vendor_id' => VendorUtil::get_vendor_id_for_user( (int) $user['id'] ),
49+
];
50+
51+
foreach ( $this->get_user_data_fields() as $field ) {
52+
$values[ $field ] = self::get_user_data_field( $user['id'], $field );
53+
}
54+
55+
/**
56+
* Filter the user data values exposed over the WordPress user endpoint.
57+
*
58+
* @since DOKAN_SINCE
59+
*
60+
* @param array $values Array of user data values.
61+
* @param array $user Current user data from REST API.
62+
*/
63+
return apply_filters( 'dokan_vendor_api_meta_get_user_data_values', $values, $user );
64+
}
65+
66+
/**
67+
* We store some Dokan specific user meta attached to users endpoint,
68+
* so that we can track certain preferences or values for vendors.
69+
* Additional fields can be added in the function below, and then used via Dokan's currentUser data.
70+
*
71+
* @since DOKAN_SINCE
72+
*
73+
* @return array Fields to expose over the WP user endpoint.
74+
*/
75+
public function get_user_data_fields() {
76+
/**
77+
* Filter user data fields exposed over the WordPress user endpoint.
78+
*
79+
* @since DOKAN_SINCE
80+
*
81+
* @param array $fields Array of fields to expose over the WP user endpoint.
82+
*/
83+
return apply_filters( 'dokan_vendor_get_user_data_fields', [] );
84+
}
85+
86+
/**
87+
* Helper to retrieve user data fields.
88+
*
89+
* @since DOKAN_SINCE
90+
*
91+
* @param int $user_id User ID.
92+
* @param string $field Field name.
93+
* @return mixed The user field value.
94+
*/
95+
public static function get_user_data_field( $user_id, $field ) {
96+
$meta_value = get_user_meta( $user_id, $field, true );
97+
98+
return $meta_value;
99+
}
100+
}

src/stores/core/resolvers.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ const resolvers = {
7878
async ( { resolveSelect } ) => {
7979
return await resolveSelect.getCurrentUser();
8080
},
81+
82+
/**
83+
* Get the vendor ID for the current user.
84+
*/
85+
getVendorId:
86+
() =>
87+
async ( { resolveSelect } ) => {
88+
return await resolveSelect.getCurrentUser();
89+
},
8190
};
8291

8392
export default resolvers;

src/stores/core/selectors.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ const selectors = {
8787
getGlobalSettings( state: CoreState ) {
8888
return state.global;
8989
},
90+
91+
/**
92+
* Get the vendor ID for the current user.
93+
*
94+
* @param state
95+
*/
96+
getVendorId( state: CoreState ) {
97+
return state.currentUser?.dokan_meta?.vendor_id;
98+
},
9099
};
91100

92101
export default selectors;

0 commit comments

Comments
 (0)