<commit_before><?php

namespace Mapbender\CoreBundle\Component;

use Doctrine\DBAL\Platforms\PostgreSqlPlatform;


class SQLSearchEngine
{

    protected $container;

    public function __construct($container)
    {
        $this->container = $container;
    }

    /**
     * SQL Autocomplete method
     *
     * @todo Make like search configurable (exact, left, right, both)
     * @todo Make case invariant configurable
     * @todo Limit results
     *
     * @param  Array  $config     Search configuration
     * @param  String $key        Autocomplete field nme
     * @param  String $value      Autocomplete value
     * @param  Object $properties All form values
     * @param  String $srs        Current map SRS
     * @param  Array  $extent     Current map extent
     * @return Array              Autocomplete suggestions
     */
    public function autocomplete($config, $key, $value, $properties, $srs, $extent)
    {
        // First, get DBAL connection service, either given one or default one
        $connection = $config['class_options']['connection'] ? : 'default';
        $connection = $this->container->get('doctrine.dbal.' . $connection . '_connection');
        $qb = $connection->createQueryBuilder();

        $distinct = false;
        if(array_key_exists('attr', $config['form'][$key]['options'])
            && array_key_exists('data-autocomplete-distinct', $config['form'][$key]['options']['attr'])
            && strtolower($config['form'][$key]['options']['attr']['data-autocomplete-distinct']) == 'on') {
            $distinct = true;
        }

        $keys = array($key);
        $values = array($value);
        if(array_key_exists('split', $config['form'][$key])) {
            $keys = $config['form'][$key]['split'];
            $values = explode(' ', $value);
        }

        // Build SELECT
        $select = implode(', ', array_map(function($attribute) {
            return 't.' . $attribute;
        }, $keys));

        if(array_key_exists('autocomplete-key', $config['form'][$key])) {
            $select .= ', t.' . $config['form'][$key]['autocomplete-key'];
        }

        $qb->select($distinct ? 'DISTINCT ' . $select : $select);

        // Add FROM
        $qb->from($config['class_options']['relation'], 't');

        // Build WHERE condition
        $cond = $qb->expr()->andx();
        $params = array();
        for($i = 0; $i < count($keys); $i++) {
            // @todo: Platform independency (::varchar, lower)
            $cond->add($qb->expr()->like('LOWER(t.' . $keys[$i] . '::varchar)', '?'));
            $params[] = '%' . (count($values) > $i ? strtolower($values[$i]) : '') . '%';
        }

        $logger = $this->container->get('logger');

        if(array_key_exists('attr', $config['form'][$key]['options'])
            && array_key_exists('data-autocomplete-using', $config['form'][$key]['options']['attr'])) {
            $using = explode(',', $config['form'][$key]['options']['attr']['data-autocomplete-using']);
            array_walk($using, function($key) use ($properties, $logger, $cond, $qb, &$params) {
                if(property_exists($properties, $key)) {
                    $value = $properties->$key;
                    if(!$value) {
                        return;
                    }
                    $cond->add($qb->expr()->eq('t.' . $key, '?'));
                    $params[] = $value;
                } else {
                    $logger->warn('Key "' . $key . '" for autocomplete-using does not exist in data.');
                }
            });
        }

        $qb->where($cond);

        // Create prepared statement and execute
        $stmt = $connection->executeQuery($qb->getSql(), $params);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        array_walk($rows, function(&$row) use ($key, $keys, $config) {
            $value = array();
            foreach($keys as $k) {
                $value[] = $row[$k];
            }

            if(array_key_exists('autocomplete-key', $config['form'][$key])) {
                $row = array(<commit_msg>SearchRouter - sort autocomplete results<commit_after><?php

namespace Mapbender\CoreBundle\Component;

use Doctrine\DBAL\Platforms\PostgreSqlPlatform;


class SQLSearchEngine
{

    protected $container;

    public function __construct($container)
    {
        $this->container = $container;
    }

    /**
     * SQL Autocomplete method
     *
     * @todo Make like search configurable (exact, left, right, both)
     * @todo Make case invariant configurable
     * @todo Limit results
     *
     * @param  Array  $config     Search configuration
     * @param  String $key        Autocomplete field nme
     * @param  String $value      Autocomplete value
     * @param  Object $properties All form values
     * @param  String $srs        Current map SRS
     * @param  Array  $extent     Current map extent
     * @return Array              Autocomplete suggestions
     */
    public function autocomplete($config, $key, $value, $properties, $srs, $extent)
    {
        // First, get DBAL connection service, either given one or default one
        $connection = $config['class_options']['connection'] ? : 'default';
        $connection = $this->container->get('doctrine.dbal.' . $connection . '_connection');
        $qb = $connection->createQueryBuilder();

        $distinct = false;
        if(array_key_exists('attr', $config['form'][$key]['options'])
            && array_key_exists('data-autocomplete-distinct', $config['form'][$key]['options']['attr'])
            && strtolower($config['form'][$key]['options']['attr']['data-autocomplete-distinct']) == 'on') {
            $distinct = true;
        }

        $keys = array($key);
        $values = array($value);
        if(array_key_exists('split', $config['form'][$key])) {
            $keys = $config['form'][$key]['split'];
            $values = explode(' ', $value);
        }

        // Build SELECT
        $select = implode(', ', array_map(function($attribute) {
            return 't.' . $attribute;
        }, $keys));

        if(array_key_exists('autocomplete-key', $config['form'][$key])) {
            $select .= ', t.' . $config['form'][$key]['autocomplete-key'];
        }

        $qb->select($distinct ? 'DISTINCT ' . $select : $select);

        // Add FROM
        $qb->from($config['class_options']['relation'], 't');

        // Build WHERE condition
        $cond = $qb->expr()->andx();
        $params = array();
        for($i = 0; $i < count($keys); $i++) {
            // @todo: Platform independency (::varchar, lower)
            $cond->add($qb->expr()->like('LOWER(t.' . $keys[$i] . '::varchar)', '?'));
            $params[] = '%' . (count($values) > $i ? strtolower($values[$i]) : '') . '%';
        }

        $logger = $this->container->get('logger');

        if(array_key_exists('attr', $config['form'][$key]['options'])
            && array_key_exists('data-autocomplete-using', $config['form'][$key]['options']['attr'])) {
            $using = explode(',', $config['form'][$key]['options']['attr']['data-autocomplete-using']);
            array_walk($using, function($key) use ($properties, $logger, $cond, $qb, &$params) {
                if(property_exists($properties, $key)) {
                    $value = $properties->$key;
                    if(!$value) {
                        return;
                    }
                    $cond->add($qb->expr()->eq('t.' . $key, '?'));
                    $params[] = $value;
                } else {
                    $logger->warn('Key "' . $key . '" for autocomplete-using does not exist in data.');
                }
            });
        }

        $qb->where($cond);
        $qb->orderBy('t.' . $key, 'ASC');

        // Create prepared statement and execute
        $stmt = $connection->executeQuery($qb->getSql(), $params);
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        array_walk($rows, function(&$row) use ($key, $keys, $config) {
            $value = array();
            foreach($keys as $k) {
                $value[] = $row[$k];
            }

            if(array_key_exists('autocomplete-key', $config['form'][$key])) {
                $row = array(
{'fraction_non_alphanumeric': 0.18247108947048082, 'fraction_numerical': 0.00024345709068776628, 'mean_word_length': 2.1734260332174586, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1367313', 'n_tokens_mistral': 2414, 'n_tokens_neox': 2321, 'n_words': 469}