diff --git a/code_samples/back_office/search/src/Query/DateTimeAttributeQuery.php b/code_samples/back_office/search/src/Query/DateTimeAttributeQuery.php
new file mode 100644
index 0000000000..adde49a43e
--- /dev/null
+++ b/code_samples/back_office/search/src/Query/DateTimeAttributeQuery.php
@@ -0,0 +1,13 @@
+setOperator(FieldValueCriterion::COMPARISON_EQ);
+$query->setFilter($filter);
+/** @var \Ibexa\Contracts\ProductCatalog\ProductServiceInterface $productService */
+$results = $productService->findProducts($query);
diff --git a/code_samples/back_office/search/src/Query/DateTimeAttributeRangeQuery.php b/code_samples/back_office/search/src/Query/DateTimeAttributeRangeQuery.php
new file mode 100644
index 0000000000..f8016aa377
--- /dev/null
+++ b/code_samples/back_office/search/src/Query/DateTimeAttributeRangeQuery.php
@@ -0,0 +1,10 @@
+setFilter(new DateTimeAttributeRange('event_date', new DateTimeImmutable('2025-01-01')));
+/** @var \Ibexa\Contracts\ProductCatalog\ProductServiceInterface $productService */
+$results = $productService->findProducts($query);
diff --git a/code_samples/data_migration/examples/create_datetime_attribute.yaml b/code_samples/data_migration/examples/create_datetime_attribute.yaml
new file mode 100644
index 0000000000..194792ef83
--- /dev/null
+++ b/code_samples/data_migration/examples/create_datetime_attribute.yaml
@@ -0,0 +1,10 @@
+- type: attribute
+ mode: create
+ identifier: event_date
+ attribute_group_identifier: example
+ attribute_type_identifier: datetime
+ position: 1
+ names:
+ eng-GB: 'Event date'
+ options:
+ accuracy: day # One of: second, minute, day, month, trimester, year
diff --git a/composer.json b/composer.json
index 8e45f09ed5..56798ec64b 100644
--- a/composer.json
+++ b/composer.json
@@ -22,6 +22,7 @@
"ibexa/design-engine": "5.0.x-dev",
"ibexa/user": "5.0.x-dev",
"ibexa/notifications": "5.0.x-dev",
+ "ibexa/product-catalog-date-time-attribute": "5.0.x-dev",
"ibexa/fieldtype-richtext": "5.0.x-dev",
"ibexa/rector": "5.0.x-dev",
"ibexa/rest": "5.0.x-dev",
diff --git a/docs/content_management/data_migration/importing_data.md b/docs/content_management/data_migration/importing_data.md
index de78dd8a15..55dc32a435 100644
--- a/docs/content_management/data_migration/importing_data.md
+++ b/docs/content_management/data_migration/importing_data.md
@@ -346,6 +346,14 @@ You can also update attributes, including changing which attribute group they be
You can't change the attribute type of an existing attribute.
+##### Date and time attributes
+
+If you're using attributes of the [date and time type](date_and_time.md), you can manage it through the migrations as well, for example:
+
+``` yaml
+[[= include_file('code_samples/data_migration/examples/create_datetime_attribute.yaml') =]]
+```
+
#### Product types
The following example shows how to create a product type.
diff --git a/docs/index.md b/docs/index.md
index 556fdfe057..8ecac6ee8b 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -77,7 +77,7 @@
The latest release is v4.6
-
The newest LTS Update to Ibexa DXP v4.6 is
AI Actions. Install it to let AI help you with editorial tasks.
+
The newest LTS Update to Ibexa DXP v4.6 is the
Date and time attribute type. Install it to add time-related values to product specifications.
Update your application
diff --git a/docs/pim/attributes/date_and_time.md b/docs/pim/attributes/date_and_time.md
new file mode 100644
index 0000000000..17ae29fdff
--- /dev/null
+++ b/docs/pim/attributes/date_and_time.md
@@ -0,0 +1,78 @@
+---
+description: Date and time attribute type allows you to store product information related to time, like an expiration date or date of manufacturing.
+---
+
+# Date and time attributes
+
+The date and time [attribute type](products.md#attributes) allows you to represent date and time values as part of the product specification in the [Product Information Management](pim_guide.md) system.
+
+It's released as an [LTS update](release_process_and_roadmap.md) that you can install on top of your current project to expand the capabilities of your [[= product_name =]].
+
+You can use it to store, for example, manufacturing dates, expiration dates, or event dates, all with specified accuracy.
+
+
+## Installation
+
+### Download the bundle
+
+To get the most recent stable version of this package, open a command terminal, navigate to your project directory, and run the following command:
+
+``` bash
+composer require ibexa/product-catalog-date-time-attribute
+```
+
+### Enable the bundle
+
+Symfony Flex enables and configures the `IbexaProductCatalogDateTimeAttributeBundle` automatically.
+If you don't use it, you can manually enable this bundle by adding it to the list of bundles in `config/bundles.php`:
+
+``` php
+return [
+ // ...
+ Ibexa\Bundle\ProductCatalogDateTimeAttribute\IbexaProductCatalogDateTimeAttributeBundle::class => ['all' => true],
+ // ...
+];
+```
+
+### Update database schema
+
+The new attribute type requires changes to the database schema.
+Execute the following queries on your database to support the new attribute type:
+
+=== "MySQL"
+
+ ``` sql
+ CREATE TABLE ibexa_product_specification_attribute_datetime (id INT NOT NULL, value DATETIME DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)', INDEX ibexa_product_specification_attribute_datetime_idx (value), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
+ ALTER TABLE ibexa_product_specification_attribute_datetime ADD CONSTRAINT ibexa_product_specification_attribute_datetime_fk FOREIGN KEY (id) REFERENCES ibexa_product_specification_attribute (id) ON UPDATE CASCADE ON DELETE CASCADE;
+ ```
+
+=== "PostgreSQL"
+
+ ``` sql
+ CREATE TABLE ibexa_product_specification_attribute_datetime (id INT NOT NULL, value TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id));
+ CREATE INDEX ibexa_product_specification_attribute_datetime_idx ON ibexa_product_specification_attribute_datetime (value);
+ COMMENT ON COLUMN ibexa_product_specification_attribute_datetime.value IS '(DC2Type:datetime_immutable)';
+ ALTER TABLE ibexa_product_specification_attribute_datetime ADD CONSTRAINT ibexa_product_specification_attribute_datetime_fk FOREIGN KEY (id) REFERENCES ibexa_product_specification_attribute (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
+ ```
+
+You can now start working with the date and time attribute type.
+
+## Usage
+
+The date and time attribute type's support in the system is on par with the other, built-in attribute types.
+
+You can manage it through the back office, [data migrations](importing_data.md#date-and-time-attribute), REST, or through the PHP API.
+It also supports [searching](product_search_criteria.md) by using [DateTimeAttribute](datetimeattribute_criterion.md) and [DateTimeAttributeRange](datetimeattributerange_criterion.md) criterions.
+
+
+
+When creating an attribute based on the date and time attribute type you can select the accuracy level to match your needs:
+
+| Accuracy | Example | Limitations |
+|---|---|---|
+| Year | 2025 | Number between 1000 and 9999 |
+| Trimester | Q3 2025 | |
+| Month | July 2025 | |
+| Day | 2025-07-06 | |
+| Minute | 2025-07-06 11:15 | |
+| Second | 2025-07-06 11:15:37| |
diff --git a/docs/pim/attributes/img/datetime.png b/docs/pim/attributes/img/datetime.png
new file mode 100644
index 0000000000..6eb2458e15
Binary files /dev/null and b/docs/pim/attributes/img/datetime.png differ
diff --git a/docs/pim/products.md b/docs/pim/products.md
index 1c30153aa1..c4c4d28f3e 100644
--- a/docs/pim/products.md
+++ b/docs/pim/products.md
@@ -19,12 +19,12 @@ A product type can be, for example, a sofa, or a keyboard.
Product types, like content types, define the global properties of products and fields a product consists of.
A product type also defines the attributes that all products of this type can have.
-You can choose between two available types: `Physical` and `Virtual`:
+You can choose between two available types: `physical` and `virtual`:
-- `Physical` - tangible products with assigned stock.
+- `physical` - tangible products with assigned stock.
They can use measurement attributes. They require shipment in the online purchase process.
Examples: heaters, laptops, phones.
-- `Virtual` - non-tangible items. They can be sold individually, or as part of a product bundle.
+- `virtual` - non-tangible items. They can be sold individually, or as part of a product bundle.
They don't require shipment in the online process. Examples: memberships, services, warranties.
## Product attributes
@@ -34,12 +34,13 @@ Typical product attribute examples are: length, weight, color, format, and more.
The following attribute types are available:
-- Checkbox
-- Color
-- Float
-- Integer
-- Measurement
-- Selection
+- checkbox
+- color
+- [date and time](date_and_time.md)
+- float
+- integer
+- measurement
+- selection
Product attributes are collected in groups.
An example of an attribute group can be dimensions (length, width, height).
diff --git a/docs/release_notes/ibexa_dxp_v4.6.md b/docs/release_notes/ibexa_dxp_v4.6.md
index 73ba83693c..9440460f92 100644
--- a/docs/release_notes/ibexa_dxp_v4.6.md
+++ b/docs/release_notes/ibexa_dxp_v4.6.md
@@ -20,6 +20,12 @@ description: Ibexa DXP v4.6 brings improvements to Commerce, PIM and Personaliza
LTS Updates are opt-in packages that bring cutting-edge technologies to an LTS release that they enhance, without compromising the product's stability.
The features brought by an LTS Update become a standard part of the next LTS release.
+### Date and time attribute type
+
+The Date and time attributes allow you to represent date and time values as part of the product specification in the [Product Information Management](pim_guide.md) system.
+
+For more information, see [Date and time attributes](date_and_time.md).
+
### AI Actions
The AI Actions LTS update enhances the usability and flexibility of [[=product_name=]] v4.6 LTS by harnessing the potential of artificial intelligence to automate time-consuming editorial tasks.
@@ -695,4 +701,4 @@ The following view matchers have been introduced in [[= product_name =]] v4.6.0:
| [[= product_name_headless =]] | [[= product_name_exp =]] | [[= product_name_com =]] |
|---------------|------------------|---------------|
-| [[[= product_name_headless =]] v4.6](https://github.com/ibexa/headless/releases/tag/v4.6.0) | [[[= product_name_exp =]] v4.6](https://github.com/ibexa/experience/releases/tag/v4.6.0) | [[[= product_name_com =]] v4.6](https://github.com/ibexa/commerce/releases/tag/v4.6.0) |
\ No newline at end of file
+| [[[= product_name_headless =]] v4.6](https://github.com/ibexa/headless/releases/tag/v4.6.0) | [[[= product_name_exp =]] v4.6](https://github.com/ibexa/experience/releases/tag/v4.6.0) | [[[= product_name_com =]] v4.6](https://github.com/ibexa/commerce/releases/tag/v4.6.0) |
diff --git a/docs/resources/release_process_and_roadmap.md b/docs/resources/release_process_and_roadmap.md
index 9d3577e982..f7d1f3abd0 100644
--- a/docs/resources/release_process_and_roadmap.md
+++ b/docs/resources/release_process_and_roadmap.md
@@ -6,6 +6,8 @@ description: "Ibexa DXP releases new versions periodically in different flavors:
## Release process
+### Distributions
+
[[= product_name =]] has three distributions:
- [[= product_name_headless =]] is a multichannel and headless content management system.
@@ -17,6 +19,8 @@ Additionally, [[= product_name =]] also has an open-source version called [[= pr
The [[= product_name_oss =]] code is available on GitHub under the GPLv2 license.
It comes with no commercial support and maintenance services.
+### Long Term Support releases
+
[[= product_name_base =]] manages the release of [[= product_name =]] by using an agile iterative process and a continuous software development model, which is why we provide Long Term Support releases (LTS) of [[= product_name =]] releases.
Long Term Support releases (LTS) are supported by [[= product_name_base =]] for a long period of time.
@@ -29,6 +33,8 @@ LTS releases provide you with:
- **Predictability** that comes from following an established release plan.
- **Reduced maintenance**, because you avoid the frequent upgrade cycles.
+### LTS Updates
+
With LTS Updates customers can maintain their competitiveness by incorporating cutting-edge technologies into their LTS releases without losing stability.
LTS Updates are intended to improve the current platform by providing new features.
What's important, you are not required to switch to a newer version of [[= product_name =]] to use LTS Updates.
diff --git a/docs/search/criteria_reference/datetimeattribute_criterion.md b/docs/search/criteria_reference/datetimeattribute_criterion.md
new file mode 100644
index 0000000000..f5d416a73b
--- /dev/null
+++ b/docs/search/criteria_reference/datetimeattribute_criterion.md
@@ -0,0 +1,33 @@
+---
+description: DateTimeAttribute Criterion
+---
+
+# DateTimeAttribute criterion
+
+The [`DateTimeAttribute Search Criterion`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalogDateTimeAttribute-Search-Criterion-DateTimeAttribute.html) searches for products by value of a specified attribute, based on the [date and time attribute](date_and_time.md) type.
+
+## Arguments
+
+- `identifier` - attribute's identifier (string)
+- `value` - searched value ([DateTimeImmutable](https://www.php.net/manual/en/class.datetimeimmutable.php))
+
+## Operators
+
+The following operators are supported:
+
+- [FieldValueCriterion::COMPARISON_EQ](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_EQ)
+- [FieldValueCriterion::COMPARISON_NEQ](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_NEQ)
+- [FieldValueCriterion::COMPARISON_LT](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_LT)
+- [FieldValueCriterion::COMPARISON_LTE](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_LTE)
+- [FieldValueCriterion::COMPARISON_GT](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_GT)
+- [FieldValueCriterion::COMPARISON_GTE](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_GTE)
+
+## Example
+
+### PHP
+
+The following example lists all products for which the `event_date` attribute has value equal to 2025-07-06.
+
+``` php
+[[= include_file('code_samples/back_office/search/src/Query/DateTimeAttributeQuery.php') =]]
+```
diff --git a/docs/search/criteria_reference/datetimeattributerange_criterion.md b/docs/search/criteria_reference/datetimeattributerange_criterion.md
new file mode 100644
index 0000000000..447bb77249
--- /dev/null
+++ b/docs/search/criteria_reference/datetimeattributerange_criterion.md
@@ -0,0 +1,24 @@
+---
+description: DateTimeAttributeRange Criterion
+---
+
+# DateTimeAttributeRange criterion
+
+The [`DateTimeAttributeRange Search Criterion`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalogDateTimeAttribute-Search-Criterion-DateTimeAttributeRange.html) searches for products by value of a specified attribute, which must be based on the [date and time attribute](date_and_time.md) type.
+
+## Arguments
+
+- `identifier` - attribute's identifier (string)
+- `min` - lower range value (inclusive) of [DateTimeImmutable](https://www.php.net/manual/en/class.datetimeimmutable.php) type. Optional.
+- `max` - upper range value (inclusive) of [DateTimeImmutable](https://www.php.net/manual/en/class.datetimeimmutable.php) type. Optional.
+
+## Example
+
+### PHP
+
+The following example lists all products for which the `event_date` attribute has value greater than 2025-01-01.
+
+
+``` php
+[[= include_file('code_samples/back_office/search/src/Query/DateTimeAttributeRangeQuery.php') =]]
+```
diff --git a/docs/search/criteria_reference/product_search_criteria.md b/docs/search/criteria_reference/product_search_criteria.md
index daeec325d9..a31f6cabbc 100644
--- a/docs/search/criteria_reference/product_search_criteria.md
+++ b/docs/search/criteria_reference/product_search_criteria.md
@@ -13,8 +13,9 @@ Search Criterion let you filter product by specific attributes, for example, col
|Search Criterion|Search based on|
|-----|-----|
-|[AttributeName](attributename_criterion.md)|Value of product's attribute name|
|[AttributeGroupIdentifier](attributegroupidentifier_criterion.md)|Value of product's attribute group identifier|
+|[AttributeName](attributename_criterion.md)|Value of product's attribute name|
+|[BasePrice](baseprice_criterion.md)|Product's base price|
|[CatalogIdentifier](catalogidentifier_criterion.md)|Catalog's identifier|
|[CatalogName](catalogname_criterion.md)|Catalog's name|
|[CatalogStatus](catalogstatus_criterion.md)|Catalog's status|
@@ -22,21 +23,23 @@ Search Criterion let you filter product by specific attributes, for example, col
|[ColorAttribute](colorattribute_criterion.md)|Value of product's color attribute|
|[CreatedAt](createdat_criterion.md)|Date and time when product was created|
|[CreatedAtRange](createdatrange_criterion.md)|Date and time range when product was created|
+|[CustomPrice](customprice_criterion.md)|Product's custom price|
+|[DateTimeAttribute](datetimeattribute_criterion.md)|Value of product's date and time attribute|
+|[DateTimeAttributeRange](datetimeattributerange_criterion.md)|Value of product's date and time attribute and given time range|
|[FloatAttribute](floatattribute_criterion.md)|Value of product's float attribute|
|[FloatAttributeRange](floatattributerange_criterion.md)|Value of product's float attribute|
|[IntegerAttribute](integerattribute_criterion.md)|Value of product's integer attribute|
|[IntegerAttributeRange](integerattributerange_criterion.md)|Value of product's integer attribute|
|[IsVirtual](isvirtual_criterion.md)|Product type (virtual or physical)|
-|[SelectionAttribute](selectionattribute_criterion.md)|Value of product's selection attribute|
|[ProductAvailability](productavailability_criterion.md)|Product's availability|
-|[ProductStock](productstock_criterion.md)|Product's numerical stock|
-|[ProductStockRange](productstockrange_criterion.md)|Product's numerical stock|
|[ProductCategory](productcategory_criterion.md)|Product category assigned to product|
|[ProductCode](productcode_criterion.md)|Product's code|
|[ProductName](productname_criterion.md)|Product's name|
-|[RangeMeasurementAttributeMinimum](rangemeasurementattributeminimum_criterion.md)|Minimum value of product's measurement attribute|
+|[ProductStock](productstock_criterion.md)|Product's numerical stock|
+|[ProductStockRange](productstockrange_criterion.md)|Product's numerical stock|
+|[ProductType](producttype_criterion.md)|Product type|
|[RangeMeasurementAttributeMaximum](rangemeasurementattributemaximum_criterion.md)|Maximum value of product's measurement attribute|
+|[RangeMeasurementAttributeMinimum](rangemeasurementattributeminimum_criterion.md)|Minimum value of product's measurement attribute|
+|[SelectionAttribute](selectionattribute_criterion.md)|Value of product's selection attribute|
|[SimpleMeasurementAttribute](simplemeasurementattribute_criterion.md)|Value of product's measurement attribute|
-|[BasePrice](baseprice_criterion.md)|Product's base price|
-|[CustomPrice](customprice_criterion.md)|Product's custom price|
-|[ProductType](producttype_criterion.md)|Product type|
+
diff --git a/mkdocs.yml b/mkdocs.yml
index 217caa280a..10b6678ef6 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -333,6 +333,8 @@ nav:
- PIM guide: pim/pim_guide.md
- PIM configuration: pim/pim_configuration.md
- Products: pim/products.md
+ - Attributes:
+ - Date and Time attribute: pim/attributes/date_and_time.md
- Product API: pim/product_api.md
- Catalogs: pim/catalogs.md
- Catalog API: pim/catalog_api.md
@@ -543,15 +545,17 @@ nav:
- Product Search Criteria: search/criteria_reference/product_search_criteria.md
- AttributeName: search/criteria_reference/attributename_criterion.md
- AttributeGroupIdentifier: search/criteria_reference/attributegroupidentifier_criterion.md
+ - BasePrice: search/criteria_reference/baseprice_criterion.md
- CatalogIdentifier: search/criteria_reference/catalogidentifier_criterion.md
- CatalogName: search/criteria_reference/catalogname_criterion.md
- CatalogStatus: search/criteria_reference/catalogstatus_criterion.md
- - BasePrice: search/criteria_reference/baseprice_criterion.md
- CheckboxAttribute: search/criteria_reference/checkboxattribute_criterion.md
- ColorAttribute: search/criteria_reference/colorattribute_criterion.md
- CreatedAt: search/criteria_reference/createdat_criterion.md
- CreatedAtRange: search/criteria_reference/createdatrange_criterion.md
- CustomPrice: search/criteria_reference/customprice_criterion.md
+ - DateTimeAttribute: search/criteria_reference/datetimeattribute_criterion.md
+ - DateTimeAttributeRange: search/criteria_reference/datetimeattributerange_criterion.md
- FloatAttribute: search/criteria_reference/floatattribute_criterion.md
- FloatAttributeRange: search/criteria_reference/floatattributerange_criterion.md
- IntegerAttribute: search/criteria_reference/integerattribute_criterion.md