<commit_before><?php

/*
 * This file is part of the Admin Bundle.
 *
 * Copyright (c) 2015-2016 LIN3S <<EMAIL>>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace LIN3S\AdminBundle\Repository;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use LIN3S\AdminBundle\Configuration\EntityConfiguration;
use LIN3S\AdminBundle\ListFields\ListField;
use Symfony\Component\HttpFoundation\Request;

/**
 * Default implementation of QueryBuilder.
 *
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 */
class DefaultQueryBuilder implements QueryBuilder
{
    /**
     * The entity manager.
     *
     * @var EntityManager
     */
    protected $manager;

    /**
     * DefaultQueryBuilder constructor.
     *
     * @param EntityManager $manager The entity manager
     */
    public function __construct(EntityManager $manager)
    {
        $this->manager = $manager;
    }

    /**
     * {@inheritdoc}
     */
    public function generate(Request $request, EntityConfiguration $config)
    {
        $queryBuilder = $this->manager->getRepository($config->className())->createQueryBuilder('a');
        $metadata = $this->manager->getClassMetadata($config->className());
        $associations = $this->resolveAssociations($config, $metadata);

        $queryBuilder->groupBy('a.' . $metadata->identifier[0]);

        foreach ($associations as $association) {
            $queryBuilder->join('a.' . $association, 'join_' . $association);
        }

        if ($request->get('orderBy')) {
            $possibleAssociation = explode('.', $request->get('orderBy'))[0];

            $found = false;
            foreach ($metadata->getAssociationMappings() as $associationMapping) {
                if ($possibleAssociation === $associationMapping['fieldName']) {
                    $queryBuilder->addOrderBy(
                        'join_' . $associationMapping['fieldName'] . '.' . explode('.', $request->get('orderBy'))[1],
                        $request->get('order', 'ASC')
                    );
                    $found = true;
                    continue;
                }
            }
            if (!$found) {
                $queryBuilder->addOrderBy('a.' . $request->get('orderBy'), $request->get('order', 'ASC'));
            }
        }

        if ($request->get('filterBy') && $request->get('filter')) {
            $previousId = 97;

            if ($this->isTableRelation($metadata, $request->get('filterBy'))) {
                $associations = explode('.', $request->get('filterBy'));
                for ($i = 0; $i < count($associations) - 1; ++$i) {
                    if (false === $this->isTableRelation($metadata, $associations[$i] . '.' . $associations[$i + 1])) {
                        break;
                    }
                    $queryBuilder->innerJoin(chr($previousId) . '.' . $associations[$i], chr($previousId + 1));
                    ++$previousId;
                    foreach ($metadata->getAssociationMappings() as $associationMapping) {
                        if ($associationMapping['fieldName'] === $associations[$i]) {
                            $metadata = $this->manager->getClassMetadata($associationMapping['targetEntity']);
                        }
                    }
                }
                $queryBuilder->where($queryBuilder->expr()->like(
                    chr($previousId) . '.' . $associations[count($associations) - 1],
                    "'%" . $request->get('filter') . "%'"
                ));
            } else {
                $queryBuilder->where($queryBuilder->expr()->like(
                    chr($previousId) . '.' . $request->get('filterBy'),
                    "'%" . $request->get('filter') . "%'"
                ));
            }
        }

        return $queryBuilder;
    }

    /**
     * Checks if the association is between two tables returning true,
     * otherwise, returns false if associations is based on inheritance.
     *
     * @param ClassMetadata $metadata    The class metadata
     * @param string        $association The association field name
     *
     * @return bool
     */
    private function isTableRelation($metadata, $association)
    {
        foreach ($metadata->fieldMappings as $fieldMapping) {
            if ($fieldMapping['fieldName'] === $association) {
                return false;
            }
        }

        return true;
    }

