Your IP : 127.0.0.1


Current Path : /home/Mirasvit/SearchElasticNative/Adapter/Query/
Upload File :
Current File : /home/Mirasvit/SearchElasticNative/Adapter/Query/MatchQuery.php

<?php
/**
 * Mirasvit
 *
 * This source file is subject to the Mirasvit Software License, which is available at https://mirasvit.com/license/.
 * Do not edit or add to this file if you wish to upgrade the to newer versions in the future.
 * If you wish to customize this module for your needs.
 * Please refer to http://www.magentocommerce.com for more information.
 *
 * @category  Mirasvit
 * @package   mirasvit/module-search
 * @version   1.0.151
 * @copyright Copyright (C) 2020 Mirasvit (https://mirasvit.com/)
 */



namespace Mirasvit\SearchElasticNative\Adapter\Query;

use Magento\Framework\Search\Request\QueryInterface;
use Magento\Framework\Search\Request\Query\Match;
use Mirasvit\Search\Api\Service\QueryServiceInterface;
use Mirasvit\Search\Model\Config;

class MatchQuery
{
    /**
     * @var QueryServiceInterface
     */
    private $queryService;

    /**
     * MatchQuery constructor.
     * @param QueryServiceInterface $queryService
     */
    public function __construct(
        QueryServiceInterface $queryService
    ) {
        $this->queryService = $queryService;
    }

    /**
     * @param QueryInterface $matchQuery
     * @return array
     */
    public function build(QueryInterface $matchQuery)
    {
        $query = [];
        $searchQuery = $this->queryService->build($matchQuery->getValue());

        foreach ($matchQuery->getMatches() as $match) {
            $field = $match['field'];
            if ($field == '*') {
                continue;
            }

            $boost = isset($match['boost']) ? (int)$match['boost'] : 1; //sometimes boots is a Phrase
            $fields[$field] = $boost;
        }

        $query['bool']['must'][]['query_string'] = [
            'fields' => array_keys($fields),
            'query'  => $this->compileQuery($searchQuery),
        ];

        foreach ($fields as $field => $boost) {
            if ($boost > 1) {
                $qs = array_filter(explode(' ', $matchQuery->getValue()));

                foreach ($qs as $q) {
                    $query['bool']['should'][]['wildcard'][$field] = [
                        'value' => '*' . strtolower($q) . '*',
                        'boost' => pow(2, $boost),
                    ];
                }
            }
        }

        return $query;
    }

    /**
     * @param array $query
     * @return string
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    private function compileQuery($query)
    {
        $compiled = [];
        foreach ($query as $directive => $value) {
            switch ($directive) {
                case '$like':
                    $compiled[] = '(' . $this->compileQuery($value) . ')';
                    break;

                case '$!like':
                    $compiled[] = '(NOT ' . $this->compileQuery($value) . ')';
                    break;

                case '$and':
                    $and = [];
                    foreach ($value as $item) {
                        $and[] = $this->compileQuery($item);
                    }
                    $compiled[] = '(' . implode(' AND ', $and) . ')';
                    break;

                case '$or':
                    $or = [];
                    foreach ($value as $item) {
                        $or[] = $this->compileQuery($item);
                    }
                    $compiled[] = '(' . implode(' OR ', $or) . ')';
                    break;

                case '$term':
                    $phrase = $this->escape($value['$phrase']);
                    switch ($value['$wildcard']) {
                        case Config::WILDCARD_INFIX:
                            $compiled[] = "$phrase OR *$phrase*";
                            break;
                        case Config::WILDCARD_PREFIX:
                            $compiled[] = "$phrase OR *$phrase";
                            break;
                        case Config::WILDCARD_SUFFIX:
                            $compiled[] = "$phrase OR $phrase*";
                            break;
                        case Config::WILDCARD_DISABLED:
                            $compiled[] = $phrase;
                            break;
                    }
                    break;
            }
        }

        return implode(' AND ', $compiled);
    }

    /**
     * @param string $value
     * @return string
     */
    private function escape($value)
    {
        $pattern = '/(\+|-|\/|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
        $replace = '\\\$1';

        return preg_replace($pattern, $replace, $value);
    }
}