* @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) */ namespace PrestaShop\Module\FacetedSearch; use PrestaShop\Module\FacetedSearch\Filters\Converter; use PrestaShop\PrestaShop\Core\Product\Search\Facet; use PrestaShop\PrestaShop\Core\Product\Search\Filter; class URLSerializer { /** * Add filter * * @param array $facetFilters * @param Filter $facetFilter * @param Facet $facet * * @return array */ public function addFilterToFacetFilters(array $facetFilters, Filter $facetFilter, Facet $facet) { $facetLabel = $this->getFacetLabel($facet); $filterLabel = $this->getFilterLabel($facetFilter); if ($facet->getProperty('range')) { $facetValue = $facet->getProperty('values'); $facetFilters[$facetLabel] = [ $facetFilter->getProperty('symbol'), isset($facetValue[0]) ? $facetValue[0] : $facet->getProperty('min'), isset($facetValue[1]) ? $facetValue[1] : $facet->getProperty('max'), ]; } else { $facetFilters[$facetLabel][$filterLabel] = $filterLabel; } return $facetFilters; } /** * Remove filter * * @param array $facetFilters * @param Filter $facetFilter * @param Facet $facet * * @return array */ public function removeFilterFromFacetFilters(array $facetFilters, Filter $facetFilter, $facet) { $facetLabel = $this->getFacetLabel($facet); if ($facet->getProperty('range')) { unset($facetFilters[$facetLabel]); } else { $filterLabel = $this->getFilterLabel($facetFilter); unset($facetFilters[$facetLabel][$filterLabel]); if (empty($facetFilters[$facetLabel])) { unset($facetFilters[$facetLabel]); } } return $facetFilters; } /** * Get active facet filters * * @return array */ public function getActiveFacetFiltersFromFacets(array $facets) { $facetFilters = []; foreach ($facets as $facet) { foreach ($facet->getFilters() as $facetFilter) { if (!$facetFilter->isActive()) { // Filter is not active continue; } $facetLabel = $this->getFacetLabel($facet); $filterLabel = $this->getFilterLabel($facetFilter); if (!$facet->getProperty('range')) { $facetFilters[$facetLabel][$filterLabel] = $filterLabel; continue; } $facetValue = $facetFilter->getValue(); $facetFilters[$facetLabel] = [ $facetFilter->getProperty('symbol'), $facetValue[0], $facetValue[1], ]; } } return $facetFilters; } /** * Get Facet label * * @param Facet $facet * * @return string */ private function getFacetLabel(Facet $facet) { if ($facet->getProperty(Converter::PROPERTY_URL_NAME) !== null) { return $facet->getProperty(Converter::PROPERTY_URL_NAME); } return $facet->getLabel(); } /** * Get Facet Filter label * * @param Filter $facetFilter * * @return string */ private function getFilterLabel(Filter $facetFilter) { if ($facetFilter->getProperty(Converter::PROPERTY_URL_NAME) !== null) { return $facetFilter->getProperty(Converter::PROPERTY_URL_NAME); } return $facetFilter->getLabel(); } /** * @param array $fragment * * @return string */ public function serialize(array $fragment) { $parts = []; foreach ($fragment as $key => $values) { array_unshift($values, $key); $parts[] = $this->serializeListOfStrings($values, '-'); } return $this->serializeListOfStrings($parts, '/'); } /** * @param string $string * * @return array */ public function unserialize($string) { $fragment = []; $parts = $this->unserializeListOfStrings($string, '/'); foreach ($parts as $part) { $values = $this->unserializeListOfStrings($part, '-'); $key = array_shift($values); $fragment[$key] = $values; } return $fragment; } /** * @param string $separator the string separator * @param string $escape the string escape * @param array $list * * @return string */ private function serializeListOfStrings($list, $separator, $escape = '\\') { return implode($separator, array_map(function ($item) use ($separator, $escape) { return strtr( $item, [ $separator => $escape . $separator, ] ); }, $list)); } /** * @param string $separator the string separator * @param string $escape the string escape * @param string $string the UTF8 string * * @return array */ private function unserializeListOfStrings($string, $separator, $escape = '\\') { $list = []; $currentString = ''; $escaping = false; // get UTF-8 chars, inspired from http://stackoverflow.com/questions/9438158/split-utf8-string-into-array-of-chars $arrayOfCharacters = []; preg_match_all('/./u', $string, $arrayOfCharacters); $characters = $arrayOfCharacters[0]; foreach ($characters as $index => $character) { if ($character === $escape && isset($characters[$index + 1]) && $characters[$index + 1] === $separator ) { $escaping = true; continue; } if ($character === $separator && $escaping === false) { $list[] = $currentString; $currentString = ''; continue; } $currentString .= $character; $escaping = false; } if ('' !== $currentString) { $list[] = $currentString; } return $list; } }