Skip to content
Merged
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
46 changes: 34 additions & 12 deletions .vitepress/theme/components/VersionSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
<script setup lang="ts">
import { useRoute, useRouter } from 'vitepress'
import { computed } from 'vue'
import { data as pages } from '../pages.data.mjs'

const LATEST = '3.0'
const VERSION_PATH = /^\/(\d+\.\d+)(\/.*)?$/

const versions = [
{ label: 'master', value: 'master' },
Expand All @@ -35,22 +37,42 @@ const versions = [
const route = useRoute()
const router = useRouter()

const currentVersion = computed(() => {
const match = route.path.match(/^\/(0\.1|0\.2|0\.3|1\.0|2\.0|2\.1)(\/.*)?$/)
return match ? match[1] : LATEST
})
const knownPages = new Set(pages)

const restPath = computed(() => {
const match = route.path.match(/^\/(0\.1|0\.2|0\.3|1\.0|2\.0|2\.1)(\/.*)?$/)
return match && match[2] ? match[2] : '/'
})
const match = computed(() => route.path.match(VERSION_PATH))

const currentVersion = computed(() => match.value ? match.value[1] : LATEST)

const restPath = computed(() => match.value && match.value[2] ? match.value[2] : '/')

function exists(path: string) {
return knownPages.has(path) || knownPages.has(path.replace(/\.html$/, ''))
}

/**
* The same page in another version, or that version's landing page when the
* page does not exist there — switching versions must never land on a 404.
*/
function resolveTarget(version: string) {
const candidate = `/${version}${restPath.value}`

if (restPath.value !== '/' && exists(candidate)) {
return candidate
}

const landing = `/${version}/prologue/`

if (exists(landing)) {
return landing
}

return pages.find((url) => url.startsWith(`/${version}/`)) ?? landing
}

function onChange(e: Event) {
const newVersion = (e.target as HTMLSelectElement).value
const selected = (e.target as HTMLSelectElement).value
// 'master' is an alias that always sends users to the latest version.
const target = newVersion === 'master' ? LATEST : newVersion
const newPath = `/${target}${restPath.value}`
router.go(newPath)
router.go(resolveTarget(selected === 'master' ? LATEST : selected))
}
</script>

Expand Down
9 changes: 9 additions & 0 deletions .vitepress/theme/pages.data.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createContentLoader } from 'vitepress'

/**
* Every documented page URL, used by the version switcher to fall back to a
* version's landing page instead of navigating to a path that version lacks.
*/
export default createContentLoader('*/**/*.md', {
transform: (raw) => raw.map(({ url }) => url)
})
9 changes: 7 additions & 2 deletions .vitepress/version-configs/3.0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,8 @@ export default [
['agentic/ai-agent', 'AI Agent Integration'],
['agentic/magic-ai-platform', 'MagicAI Platform Management'],
['agentic/agent-skills', 'Agentic Skills'],
['agentic/mcp-server', 'MCP Server'],
['agentic/building-integrations', 'Building an Integration with AI'],
['agentic/building-agent-tools', 'Building Custom Agent Tools'],
['agentic/extending-mcp', 'Extending the MCP Bridge'],
['agentic/recipes', 'Agentic Recipes'],
])
},
Expand All @@ -134,6 +132,7 @@ export default [
collapsed: false,
items: setVersionPrefix([
['api/whats-new-v3', "What's New in v3.0"],
['api/migrating-your-client', 'Migrating an API Client'],
['api/configuration', 'Configuration'],
['api/authenticate', 'Authentication'],
['api/attribute', 'Attribute'],
Expand All @@ -146,9 +145,15 @@ export default [
['api/product', 'Product'],
['api/configurable_products', 'Configurable Products'],
['api/media', 'Media'],
['api/association_types', 'Association Types'],
['api/variant_structures', 'Variant Structures'],
['api/passports', 'Digital Product Passports'],
['api/channel', 'Channel'],
['api/locales', 'Locales'],
['api/currency', 'Currency'],
['api/explanation', 'Response Structure'],
['api/getting-started-with-the-api', 'Getting Started'],
['api/postman_collection', 'Postman Collection'],
])
}
]
8 changes: 4 additions & 4 deletions src/3.0/advanced/cli-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ UnoPim provides a set of Artisan commands for managing your PIM installation. Th
| `php artisan unopim:install:demo-data` | Seed the sample catalog (`--force` to re-seed, `--scale=large` for a 2,000-product performance dataset) |
| `php artisan unopim:version` | Display the current UnoPim version |
| `php artisan unopim:publish` | Publish UnoPim assets and config (`--force` to overwrite) |
| `php artisan unopim:user:create` | Create an admin user (`--name`, `--email`, password, UI locale, timezone, admin flag) |
| `php artisan unopim:user:create` | Create a user (`--name=`, `--email=`, `--password=`, `--ui_locale=`, `--timezone=`, `--admin`) |
| `php artisan unopim:images:purge-unused` | Remove unused images from storage (`--dry-run` to preview) |
| `php artisan unopim:translations:check` | Audit translation files across all packages against the `en_US` canonical set (`--locale=`, `--package=`) |

