<commit_before><?php

namespace Oro\Bundle\SegmentBundle\Migrations\Schema\v1_5;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\QueryBuilder;

use Psr\Log\LoggerInterface;

use Oro\Bundle\MigrationBundle\Migration\ConnectionAwareInterface;
use Oro\Bundle\MigrationBundle\Migration\MigrationQuery;

class UpdateDateVariablesQuery implements MigrationQuery, ConnectionAwareInterface
{
    const LIMIT = 100;

    /** @var Connection */
    protected $connection;

    /** @var string */
    protected $segmentTable;

    /**
     * @param string $segmentTable
     */
    public function __construct($segmentTable)
    {
        $this->segmentTable = $segmentTable;
    }

    /**
     * {@inheritdoc}
     */
    public function getDescription()
    {
        return 'Fixes month variables to use new format';
    }

    /**
     * {@inheritdoc}
     */
    public function setConnection(Connection $connection)
    {
        $this->connection = $connection;
    }

    /**
     * {@inheritdoc}
     */
    public function execute(LoggerInterface $logger)
    {
        $steps = ceil($this->getSegmentCount() / static::LIMIT);

        $segmentQb = $this->createSegmentQb()
            ->setMaxResults(static::LIMIT);

        for ($i = 0; $i < $steps; $i++) {
            $rows = $segmentQb
                ->setFirstResult($i * static::LIMIT)
                ->execute()
                ->fetchAll(\PDO::FETCH_ASSOC);

            foreach ($rows as $row) {
                $this->processRow($row);
            }
        }
    }

    /**
     * @param array $row
     */
    private function processRow(array $row)
    {
        $definition = $this->connection->convertToPHPValue($row['definition'], Type::JSON_ARRAY);
        if (empty($definition['filters'])) {
            return;
        }

        $updatedFilters = $this->processFilters($definition['filters']);
        if (!$updatedFilters) {
            return;
        }
        $definition['filters'] = $updatedFilters;

        $this->connection->update(
            $this->segmentTable,
            ['definition' => $definition],
            ['id' => $row['id']],
            [Type::JSON_ARRAY]
        );
    }

    /**
     * @param array $filters
     *
     * @return array|false
     */
    private function processFilters(array $filters)
    {
        $updates = [];
        foreach ($filters as $key => $filter) {
            if (isset($filter['criterion'])) {
                $updates[$key] = $this->updateFilterValue($filter);
            } elseif (is_array($filter)) {
                $updates[$key] = $this->processFilters($filter);
            }
        }

        $validUpddates = array_filter($updates);
        if (!$validUpddates) {
            return false;
        }

        return $validUpddates + $filters;
    }

    /**
     * @param array $filter
     *
     * @return array|false
     */
    private function updateFilterValue(array $filter)
    {
        if (!isset(
            $filter['criterion']['filter'],
            $filter['criterion']['data'],
            $filter['criterion']['data']['part']
        ) &&
            !in_array($filter['criterion']['filter'], ['date', 'datetime']) &&
            !$filter['criterion']['data']['part'] === 'month'
        ) {
            return false;
        }

        $value = $filter['criterion']['data']['value'];
        if ($newStart = $this->updateMonthValue($value['start'])) {
            $filter['criterion']['data']['value']['start'] = $newStart;
        }
        if ($newEnd = $this->updateMonthValue($value['end'])) {
            $filter['criterion']['data']['value']['end'] = $newEnd;
        }

        return !$newStart && !$newEnd ? false : $filter;
    }
<commit_msg>BAP-9351: Date variable couldn't be used in reports/segments<commit_after><?php

namespace Oro\Bundle\SegmentBundle\Migrations\Schema\v1_5;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\QueryBuilder;

use Psr\Log\LoggerInterface;

use Oro\Bundle\MigrationBundle\Migration\ConnectionAwareInterface;
use Oro\Bundle\MigrationBundle\Migration\MigrationQuery;

class UpdateDateVariablesQuery implements MigrationQuery, ConnectionAwareInterface
{
    const LIMIT = 100;

    /** @var Connection */
    protected $connection;

    /** @var string */
    protected $segmentTable;

    /**
     * @param string $segmentTable
     */
    public function __construct($segmentTable)
    {
        $this->segmentTable = $segmentTable;
    }

    /**
     * {@inheritdoc}
     */
    public function getDescription()
    {
        return 'Fixes month variables to use new format';
    }

    /**
     * {@inheritdoc}
     */
    public function setConnection(Connection $connection)
    {
        $this->connection = $connection;
    }

    /**
     * {@inheritdoc}
     */
    public function execute(LoggerInterface $logger)
    {
        $steps = ceil($this->getSegmentCount() / static::LIMIT);

        $segmentQb = $this->createSegmentQb()
            ->setMaxResults(static::LIMIT);

        for ($i = 0; $i < $steps; $i++) {
            $rows = $segmentQb
                ->setFirstResult($i * static::LIMIT)
                ->execute()
                ->fetchAll(\PDO::FETCH_ASSOC);

            foreach ($rows as $row) {
                $this->processRow($row);
            }
        }
    }

    /**
     * @param array $row
     */
    private function processRow(array $row)
    {
        $definition = $this->connection->convertToPHPValue($row['definition'], Type::JSON_ARRAY);
        if (empty($definition['filters'])) {
            return;
        }

        $updatedFilters = $this->processFilters($definition['filters']);
        if (!$updatedFilters) {
            return;
        }
        $definition['filters'] = $updatedFilters;

        $this->connection->update(
            $this->segmentTable,
            ['definition' => $definition],
            ['id' => $row['id']],
            [Type::JSON_ARRAY]
        );
    }

    /**
     * @param array $filters
     *
     * @return array|false
     */
    private function processFilters(array $filters)
    {
        $updates = [];
        foreach ($filters as $key => $filter) {
            if (isset($filter['criterion'])) {
                $updates[$key] = $this->updateFilterValue($filter);
            } elseif (is_array($filter)) {
                $updates[$key] = $this->processFilters($filter);
            }
        }

        $validUpddates = array_filter($updates);
        if (!$validUpddates) {
            return false;
        }

        $updatedFilters = $validUpddates + $filters;
        ksort($updatedFilters);

        return $updatedFilters;
    }

    /**
     * @param array $filter
     *
     * @return array|false
     */
    private function updateFilterValue(array $filter)
    {
        if (!isset(
            $filter['criterion']['filter'],
            $filter['criterion']['data'],
            $filter['criterion']['data']['part']
        ) &&
            !in_array($filter['criterion']['filter'], ['date', 'datetime']) &&
            !$filter['criterion']['data']['part'] === 'month'
        ) {
            return false;
        }

        $value = $filter['criterion']['data']['value'];
        if ($newStart = $this->updateMonthValue($value['start'])) {
            $filter['criterion']['data']['value']['start'] = $newStart;
        }
        if ($newEnd = $this->updateMonthValue($value['end'])) {
            $filter['criterion']['data']['value']['end'] = $newEnd;
        }

        return !$newStart && !$newEnd ? false : $filter;
    }

{'fraction_non_alphanumeric': 0.1580259876624229, 'fraction_numerical': 0.002100013125082032, 'mean_word_length': 2.096302316131654, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 47, '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': '7324255', 'n_tokens_mistral': 2163, 'n_tokens_neox': 2137, 'n_words': 376}