    /**
     * Resolves associations.
     *
     * @param EntityConfiguration $config   The entity configuration
     * @param ClassMetadata       $metadata The class metadata
     * @param Request             $request<commit_msg>Made more flexible the query builder<commit_after><?php

/*
 * This file is part of the Admin Bundle.
 *
 * Copyright (c) 2015-2016 LIN3S <<EMAIL>>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace LIN3S\AdminBundle\Repository;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use LIN3S\AdminBundle\Configuration\EntityConfiguration;
use LIN3S\AdminBundle\ListFields\ListField;
use Symfony\Component\HttpFoundation\Request;

/**
 * Default implementation of QueryBuilder.
 *
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 */
class DefaultQueryBuilder implements QueryBuilder
{
    /**
     * The entity manager.
     *
     * @var EntityManager
     */
    protected $manager;

    /**
     * Constructor.
     *
     * @param EntityManager $manager The entity manager
     */
    public function __construct(EntityManager $manager)
    {
        $this->manager = $manager;
    }

    /**
     * {@inheritdoc}
     */
    public function generate(Request $request, EntityConfiguration $config)
    {
        $queryBuilder = $this->manager->getRepository($config->className())->createQueryBuilder('a');
        $metadata = $this->manager->getClassMetadata($config->className());
        $associations = $this->resolveAssociations($config, $metadata);

        $queryBuilder->groupBy('a.' . $metadata->identifier[0]);

        foreach ($associations as $association) {
            $queryBuilder->join('a.' . $association, 'join_' . $association);
        }

        if ($request->get('orderBy')) {
            $possibleAssociation = explode('.', $request->get('orderBy'))[0];

            $found = false;
            foreach ($metadata->getAssociationMappings() as $associationMapping) {
                if ($possibleAssociation === $associationMapping['fieldName']) {
                    $queryBuilder->addOrderBy(
                        'join_' . $associationMapping['fieldName'] . '.' . explode('.', $request->get('orderBy'))[1],
                        $request->get('order', 'ASC')
                    );
                    $found = true;
                    continue;
                }
            }
            if (!$found) {
                $queryBuilder->addOrderBy('a.' . $request->get('orderBy'), $request->get('order', 'ASC'));
            }
        }

        if ($request->get('filterBy') && $request->get('filter')) {
            $previousId = 97;

            if ($this->isTableRelation($metadata, $request->get('filterBy'))) {
                $associations = explode('.', $request->get('filterBy'));
                $fields = $associations;
                for ($i = 0; $i < count($associations) - 1; ++$i) {
                    if (false === $this->isTableRelation($metadata, $associations[$i] . '.' . $associations[$i + 1])) {
                        break;
                    }
                    $queryBuilder->innerJoin(chr($previousId) . '.' . $associations[$i], chr($previousId + 1));
                    ++$previousId;
                    foreach ($metadata->getAssociationMappings() as $associationMapping) {
                        if ($associationMapping['fieldName'] === $associations[$i]) {
                            $metadata = $this->manager->getClassMetadata($associationMapping['targetEntity']);
                        }
                    }
                    unset($fields[$i]);
                }

                $fields = implode('.', $fields);

                $queryBuilder->where($queryBuilder->expr()->like(
                    chr($previousId) . '.' . $fields,
                    "'%" . $request->get('filter') . "%'"
                ));
            } else {
                $queryBuilder->where($queryBuilder->expr()->like(
                    chr($previousId) . '.' . $request->get('filterBy'),
                    "'%" . $request->get('filter') . "%'"
                ));
            }
        }

        return $queryBuilder;
    }

    /**
     * Checks if the association is between two tables returning true,
     * otherwise, returns false if associations is based on inheritance.
     *
     * @param ClassMetadata $metadata    The class metadata
     * @param string        $association The association field name
     *
     * @return bool
     */
    private function isTableRelation($metadata, $association)
    {
        foreach ($metadata->fieldMappings as $fieldMapping) {
            if ($fieldMapping['fieldName'] === $association) {
                return false;
            }
        }

        return true;
    }

    /**
     * Resolves associations.
     *
     * @param EntityConfiguration $config   The entity configuration
     * @param ClassMetadata       $metadata The class metadata
{'fraction_non_alphanumeric': 0.1440873766015543, 'fraction_numerical': 0.004515858013022474, 'mean_word_length': 1.9319581280788178, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 101, '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': '2765292', 'n_tokens_mistral': 2508, 'n_tokens_neox': 2379, 'n_words': 507}