Skip to content

Commit

Permalink
FFWEB-3057: New routing implementation
Browse files Browse the repository at this point in the history
New routing implementation - implement add param feature
  • Loading branch information
Rayn93 authored May 28, 2024
1 parent 587efd5 commit 754c26d
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 84 deletions.
26 changes: 26 additions & 0 deletions src/Block/Adminhtml/System/Config/Field/AddUrlParameters.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Omikron\Factfinder\Block\Adminhtml\System\Config\Field;

use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;

/**
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*/
class AddUrlParameters extends AbstractFieldArray
{
protected function _prepareToRender()
{
$this->_addAfter = false;
$this->addColumn('name', [
'label' => __('Parameter name'),
'class' => 'required-entry',
]);
$this->addColumn('value', [
'label' => __('Parameter value'),
'class' => 'required-entry',
]);
}
}
22 changes: 22 additions & 0 deletions src/Block/Adminhtml/System/Config/Field/ParameterWhitelist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Omikron\Factfinder\Block\Adminhtml\System\Config\Field;

use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;

/**
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*/
class ParameterWhitelist extends AbstractFieldArray
{
protected function _prepareToRender()
{
$this->_addAfter = false;
$this->addColumn('name', [
'label' => __('Parameter name'),
'class' => 'required-entry',
]);
}
}
20 changes: 14 additions & 6 deletions src/Model/Config/Communication/BehaviourConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Omikron\Factfinder\Model\Config\Communication;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Store\Model\ScopeInterface;
use Omikron\Factfinder\Api\Config\ParametersSourceInterface;

Expand All @@ -13,17 +14,16 @@ class BehaviourConfig implements ParametersSourceInterface
private const PATH_ADD_PARAMS = 'factfinder/advanced/add_params';
private const PATH_PARAMETER_WHITELIST = 'factfinder/advanced/parameter_whitelist';

private ScopeConfigInterface $scopeConfig;

public function __construct(ScopeConfigInterface $scopeConfig)
{
$this->scopeConfig = $scopeConfig;
public function __construct(
private readonly ScopeConfigInterface $scopeConfig,
private readonly Json $serializer
) {
}

public function getParameters(): array
{
$parameters = [
'add-params' => $this->getConfig(self::PATH_ADD_PARAMS), // postStringifier
'add-params' => $this->getAddParams(), // postStringifier
'parameter-whitelist' => $this->getConfig(self::PATH_PARAMETER_WHITELIST), // allow setUrlParamOptionsListener
];

Expand All @@ -34,4 +34,12 @@ private function getConfig(string $path): string
{
return (string) $this->scopeConfig->getValue($path, ScopeInterface::SCOPE_STORES);
}

private function getAddParams(): array
{
$storedValue = $this->scopeConfig->getValue(self::PATH_ADD_PARAMS);
$unserialized = array_values($this->serializer->unserialize($storedValue ?: '[]'));

return array_column($unserialized, 'value', 'name');
}
}
12 changes: 0 additions & 12 deletions src/Test/Unit/ViewModel/CategoryPathTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,6 @@ class CategoryPathTest extends TestCase
/** @var MockObject|CommunicationConfig */
private MockObject $communicationConfig;

public function test_category_path_for_standard_version()
{
$this->communicationConfig->method('getVersion')->willReturn('7.3');
$categoryPath = $this->newCategoryPath($this->communicationConfig);

$this->currentCategory->method('getParentCategories')
->willReturn([$this->category('Jackets +Size', 3), $this->category('Men 100%', 1), $this->category('Tops & 1/2', 2)]);

$value = 'filterCategoryPathROOT=Men+100%25,filterCategoryPathROOT%2FMen+100%2525=Tops+%26+1%2F2,filterCategoryPathROOT%2FMen+100%2525%2FTops+%26+1%252F2=Jackets+%2BSize';
$this->assertSame($value, (string) $categoryPath->getAddParams());
}

public function test_category_names_are_trimmed()
{
$this->communicationConfig->method('getVersion')->willReturn('ng');
Expand Down
2 changes: 1 addition & 1 deletion src/Test/Unit/ViewModel/CommunicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function test_get_parameters_will_implode_arrays()
$parameters = $this->communication->getParameters($blockParams);

$this->assertArrayHasKey('add-params', $parameters);
$this->assertSame('param1=123,param2=abc', $parameters['add-params']);
$this->assertSame('param1=123', $parameters['add-params']);
}

public function test_multiple_boolean_values_will_be_overwritten()
Expand Down
44 changes: 2 additions & 42 deletions src/ViewModel/CategoryPath.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function __construct(
public function __toString()
{
return $this->communicationConfig->getVersion() === Version::NG ? $this->getCategoryPath(
) : $this->getAddParams();
) : '';
}

public function getCategoryPath(): array
Expand All @@ -32,39 +32,17 @@ public function getCategoryPath(): array

foreach ($this->getParentCategories($this->getCurrentCategory()) as $item) {
$categoryName = trim($item->getName());
$values[] = $categoryName;
$values[] = $categoryName;
}

return $values;
}

