eZ\Publish\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\MapLocationDistance::handle PHP Method

handle() public method

accept() must be called before calling this method.
public handle ( CriteriaConverter $converter, eZ\Publish\Core\Persistence\Database\SelectQuery $query, eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion, array $languageSettings ) : eZ\Publish\Core\Persistence\Database\Expression
$converter eZ\Publish\Core\Search\Legacy\Content\Common\Gateway\CriteriaConverter
$query eZ\Publish\Core\Persistence\Database\SelectQuery
$criterion eZ\Publish\API\Repository\Values\Content\Query\Criterion
$languageSettings array
return eZ\Publish\Core\Persistence\Database\Expression
    public function handle(CriteriaConverter $converter, SelectQuery $query, Criterion $criterion, array $languageSettings)
    {
        $fieldDefinitionIds = $this->getFieldDefinitionIds($criterion->target);
        $subSelect = $query->subSelect();
        /** @var \eZ\Publish\API\Repository\Values\Content\Query\Criterion\Value\MapLocationValue $location */
        $location = $criterion->valueData;
        /*
         * Note: this formula is precise only for short distances.
         * @todo if ABS function was available in Zeta Database component it should be possible to account for
         * distances across the date line. Revisit when Doctrine DBAL is introduced.
         */
        $longitudeCorrectionByLatitude = pow(cos(deg2rad($location->latitude)), 2);
        $distanceExpression = $subSelect->expr->add($subSelect->expr->mul($subSelect->expr->sub($this->dbHandler->quoteColumn('latitude', 'ezgmaplocation'), $subSelect->bindValue($location->latitude)), $subSelect->expr->sub($this->dbHandler->quoteColumn('latitude', 'ezgmaplocation'), $subSelect->bindValue($location->latitude))), $subSelect->expr->mul($subSelect->expr->sub($this->dbHandler->quoteColumn('longitude', 'ezgmaplocation'), $subSelect->bindValue($location->longitude)), $subSelect->expr->sub($this->dbHandler->quoteColumn('longitude', 'ezgmaplocation'), $subSelect->bindValue($location->longitude)), $subSelect->bindValue($longitudeCorrectionByLatitude)));
        switch ($criterion->operator) {
            case Criterion\Operator::IN:
            case Criterion\Operator::EQ:
            case Criterion\Operator::GT:
            case Criterion\Operator::GTE:
            case Criterion\Operator::LT:
            case Criterion\Operator::LTE:
                $operatorFunction = $this->comparatorMap[$criterion->operator];
                $distanceInDegrees = pow($this->kilometersToDegrees($criterion->value), 2);
                $distanceFilter = $subSelect->expr->{$operatorFunction}($distanceExpression, $subSelect->expr->round($subSelect->bindValue($distanceInDegrees), 10));
                break;
            case Criterion\Operator::BETWEEN:
                $distanceInDegrees1 = pow($this->kilometersToDegrees($criterion->value[0]), 2);
                $distanceInDegrees2 = pow($this->kilometersToDegrees($criterion->value[1]), 2);
                $distanceFilter = $subSelect->expr->between($distanceExpression, $subSelect->expr->round($subSelect->bindValue($distanceInDegrees1), 10), $subSelect->expr->round($subSelect->bindValue($distanceInDegrees2), 10));
                break;
            default:
                throw new RuntimeException('Unknown operator.');
        }
        // Calculate bounding box if possible
        // @todo consider covering operators EQ and IN as well
        $boundingConstraints = array();
        switch ($criterion->operator) {
            case Criterion\Operator::LT:
            case Criterion\Operator::LTE:
                $distanceUpper = $criterion->value;
                break;
            case Criterion\Operator::BETWEEN:
                $distanceUpper = $criterion->value[0] > $criterion->value[1] ? $criterion->value[0] : $criterion->value[1];
                break;
        }
        if (isset($distanceUpper)) {
            $boundingConstraints = $this->getBoundingConstraints($subSelect, $location, $distanceUpper);
        }
        $subSelect->select($this->dbHandler->quoteColumn('contentobject_id'))->from($this->dbHandler->quoteTable('ezcontentobject_attribute'))->innerJoin($this->dbHandler->quoteTable('ezgmaplocation'), $subSelect->expr->lAnd(array($subSelect->expr->eq($this->dbHandler->quoteColumn('contentobject_version', 'ezgmaplocation'), $this->dbHandler->quoteColumn('version', 'ezcontentobject_attribute')), $subSelect->expr->eq($this->dbHandler->quoteColumn('contentobject_attribute_id', 'ezgmaplocation'), $this->dbHandler->quoteColumn('id', 'ezcontentobject_attribute'))), $boundingConstraints))->where($subSelect->expr->lAnd($subSelect->expr->eq($this->dbHandler->quoteColumn('version', 'ezcontentobject_attribute'), $this->dbHandler->quoteColumn('current_version', 'ezcontentobject')), $subSelect->expr->in($this->dbHandler->quoteColumn('contentclassattribute_id', 'ezcontentobject_attribute'), $fieldDefinitionIds), $distanceFilter, $this->getFieldCondition($subSelect, $languageSettings)));
        return $query->expr->in($this->dbHandler->quoteColumn('id', 'ezcontentobject'), $subSelect);
    }