protected function rewriteQueryFilterParameters(Filter $filter, QueryInterface $query, $field, $column)
    {
        $originalExpression = $filter->getExpressionObject();

        $reflected = new ReflectionProperty(CompositeExpression::class, 'parts');
        $reflected->setAccessible(true);

        $reflected2 = new ReflectionProperty(CompositeExpression::class, 'type');
        $reflected2->setAccessible(true);

        $originalParts = $reflected->getValue($originalExpression);
        foreach ($originalParts as &$part) {
            /** @var \Bolt\Storage\Query\SelectQuery $query */
            $part = str_replace('_' . $query->getContenttype() . '.' . $field, $field . '.' . $column, $part);
        }
        $reflected->setValue($originalExpression, $originalParts);

        if ($originalExpression->getType() === 'AND' && count($originalParts) > 1) {
            $platform = $query->getQueryBuilder()->getConnection()->getDatabasePlatform();
            $reflected2->setValue($originalExpression, 'OR');
            $reflected->setValue($originalExpression, [1]);
            foreach ($query->getWhereParametersFor($field) as $paramKey => $paramValue) {
                $query->getQueryBuilder()->andHaving($platform->getConcatExpression("','", '_' . $field . '_' . str_replace('_', '', $column), "','") . ' LIKE(' . ':_having_' . $paramKey . ')');
                $query->getQueryBuilder()->setParameter('_having_' . $paramKey, "%,$paramValue,%");
            }
        }

        $filter->setExpression($originalExpression);
    }
protected function rewriteQueryFilterParameters(Filter $filter, QueryInterface $query, $field, $column)
    {
        $originalExpression = $filter->getExpressionObject();

        $reflected = new ReflectionProperty(CompositeExpression::class, 'parts');
        $reflected->setAccessible(true);

        $reflected2 = new ReflectionProperty(CompositeExpression::class, 'type');
        $reflected2->setAccessible(true);

        $originalParts = $reflected->getValue($originalExpression);
        foreach ($originalParts as &$part) {
            /** @var \Bolt\Storage\Query\SelectQuery $query */
            $part = str_replace('_' . $query->getContenttype() . '.' . $field, $field . '.' . $column, $part);
        }
        $reflected->setValue($originalExpression, $originalParts);

        if ($originalExpression->getType() === 'AND' && count($originalParts) > 1) {
            $platform = $query->getQueryBuilder()->getConnection()->getDatabasePlatform();
            $reflected2->setValue($originalExpression, 'OR');
            $reflected->setValue($originalExpression, [1]);
            foreach ($query->getWhereParametersFor($field) as $paramKey => $paramValue) {
                $query->getQueryBuilder()->andHaving($platform->getConcatExpression("','", '_' . $field . '_' . str_replace('_', '', $column), "','") . ' LIKE(' . ':_having_' . $paramKey . ')');
                $query->getQueryBuilder()->setParameter('_having_' . $paramKey, "%,$paramValue,%");
            }
        }

        $filter->setExpression($originalExpression);
    }
protected function rewriteQueryFilterParameters ( Filter $ filter , QueryInterface $ query , $ field , $ column ) { $ originalExpression = $ filter -> getExpressionObject ( ) ; $ reflected = new ReflectionProperty ( CompositeExpression :: class , 'parts' ) ; $ reflected -> setAccessible ( true ) ; $ reflected2 = new ReflectionProperty ( CompositeExpression :: class , 'type' ) ; $ reflected2 -> setAccessible ( true ) ; $ originalParts = $ reflected -> getValue ( $ originalExpression ) ; foreach ( $ originalParts as & $ part ) { /** @var \Bolt\Storage\Query\SelectQuery $query */ $ part = str_replace ( '_' . $ query -> getContenttype ( ) . '.' . $ field , $ field . '.' . $ column , $ part ) ; } $ reflected -> setValue ( $ originalExpression , $ originalParts ) ; if ( $ originalExpression -> getType ( ) === 'AND' && count ( $ originalParts ) > 1 ) { $ platform = $ query -> getQueryBuilder ( ) -> getConnection ( ) -> getDatabasePlatform ( ) ; $ reflected2 -> setValue ( $ originalExpression , 'OR' ) ; $ reflected -> setValue ( $ originalExpression , [ 1 ] ) ; foreach ( $ query -> getWhereParametersFor ( $ field ) as $ paramKey => $ paramValue ) { $ query -> getQueryBuilder ( ) -> andHaving ( $ platform -> getConcatExpression ( "','" , '_' . $ field . '_' . str_replace ( '_' , '' , $ column ) , "','" ) . ' LIKE(' . ':_having_' . $ paramKey . ')' ) ; $ query -> getQueryBuilder ( ) -> setParameter ( '_having_' . $ paramKey , "%,$paramValue,%" ) ; } } $ filter -> setExpression ( $ originalExpression ) ; }
This method does an in-place modification of a generic contenttype.field query to the format actually used
in the raw sql category. For instance a simple query might say `entries.tags = 'movies'` but now we are in the
context of entries the actual SQL fragment needs to be `tags.slug = 'movies'`. We don't know this until we
drill down to the individual field types so this rewrites the SQL fragment just before the query gets sent.

Note, reflection is used to achieve this, it is not ideal, but the CompositeExpression shipped with DBAL chooses
to keep the query parts as private and only allow access to the final computed string.

@param Filter         $filter
@param QueryInterface $query
@param string         $field
@param string         $column
This method does an in - place modification of a generic contenttype . field query to the format actually used in the raw sql category . For instance a simple query might say entries . tags = movies but now we are in the context of entries the actual SQL fragment needs to be tags . slug = movies . We don t know this until we drill down to the individual field types so this rewrites the SQL fragment just before the query gets sent .