public function getAddParams(): string
{
if ($this->communicationConfig->getVersion() === Version::NG) {
return '';
}

return implode(',', $this->standardPath($this->getCurrentCategory()));
}

public function getCategoryPathFieldName(): string
{
return $this->param;
}

private function standardPath(?Category $category): array
{
$path = 'ROOT';
$value = $this->initial;
foreach ($this->getParentCategories($category) as $item) {
$categoryName = trim($item->getName());
$value[] = sprintf("filter{$this->param}%s=%s", $path, urlencode($categoryName));
$path .= urlencode('/' . $this->encodeCategoryName($categoryName));
}

return $value;
}

/**
* @param Category|null $category
*
Expand All @@ -82,22 +60,4 @@ private function getCurrentCategory(): ?Category
{
return $this->registry->registry('current_category');
}

private function encodeCategoryName(string $path): string
{
//important! do not override this method
return preg_replace(
'/\+/',
'%2B',
preg_replace(
'/\//',
'%2F',
preg_replace(
'/%/',
'%25',
$path
)
)
);
}
}
13 changes: 2 additions & 11 deletions src/ViewModel/Communication.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,12 @@ class Communication implements ArgumentInterface
{
private const PATH_USE_SRR = 'factfinder/general/use_ssr';

/** @var string[] */
private array $mergeableParams;

public function __construct(
private readonly FieldRoles $fieldRoles,
private readonly SerializerInterface $serializer,
private readonly CommunicationParametersProvider $parametersProvider,
private readonly ScopeConfigInterface $scopeConfig,
array $mergeableParams = [
'add-params',
'parameter-whitelist'
],
) {
$this->mergeableParams = array_combine($mergeableParams, array_fill(0, count($mergeableParams), ''));
}

public function getParameters(array $blockParams = []): array
Expand All @@ -54,9 +46,8 @@ public function isSsrEnable(): bool

