Skip to content
46 changes: 46 additions & 0 deletions code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace App\PIM\Symbol\Format\Checksum;

use Ibexa\Contracts\ProductCatalog\Values\AttributeDefinitionInterface;
use Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface;

final class LuhnChecksum implements ChecksumInterface

Check failure on line 10 in code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

Class App\PIM\Symbol\Format\Checksum\LuhnChecksum implements unknown interface Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface.
{
public function validate(AttributeDefinitionInterface $attributeDefinition, string $value): bool
{
$digits = $this->getDigits($value);

$count = count($digits);
$total = 0;
for ($i = $count - 2; $i >= 0; $i -= 2) {
$digit = $digits[$i];
if ($i % 2 === 0) {
$digit *= 2;
}

$total += $digit > 9 ? $digit - 9 : $digit;
}

$checksum = $digits[$count - 1];

return $total + $checksum === 0;
}

/**
* Returns an array of digits from the given value (skipping any formatting characters).
*
* @return int[]
*/
private function getDigits(string $value): array
{
$chars = array_filter(
str_split($value),
static fn (string $char): bool => $char !== '-'
);

return array_map('intval', array_values($chars));
}
}
138 changes: 138 additions & 0 deletions docs/pim/symbol_attribute_type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---

Check warning on line 1 in docs/pim/symbol_attribute_type.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/pim/symbol_attribute_type.md#L1

[Ibexa.ReadingLevel] The grade level is 9.26. Aim for 8th grade or lower by using shorter sentences and words.
Raw output
{"message": "[Ibexa.ReadingLevel] The grade level is 9.26. Aim for 8th grade or lower by using shorter sentences and words.", "location": {"path": "docs/pim/symbol_attribute_type.md", "range": {"start": {"line": 1, "column": 1}}}, "severity": "WARNING"}
description: Create a symbol attribute type that enables for the efficient representation of string-based values while enforcing their format in product specifications.
---

# Symbol attribute type

In product specifications, the symbol attribute type enables the efficient representation of string-based data and enforces their format.

This feature allows you to store standard product identifiers (such as EAN or ISBN) in the [Product Information Management](pim_guide.md) system.

## Installation

### Download the bundle

To get the most recent stable version of this bundle, open a command terminal, navigate to your project directory, and run the following command:

``` bash
composer require ibexa/product-catalog-symbol-attribute
```

### Enable the bundle

Symfony Flex enables and configures the `IbexaProductCatalogSymbolAttributeBundle` automatically.
If you don't use it, you can manually enable this bundle by adding the line below to the Kernel of your project:

``` php
// config/bundles.php

return [
// ...
Ibexa\Bundle\ProductCatalogSymbolAttribute\IbexaProductCatalogSymbolAttributeBundle::class => ['all' => true],
// ...
];
```

### Update database schema

To store symbol attribute values, the `IbexaProductCatalogSymbolAttributeBundle` needs an extra table.
The following SQL query can be used to build the required database structure:

``` sql
create table ibexa_product_specification_attribute_symbol (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This query is not working on PostgreSQL - we need to have a separate entry for PostgreSQL

id int not null primary key,
value varchar(255) null,
constraint ibexa_product_specification_attribute_symbol_fk
foreign key (id) references ibexa_product_specification_attribute (id)
on update cascade on delete cascade
) collate = utf8mb4_unicode_520_ci;

create index ibexa_product_specification_attribute_symbol_value_idx
on ibexa_product_specification_attribute_symbol (value);
```

### Create symbol attribute definition (optional)

Now, you're able to define symbol attributes at this point.

To create symbol attribute definition, in the back office, go to **Product catalog** -> **Attributes**, and click **Create**.
Then, choose **Symbol** attribute type.

## Build-in symbol attribute formats

The built-in symbol attribute formats in `ibexa/product-catalog-symbol-attribute` are listed below:

| Name | Description | Example |
|-----------------|-----------------|-----------------|
| Generic | Accepts any string value | #FR1.2 |
| Generic (alphabetic characters only) | Accepts any string value that contais only letters | ABCD |
| Generic (digits only) | Accepts any string value that contais only digits | 123456 |
| Generic (alphanumeric characters only) | Accepts any string value that contains only letters or digits | 2N6405G |
| Generic (hexadecimal digits only) | Accepts any string value that contains only hexadecimal digits (digits or A-F characters) | DEADBEEF |
| EAN-8 | European Article Number (8 characters) | 29033706 |
| EAN-13 | European Article Number (13 characters) | 5023920187205 |
| EAN-14 | European Article Number (14 characters) | 50239201872050 |
| ISBN-10 | International Standard Book Number (10 characters) | 0-19-852663-6 |
| ISBN-13 | International Standard Book Number (13 characters) | 978-1-86197-876-9 |

