protected function getNestedWhereConditions($builder, array $criteria)
    {
        $subQuery = $builder->forNestedWhere();
        foreach ($criteria as $key => $criterionData) {
            switch (true) {
                case $criterionData instanceof Criterion:
                    $criterion = $criterionData;
                    break;
                case is_string($key)
                    && ((!is_array($criterionData) && !is_object($criterionData))
                        || $criterionData instanceof Carbon):
                    $criterion = new Criterion([Criterion::ATTRIBUTE => $key, Criterion::VALUE => $criterionData]);
                    break;
                case is_int($key) && is_array($criterionData) && $this->isNestedCriteria($criterionData):
                    $boolean = 'and';
                    if (isset($criterionData[Criterion::BOOLEAN])) {
                        $boolean = $criterionData[Criterion::BOOLEAN];
                        unset($criterionData[Criterion::BOOLEAN]);
                    }
                    $subQuery->addNestedWhereQuery(
                        $this->getNestedWhereConditions($subQuery, $criterionData),
                        $boolean
                    );
                    continue 2;
                default:
                    $criterion = $this->parseCriterion($criterionData);
            }

            if (!$this->isCriterionValid($criterion)) {
                throw new BadCriteriaException($this);
            }

            switch ($criterion->operator) {
                case 'in':
                    $subQuery->whereIn($criterion->attribute, $criterion->value, $criterion->boolean);
                    break;
                case 'not in':
                    $subQuery->whereNotIn($criterion->attribute, $criterion->value, $criterion->boolean);
                    break;
                default:
                    $subQuery->where(
                        $criterion->attribute,
                        $criterion->operator,
                        $criterion->value,
                        $criterion->boolean
                    );
                    break;
            }
        }

        return $subQuery;
    }