Expand All @@ -27,7 +27,7 @@ UnoPim provides a set of Artisan commands for managing your PIM installation. Th

| Command | Description |
|---------|-------------|
| `php artisan unopim:completeness:recalculate` | Recalculate product completeness (`--family=`, `--product=`, or all) |
| `php artisan unopim:completeness:recalculate` | Recalculate product completeness (`--family=`, `--product=`, repeatable `--products=`, or `--all`) |
| `php artisan unopim:variants:strip-redundant` | <Badge type="tip" text="3.0" /> Remove child attribute values that duplicate an inherited ancestor value. Dry-run by default — pass `--apply` to write, `--product=` to scope |
| `php artisan unopim:variants:resync` | <Badge type="tip" text="3.0" /> Rebuild derived data (completeness, search index) for variant subtrees (`--product=`, `--all`) |
| `php artisan measurement:recalculate` | <Badge type="tip" text="3.0" /> Rebuild the stored base value of every product measurement from current family definitions (`--family=`, `--chunk=200`) |
Expand Down Expand Up @@ -65,7 +65,7 @@ See [Digital Product Passport](digital-product-passport) for the preset config s
| Command | Description |
|---------|-------------|
| `php artisan ai-agent:embeddings:index` | <Badge type="tip" text="3.0" /> Queue (re)indexing of product embeddings into the AI vector store (`--since=`, `--batch=`) |
| `php artisan ai-agent:quality-monitor` | Scan the catalog for data-quality issues (`--channel=`, `--locale=`) |
| `php artisan ai-agent:quality-monitor` | Scan the catalog for data-quality issues (`--channel=default`, `--locale=en_US`, `--limit=500`) |
| `php artisan ai-agent:cleanup` | Clean up temporary AI files (`--days=7`, `--dry-run`) |

## Scheduled Commands
Expand All @@ -91,7 +91,7 @@ Make sure the scheduler is running:
Most heavy work is queued. A production worker should listen on every queue in use:

```bash
php artisan queue:work --queue="system,completeness,publication,default"
php artisan queue:work --queue="system,completeness,publication,webhooks,default"
```

The `publication` queue (new in 3.0) carries all Digital Product Passport publishing, bulk transitions, and view-count aggregation. See [Queue Management](queue-management) for Supervisor configuration.
4 changes: 4 additions & 0 deletions src/3.0/advanced/digital-product-passport.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,7 @@ All publishing, bulk transitions and view counting run on the `publication` queu
php artisan queue:work --queue=publication
```
:::

## REST API

Passports are fully manageable over the REST API — list publications, read them per SKU, publish, withdraw, reinstate, and redact. See [Digital Product Passports](../api/passports) in the API reference.
2 changes: 1 addition & 1 deletion src/3.0/advanced/elasticsearch-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ php artisan unopim:category:index

## Filter Improvements (v2.0.0)

UnoPim v2.0.0 includes several improvements to Elasticsearch filter handling:
UnoPim includes several improvements to Elasticsearch filter handling:

- **SKU Filters** — Improved handling for exact and partial SKU matching.
- **Text Filters** — Better support for text-based attribute filtering with improved tokenization.
Expand Down
10 changes: 5 additions & 5 deletions src/3.0/advanced/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ In UnoPim, events and listeners are organized in a clear and structured manner:

This organization makes it easy to manage and locate the event-driven components of your application.

To learn in detail about Controllers, you can visit the Laravel documentation [here](https://laravel.com/docs/10.x/events).
To learn in detail about events, you can visit the Laravel documentation [here](https://laravel.com/docs/13.x/events).

## Creating an Event Class

Expand Down Expand Up @@ -51,7 +51,7 @@ class EventServiceProvider extends ServiceProvider
{
//...

Event::listen('catalog.attribute.create.after', 'Webkul\Catalog\Listeners\Attribute@handleAttributeCreated');
Event::listen('catalog.attribute.create.after', 'App\Listeners\AttributeListener@handleAttributeCreated');
}
}
```
Expand All @@ -63,9 +63,9 @@ In UnoPim, events are typically fired before and after the execution of CRUD ope
For example, you might have events fired during product creation, updating, or deletion. Here’s an example of firing events before and after saving a product:

```php
namespace Webkul\Catalog\Repositories;
namespace Webkul\Product\Repositories;

use Webkul\Catalog\Contracts\Product;
use Webkul\Product\Contracts\Product;

class ProductRepository extends Repository
{
Expand Down Expand Up @@ -199,7 +199,7 @@ Open the `EventServiceProvider.php` file located in the `Providers` directory of
Inside the `boot()` method of `EventServiceProvider.php`, use the `Event::listen` method to register your listener. This method takes the event name and a callback function or a class method that will handle the event.

```php
Event::listen('catalog.product.create.after', 'Webkul\Notification\Listeners\Product@createNotification');
Event::listen('catalog.product.create.after', 'App\Listeners\ProductListener@createNotification');
```

By registering the listener, you have associated the **`createNotification`** function with the **`catalog.product.create.after`** event. Whenever this event is triggered, the specified function will be executed.
Expand Down
105 changes: 0 additions & 105 deletions src/3.0/advanced/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,41 +188,6 @@ To set the current currency in UnoPim using the `core()->setCurrentCurrency()` m
core()->setCurrentCurrency()
```

### Get current channel's currency model

```php
core()->getCurrentCurrency()
```

- **Get current channel's currency code.**

To retrieve the current channel's currency model in UnoPim, you should use the `core()->getCurrentCurrency()` method. Here's how you can use it:

```php
core()->getCurrentCurrencyCode()
```

This function call retrieves the currency model of the current channel, allowing you to access attributes such as the currency code, symbol, exchange rates, and other relevant information related to currency management within your pim application.

### Get exchange rates

To get exchange rates in UnoPim, you typically need to specify the base currency and the target currency for which you want to retrieve the exchange rate. Here's how you can achieve this:

```php
core()->getExchangeRate()
```

### Converts price.

The `core()->convertPrice()` function in UnoPim is used to convert a given amount from the base currency to a specified target currency. Here's how you can use it:

```php
$amount = 100; // Replace with the amount you want to convert
$targetCurrencyCode = 'EUR'; // Replace with the target currency code

$convertedAmount = core()->convertPrice($amount, $targetCurrencyCode);
```

### Converts to base price

The `core()->convertToBasePrice()` function in UnoPim is used to convert a given amount from a specified currency (target currency) to the base currency of the application. Here's how you can use it:
Expand Down Expand Up @@ -273,14 +238,6 @@ This method also give ability to encode the base currency symbol and its optiona
core()->formatBasePrice($price, $isEncoded = false)
```

### Checks if current date of the given channel (in the channel timezone) is within the range

The `core()->isChannelDateInInterval($dateFrom = null, $dateTo = null)` function in UnoPim checks if the current date of the given channel (considering the channel's timezone) falls within the specified date range.

```php
core()->isChannelDateInInterval($dateFrom = null, $dateTo = null)
```

### Get channel timestamp, timestamp will be builded with channel timezone settings.

To retrieve a timestamp that adheres to a specific channel's timezone settings in UnoPim, you typically use the `core()->channelTimeStamp($channel)` function. Here's how you can implement it:
Expand Down Expand Up @@ -325,42 +282,6 @@ To retrieve all countries in UnoPim, you can use the `core()->countries()` funct
core()->countries()
```

### Get country name by code

To get the country name by its ISO 3166-1 alpha-2 code in UnoPim, you can use the `core()->country_name($code)` function. Here's how you can use it

```php
core()->country_name($code)
```

This function retrieves the full name of the country based on its ISO 3166-1 alpha-2 code ($code).

### Retrieve all country states