private function mergeParameters(array ...$params): array
{
$params = array_map(fn (array $param) => array_intersect_key($param + $this->mergeableParams, $this->mergeableParams), $params);
$params = array_map(fn (array $param) => array_intersect_key($param, []), $params);

return array_reduce(array_keys($this->mergeableParams), fn ($result, $key) => $result
+ [$key => implode(',', array_filter(array_column($params, $key)))], []);
return $params;
}
}
18 changes: 10 additions & 8 deletions src/etc/adminhtml/system/advanced.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@
<comment>The advanced settings can change how the search works. Please edit them with caution and only if you know what they are doing.</comment>
<field id="internal_ips" translate="label comment" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Internal IPs</label>
<tooltip>Comma-separated value</tooltip>
<comment>Requests from these IPs will be excluded from your license plan</comment>
<tooltip>Requests from these IPs will be excluded from your license plan</tooltip>
</field>
<field id="parameter_whitelist" translate="label comment tooltip" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Parameter whitelist</label>
<comment>If any URL parameters are omitted through other attributes like use-url-parameter="false" or only-search-params you can add specific important parameters manually. Just use a comma separated list like: parameter-whitelist="param1,myParam"</comment>
<tooltip>Comma-separated value</tooltip>
<frontend_model>Omikron\Factfinder\Block\Adminhtml\System\Config\Field\ParameterWhitelist</frontend_model>
<backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
<tooltip>Specifies a list of search parameter names (as they appear in a _SearchParams_ object) that shall be considered for stringification.
Search parameters that are not listed are discarded and will not appear in the URL.</tooltip>
</field>
<field id="add_params" translate="label comment tooltip" type="text" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Add search parameters</label>
<comment>With this property you can deliver standard parameters which will then be attached to the search request. Example: param1=abc,param2=xyz.</comment>
<tooltip>Comma-separated value</tooltip>
<label>Add URL parameters</label>
<frontend_model>Omikron\Factfinder\Block\Adminhtml\System\Config\Field\AddUrlParameters</frontend_model>
<backend_model>Magento\Config\Model\Config\Backend\Serialized\ArraySerialized</backend_model>
<tooltip>With this property you can deliver standard parameters which will then be attached to the search or navigation request.</tooltip>
</field>
<field id="anonymize_user_id" translate="label comment" type="select" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Anonymize user id</label>
<comment>Sends hashed user id with tracking requests</comment>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<tooltip>Sends hashed user id with tracking requests</tooltip>
</field>
</group>
</include>
1 change: 0 additions & 1 deletion src/view/frontend/layout/factfinder_category_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
<referenceBlock name="factfinder.communication">
<arguments>
<argument name="communication_parameters" xsi:type="array">
<item name="add-params" xsi:type="helper" helper="Omikron\Factfinder\ViewModel\CategoryPath::getAddParams" />
<item name="category-page" xsi:type="helper" helper="Omikron\Factfinder\ViewModel\CategoryPath::getCategoryPath" />
<item name="search-immediate" xsi:type="string">false</item>
</argument>
Expand Down
21 changes: 19 additions & 2 deletions src/view/frontend/templates/ff/communication.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ $searchImmediate = $communicationParameters['search-immediate'] ?? 'false';
factfinder.config.apiKey = `<?= $escaper->escapeHtml($parameters['api_key'])?>`;
factfinder.config.fieldRoles = <?= /* @noEscape */ $viewModel->getFieldRoles() ?>;

<?php if(!empty($parameters['add-params'])) : ?>
factfinder.routing.setUrlParamOptionsListener(() => ({
postStringifier: pairs => {
<?php foreach ($parameters['add-params'] as $name => $value) {
/* @noEscape */ echo "pairs.push({ key: `{$name}`, value: `{$value}` });";
} ?>

return pairs;
},
}));
<?php endif; ?>

factfinder.config.formatting = {
locale: `<?= $escaper->escapeUrl($parameters['currency-country-code'])?>`,
formatOptions: {
Expand All @@ -30,15 +42,20 @@ $searchImmediate = $communicationParameters['search-immediate'] ?? 'false';

// This is also the best place to invoke a search request replacing the `search-immediate` attribute.

if (<?= /** @SuppressWarnings(PHPMD) */ $searchImmediate ?>){
if (<?= /** @SuppressWarnings(PHPMD) */ $searchImmediate ?>) {
const searchParams = factfinder.utils.env.searchParamsFromUrl();
initialSearch(searchParams, { requestOptions: { origin: `initialSearch` } });
}

factfinder.request.before.search(({ searchParams, searchOptions }) => {
// If the search request was invoked by `ff-searchbox`, `searchOptions.requestOptions.origin` will be a reference to the `ff-searchbox` element.
if (searchOptions?.requestOptions?.origin?.tagName === `FF-SEARCHBOX`) {
window.location.href = `/factfinder/result?query=${searchParams.query}`;
<?php if(!empty($parameters['add-params'])) : ?>
window.location.href = `/factfinder/result?query=${searchParams.query}&<?= /* @noEscape */ http_build_query($parameters['add-params']) ?>`;
<?php else : ?>
window.location.href = `/factfinder/result?query=${searchParams.query}`;
<?php endif; ?>


// Cancel the pipeline to avoid sending a search request to FactFinder before the redirect is complete.
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/view/frontend/web/ff-web-components/bundle.js

Large diffs are not rendered by default.

0 comments on commit 754c26d

Please sign in to comment.