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
2 changes: 1 addition & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
->setRules([
'@PSR2' => true,
'@PSR12' => true,
'@PHP74Migration:risky' => true,
'@PHP7x4Migration:risky' => true,
'@Symfony' => true,
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => [
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog
## Unreleased
### Add
- Add possibility to disable Web Components integration per sales channel

### Change
- Upgrade Web Components version to v5.1.7
- Add template to suggest element
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ store cache in order the new applied configuration to start working.
* Server URL - FACT-Finder® instance url
**Note:** Server URL should contain a used protocol: (e.g. `https://`) and should end with an
endpoint ( `fact-finder` )
* Channel - Channel you want to serve data from
* Channel - Channel you want to serve data from. This field works for each sales channel separately, so you can, for example, adjust FactFinder integration to different store's language versions.
* API key - your FACT-Finder® API key

You can check if the above data is correctly set by clicking on the `Test Connection` button. Please save your settings before clicking on button.
Expand All @@ -123,6 +123,13 @@ You can find more information about what Field Roles are in (Web Components docu
**Note:**
Updating process is ran for all sales channels, no need to run it separately for each of them

#### Disable FactFinder Web Components option

This option allows you to disable FACT-Finder® Web Components integration on the frontend. It works for each sales channel separately so you can use our plugin only on the sales channels you want.

**Note:** If you enable this option, FACT-Finder® integration on the frontend will stop working. Pay special attention not to define FACT-Finder® category pages for sales channels where you enable this option, as this will cause an error on the page or incorrect generation of HTML code


## Advanced Settings

![Advanced Settings](docs/assets/advanced-settings.png "Advanced Settings")
Expand Down Expand Up @@ -462,6 +469,17 @@ Plugin implements a list of given Web Components:
* ff-checkout-tracking


## Sales channels management

The entire plugin configuration must be placed in `All Sales Channels`:

![sales-channels-management.png](docs/assets/sales-channels-management.png)

There are only two fields that can be defined for each sales channel separately:

- `Channel` - you can define different data comes from FACT-Finder®, especially in the case of multi-language stores
- `Disable FactFinder Web Components on frontend?` - allows you to disable FACT-Finder® Web Components integration on the frontend. With this option you can use our plugin only on the sales channels you want.

## Modifications Examples

### Adding New Column to Feed
Expand Down
Binary file modified docs/assets/advanced-settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/sales-channels-management.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions spec/Storefront/Controller/ResultControllerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public function let(
$this->factfinderLogger = $factfinderLogger;
$this->beConstructedWith($config, $pageLoader, $factfinderLogger);
$requestStack->getCurrentRequest()->willReturn($request);
$salesChannelContext->getSalesChannelId()->willReturn('main_sales_channel');
$container->get('request_stack')->willReturn($requestStack);
$this->request->attributes = $attributes;
$attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT)->willReturn($salesChannelContext);
Expand All @@ -93,6 +94,7 @@ public function it_should_return_original_response_content_when_ssr_is_not_activ
$this->twig->render('@OmikronFactFinder/storefront/page/factfinder/result.html.twig', Argument::any())->willReturn($content);
$this->seoUrlPlaceholderHandler->replace($content, 'https://shop.com', $this->salesChannelContext)->willReturn($content);
$this->mediaUrlPlaceholderHandler->replace($content)->willReturn($content);
$this->config->disableFFWebc('main_sales_channel')->willReturn(false);
$response = $this->result(
$this->request,
$this->salesChannelContext,
Expand Down
5 changes: 5 additions & 0 deletions src/Config/Communication.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public function getChannel(?string $salesChannelId = null): string
return (string) $this->config('channel', $salesChannelId);
}

public function disableFFWebc(?string $salesChannelId = null): bool
{
return (bool) $this->config('disableFactFinderWebc', $salesChannelId);
}

public function getCredentials(): array
{
return [
Expand Down
2 changes: 1 addition & 1 deletion src/Domain/RedirectMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Omikron\FactFinder\Shopware6\Domain;

readonly class RedirectMapping
readonly class RedirectMapping implements \Stringable
{
public function __construct(private string $data)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Export/Field/PriceCurrency.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
use Shopware\Core\System\Currency\CurrencyEntity;

class PriceCurrency extends Price
class PriceCurrency extends Price implements \Stringable
{
private CurrencyEntity $currency;
private NumberFormatter $numberFormatter;
Expand Down
9 changes: 9 additions & 0 deletions src/Resources/config/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
<helpText lang="de-DE">Diese Option funktioniert nur, wenn das serverseitige Rendering [SSR] aktiviert ist. Wenn das SSR-Suchergebnis ein Ergebnis enthält, wird es automatisch auf die Produktdetailseite umgeleitet [PDP].</helpText>
</input-field>

<input-field type="bool">
<name>disableFactFinderWebc</name>
<label>Disable FactFinder Web Components on frontend?</label>
<label lang="de-DE">FactFinder-Webkomponenten im Frontend verwenden?</label>
<defaultValue>false</defaultValue>
<helpText>You can disable FactFinder integration on the frontend. This option works for each sales channel separately. Note. If you enable this option, FactFinder integration on the frontend will stop working.</helpText>
<helpText lang="de-DE">Sie können die FactFinder-Integration im Frontend deaktivieren. Diese Option funktioniert für jeden Vertriebskanal separat. Notiz. Wenn Sie diese Option aktivieren, funktioniert die FactFinder-Integration im Frontend nicht mehr.</helpText>
</input-field>

<input-field type="bool">
<name>useProxy</name>
<label>Use Proxy?</label>
Expand Down
5 changes: 5 additions & 0 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -213,5 +213,10 @@
<argument type="service" id="Omikron\FactFinder\Shopware6\MessageQueue\FeedExportHandler" />
<tag name="messenger.message_handler" />
</service>
<service id="Omikron\FactFinder\Shopware6\Twig\FactFinderExtension">
<argument type="service" id="Omikron\FactFinder\Shopware6\Config\Communication" />
<argument type="service" id="request_stack" />
<tag name="twig.extension" />
</service>
</services>
</container>
218 changes: 111 additions & 107 deletions src/Resources/views/storefront/base.html.twig
Original file line number Diff line number Diff line change
@@ -1,149 +1,153 @@
{% sw_extends '@Parent/storefront/base.html.twig' %}

{% block base_body_inner %}
{% block base_body_inner_factfinder_communication %}

<!--Main FF Web-components Initialisation -->
<script>
document.addEventListener(`ffCoreReady`, ({ factfinder, init, initialSearch }) => {

init({
ff: {
url: `{{page.extensions.factfinder.communication.url}}`,
channel: `{{page.extensions.factfinder.communication.channel}}`,
apiKey: `{{page.extensions.factfinder.communication.apiKey}}`,
},
appConfig: {
debug: true,
fieldRoles: {{ page.extensions.factfinder.field_roles|json_encode|raw }},
formatting: {
locale: `{{page.extensions.factfinder.communication.currencyCountryCode}}`,
formatOptions: {
style: `currency`,
currency: `{{page.extensions.factfinder.communication.currencyCode}}`,
{% if not ff_disable_webc() %}
{% block base_body_inner_factfinder_communication %}

<!--Main FF Web-components Initialisation -->
<script>
document.addEventListener(`ffCoreReady`, ({ factfinder, init, initialSearch }) => {

init({
ff: {
url: `{{page.extensions.factfinder.communication.url}}`,
channel: `{{page.extensions.factfinder.communication.channel}}`,
apiKey: `{{page.extensions.factfinder.communication.apiKey}}`,
},
appConfig: {
debug: true,
fieldRoles: {{ page.extensions.factfinder.field_roles|json_encode|raw }},
formatting: {
locale: `{{page.extensions.factfinder.communication.currencyCountryCode}}`,
formatOptions: {
style: `currency`,
currency: `{{page.extensions.factfinder.communication.currencyCode}}`,
},
},
},
},
});

const ffRedirectMapping = JSON.parse('{{ page.extensions.factfinder.redirectMapping|raw }}');
});

factfinder.request.before.search(({ searchParams, searchOptions }) => {
const ffRedirectMapping = JSON.parse('{{ page.extensions.factfinder.redirectMapping|raw }}');

if (ffRedirectMapping.hasOwnProperty(searchParams.query)) {
window.location = ffRedirectMapping[searchParams.query];
factfinder.request.before.search(({ searchParams, searchOptions }) => {

return;
}
if (ffRedirectMapping.hasOwnProperty(searchParams.query)) {
window.location = ffRedirectMapping[searchParams.query];

{% if app.request.pathInfo !== "/factfinder/result" %}
if (searchOptions?.requestOptions?.origin?.tagName === `FF-SEARCHBOX`) {
window.location.href = `/factfinder/result?query=${searchParams.query}`;

// Cancel the pipeline to avoid sending a search request to FactFinder before the redirect is complete.
return false;
return;
}
{% endif %}
});

{% if app.request.pathInfo !== "/factfinder/result" %}
factfinder.notifications.addSuggestClickListener(origin => {
if (origin.suggestion.type === `searchTerm` || origin.suggestion.type === `brand`) {
window.location.href = `/factfinder/result?query=${origin.suggestion.searchParams.query}`;
{% if app.request.pathInfo !== "/factfinder/result" %}
if (searchOptions?.requestOptions?.origin?.tagName === `FF-SEARCHBOX`) {
window.location.href = `/factfinder/result?query=${searchParams.query}`;

// Cancel the pipeline to avoid sending a search request to FactFinder before the redirect is complete.
return false;
}
{% endif %}
});

factfinder.notifications.addPopularSearchClickListener(({ origin, popularSearch }) => {
window.location = `/factfinder/result?query=${popularSearch.name}`;
{% if app.request.pathInfo !== "/factfinder/result" %}
factfinder.notifications.addSuggestClickListener(origin => {
if (origin.suggestion.type === `searchTerm` || origin.suggestion.type === `brand`) {
window.location.href = `/factfinder/result?query=${origin.suggestion.searchParams.query}`;

return false;
});
{% endif %}
return false;
}
});

{% if page.extensions.factfinder.searchImmediate and not page.extensions.factfinder.ssr %}
const searchParams = factfinder.utils.env.searchParamsFromUrl(
{ categoryFieldName: `{{ page.extensions.factfinder.categoryPathFieldName }}` }
);
initialSearch(searchParams, { requestOptions: { origin: `initialSearch` } });
{% endif %}
factfinder.notifications.addPopularSearchClickListener(({ origin, popularSearch }) => {
window.location = `/factfinder/result?query=${popularSearch.name}`;

});
</script>
return false;
});
{% endif %}

{% if page.extensions.factfinder.searchImmediate and not page.extensions.factfinder.ssr %}
const searchParams = factfinder.utils.env.searchParamsFromUrl(
{ categoryFieldName: `{{ page.extensions.factfinder.categoryPathFieldName }}` }
);
initialSearch(searchParams, { requestOptions: { origin: `initialSearch` } });
{% endif %}

});
</script>

{% endblock %}
{% endblock %}
{% endif %}

{{ parent() }}
{% endblock %}

{% block base_body_script %}
<script>
const ffTrackingSettings = JSON.parse('{{ page.extensions.factfinder.trackingSettings|json_encode()|raw }}');

{% if page.extensions.factfinder.ssr %}
function generateSid() {
var length = 30;
var characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var text = "";

for (var i = 0; i < length; i++) {
text += characterSet.charAt(Math.floor(Math.random() * characterSet.length));
}
{% if not ff_disable_webc() %}
<script>
const ffTrackingSettings = JSON.parse('{{ page.extensions.factfinder.trackingSettings|json_encode()|raw }}');

return text;
}
{% endif %}
{% if page.extensions.factfinder.ssr %}
function generateSid() {
var length = 30;
var characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var text = "";

document.addEventListener('ffCoreReady', ({ factfinder }) => {
{% if page.extensions.factfinder.ssr == 'ssr' and app.request.attributes.get('_route') == 'frontend.factfinder.result' %}
const searchResult = {FF_SEARCH_RESULT};
for (var i = 0; i < length; i++) {
text += characterSet.charAt(Math.floor(Math.random() * characterSet.length));
}

if (searchResult.hasOwnProperty('records')) {
factfinder.response.dispatch.ssrSearch(searchResult);
return text;
}
{% endif %}

const ffCookies = document.cookie.split('; ').reduce((acc, cookie) => {
const cookieData = cookie.split('=');
const [key, value] = cookieData;
acc[key] = value;
document.addEventListener('ffCoreReady', ({ factfinder }) => {
{% if page.extensions.factfinder.ssr == 'ssr' and app.request.attributes.get('_route') == 'frontend.factfinder.result' %}
const searchResult = {FF_SEARCH_RESULT};

return acc;
}, {});
if (searchResult.hasOwnProperty('records')) {
factfinder.response.dispatch.ssrSearch(searchResult);
}
{% endif %}

const clearCookie = (name) => {
document.cookie = name+'=; Max-Age=-1;';
}
const ffCookies = document.cookie.split('; ').reduce((acc, cookie) => {
const cookieData = cookie.split('=');
const [key, value] = cookieData;
acc[key] = value;

if (ffCookies['ff_user_id']) {
factfinder.config.setFFParams({userId: ffCookies['ff_user_id']});
return acc;
}, {});

if (ffCookies['ff_has_just_logged_in']) {
clearCookie('ff_has_just_logged_in');
factfinder.tracking.login([{
sid: JSON.parse(localStorage.ffwebco).sid,
userId: factfinder.config.get().ffParams.userId
}]);
const clearCookie = (name) => {
document.cookie = name+'=; Max-Age=-1;';
}
} else {
if (ffCookies['ff_has_just_logged_out']) {
clearCookie('ff_has_just_logged_out');
factfinder.config.setFFParams({userId: undefined});
}
}

{% if page.extensions.factfinder.ssr %}
if (!ffCookies['ffwebc_sid']) {
const sid = generateSid();
document.cookie = 'ffwebc_sid=' + sid + '; path=/;';
factfinder.config.setFFParams({sid: sid});
if (ffCookies['ff_user_id']) {
factfinder.config.setFFParams({userId: ffCookies['ff_user_id']});

if (ffCookies['ff_has_just_logged_in']) {
clearCookie('ff_has_just_logged_in');
factfinder.tracking.login([{
sid: JSON.parse(localStorage.ffwebco).sid,
userId: factfinder.config.get().ffParams.userId
}]);
}
} else {
factfinder.config.setFFParams({sid: ffCookies['ffwebc_sid']});
if (ffCookies['ff_has_just_logged_out']) {
clearCookie('ff_has_just_logged_out');
factfinder.config.setFFParams({userId: undefined});
}
}
{% endif %}
});
</script>

{% if page.extensions.factfinder.ssr %}
if (!ffCookies['ffwebc_sid']) {
const sid = generateSid();
document.cookie = 'ffwebc_sid=' + sid + '; path=/;';
factfinder.config.setFFParams({sid: sid});
} else {
factfinder.config.setFFParams({sid: ffCookies['ffwebc_sid']});
}
{% endif %}
});
</script>
{% endif %}

{{ parent() }}
{% endblock %}
Loading
Loading