To retrieve all states (or provinces) of a specific country in UnoPim, you can use the `core()->states($countryCode)` function. Here's how you can use it

```php
core()->states($countryCode)
```

This function returns a collection of state objects for the specified country

### Retrieve all grouped states by country code.

In UnoPim, to retrieve all states grouped by country code, you can use the `core()->groupedStatesByCountries()` function. This function organizes states or provinces by their respective countries. Here's how you can use it:

```php
core()->groupedStatesByCountries()
```

### Get states by country code.

To retrieve states (or provinces) by country code in UnoPim, you can use the `core()->findStateByCountryCode($countryCode, $stateCode = null)` function. Here’s how you can use it

```php
core()->findStateByCountryCode($countryCode = null, $stateCode = null)
```

### Get guest customer group

In UnoPim, to get the guest customer group, you can use the `core()->getGuestCustomerGroup()` function. Here's how you can use it
Expand All @@ -371,32 +292,6 @@ core()->getGuestCustomerGroup()

This function retrieves the guest customer group configured in your UnoPim application. It returns an object representing the guest customer group

### Is country required

In UnoPim, to check if a country selection is required (typically in address forms or checkout processes), you can use the `core()->isCountryRequired()` function. Here's how you can use it:

```php
core()->isCountryRequired()
```

This function returns a boolean (true or false) indicating whether the country selection is mandatory

### Is state required

In UnoPim, to check if a state or province selection is required (typically in address forms or checkout processes), you can use the `core()->isStateRequired()` function. Here's how you can use it:

```php
core()->isStateRequired()
```

### Is postcode required.

This function returns a boolean (true or false) indicating whether the postcode (or ZIP code) selection is mandatory.

```php
core()->isPostCodeRequired()
```

### Week range

In UnoPim, there isn't a specific `core()->xWeekRange()` function predefined. However, if you need to calculate a date range based on a given date and the number of weeks before or after that date, you can achieve this using PHP's DateTime and DateInterval classes. Here’s how you can calculate a week range
Expand Down
2 changes: 1 addition & 1 deletion src/3.0/advanced/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ UnoPim includes a comprehensive set of helper functions that simplify common dev
Sometimes, you may need to modify or extend the default behavior of UnoPim's core models to accommodate your specific business requirements. We will demonstrate how to override core models effectively, enabling you to customize the behavior of UnoPim without modifying the underlying codebase.

::: tip
Looking for the AI Agent and MagicAI platform documentation? Those topics now live in the dedicated [Agentic Development](../agentic/) section, alongside the Agentic Skills and MCP Server guides.
Looking for the AI Agent and MagicAI platform documentation? Those topics now live in the dedicated [Agentic Development](../agentic/) section, alongside the Agentic Skills guides.
:::
8 changes: 4 additions & 4 deletions src/3.0/advanced/override-core-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ class ExampleServiceProvider extends ServiceProvider
//...

$this->app->concord->registerModel(
\Webkul\Product\Contracts\Product::class, \App\Http\Product::class
\Webkul\Product\Contracts\Product::class, \App\Models\Product::class
);
}
}
```

- Replace `\Webkul\Product\Contracts\Product::class` with the interface you wish to override.
- Replace `\App\Http\Product::class` with the path to your custom model class that extends the core model you are overriding.
- Replace `\App\Models\Product::class` with your custom model class, which must extend the core model you are overriding.

### Implement the Custom Model Class

Expand All @@ -59,7 +59,7 @@ Your custom model class (Product in this example) should extend the base core mo
```php
<?php

namespace App\Http;
namespace App\Models;

use Webkul\Product\Models\Product as ProductBaseModel;

Expand All @@ -69,7 +69,7 @@ class Product extends ProductBaseModel
}
```

Once registered, you can use dependency injection or other Laravel mechanisms to reference the interface(`\Webkul\Product\Contracts\Product::class`) throughout your application. Laravel's service container will automatically resolve your custom model implementation (`\App\Http\Product::class`) where the interface is referenced.
Once registered, you can use dependency injection or other Laravel mechanisms to reference the interface(`\Webkul\Product\Contracts\Product::class`) throughout your application. Laravel's service container will automatically resolve your custom model implementation (`\App\Models\Product::class`) where the interface is referenced.

By following this approach, you can effectively extend and override core models within UnoPim using Concord, maintaining modularity and flexibility in your application's architecture.

Loading