!!! caution

Maximum length of the symbol value is 160 characters.

## Create custom symbol attribute format

Under the `ibexa_product_catalog_symbol_attribute.formats` key, you can use configuration to create your own symbol format.

See the example below:

``` yaml
ibexa_product_catalog_symbol_attribute:
formats:
manufacturer_part_number:
name: 'Manufacturer Part Number'
pattern: '/^[A-Z]{3}-\d{5}$/'
examples:
- 'RPI-14645'
- 'MSS-24827'
- 'SEE-15444'
```

This following example specifies the format for a "Manufacturer Part Number", defined with the `manufacturer_part_number` identifier.

The pattern is specified using a regular expression.
According to the pattern option, the attribute value:

- must be a string
- begins with three capital letters (A-Z), followed by a hyphen ("-")
- ends with five numbers (0-9), with no other characters before or after

Certain formats, such as the International Standard Book Number (ISBN-10) and the European Article Number (EAN-13), contain checksum digits and are self-validating.

To validate checksum of symbol:

1\. Create a class implementing the `\Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface` interface.

2\. Register the class as a service using the `ibexa.product_catalog.attribute.symbol.checksum` tag and specify the format identifier using the `format` attribute.

See below the example implementation of checksum validation using Luhn formula:

``` php
[[= include_file('code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php') =]]
```

Example service definition:

``` yaml
services:
App\PIM\Symbol\Format\Checksum\LuhnChecksum:
tags:
- name: ibexa.product_catalog.attribute.symbol.checksum
format: my_format
```
The format attribute (`my_format`) is the identifier used under the `ibexa_product_catalog_symbol_attribute.formats` key.

## Search for products with given symbol attribute

You can use `SymbolAttribute` Search Criterion to find products by symbol attribute:

For more information, see [SymbolAttribute Criterion](symbolattribute_criterion.md).
2 changes: 1 addition & 1 deletion docs/search/criteria_reference/product_search_criteria.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ Search Criterion let you filter product by specific attributes, for example, col
|[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|

|[SymbolAttribute](symbolattribute_criterion.md)|Value of product's symbol attribute|
28 changes: 28 additions & 0 deletions docs/search/criteria_reference/symbolattribute_criterion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---

Check warning on line 1 in docs/search/criteria_reference/symbolattribute_criterion.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/search/criteria_reference/symbolattribute_criterion.md#L1

[Ibexa.ReadingLevel] The grade level is 6.58. Aim for 8th grade or lower by using shorter sentences and words.
Raw output
{"message": "[Ibexa.ReadingLevel] The grade level is 6.58. Aim for 8th grade or lower by using shorter sentences and words.", "location": {"path": "docs/search/criteria_reference/symbolattribute_criterion.md", "range": {"start": {"line": 1, "column": 1}}}, "severity": "WARNING"}
description: SymbolAttribute Criterion
---

# SymbolAttributeCriterion

The `SymbolAttribute` Search Criterion searches for products by [symbol attribute](symbol_attribute_type.md).

## Arguments

- `identifier` - identifier of the format
- `value` - array with the values to search for

## Example

### PHP

``` php
<?php

use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
use Ibexa\Contracts\ProductCatalogSymbolAttribute\Search\Criterion\SymbolAttribute;

$query = new ProductQuery();
$query->setFilter(new SymbolAttribute('ean', ['5023920187205']));
/** @var \Ibexa\Contracts\ProductCatalog\ProductServiceInterface $productService*/
$results = $productService->findProducts($query);
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ nav:
- Create product code generator: pim/create_product_code_generator.md
- Create custom catalog filter: pim/create_custom_catalog_filter.md
- Create custom name schema: pim/create_custom_name_schema_strategy.md
- Use symbol attribute type: pim/symbol_attribute_type.md
- Add remote PIM support: pim/add_remote_pim_support.md
- Commerce:
- Commerce: commerce/commerce.md
Expand Down
Loading