Passed
Push — master ( b2bdac...3a7f22 )
by Ondřej
03:22
created

SortedRelationDefinition::__construct()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
c 0
b 0
f 0
rs 9.2
cc 4
eloc 10
nc 4
nop 3
1
<?php
2
namespace Ivory\Query;
3
4
use Ivory\Lang\Sql\ISqlSortExpression;
5
use Ivory\Lang\SqlPattern\SqlPattern;
6
use Ivory\Type\ITypeDictionary;
7
8
class SortedRelationDefinition extends RelationDefinition implements IRelationDefinition
9
{
10
    private $baseRelDef;
11
    private $sortExpr;
12
    private $args;
13
14
    /**
15
     * @param IRelationDefinition $relationDefinition definition of relation to constrain
16
     * @param ISqlSortExpression|SqlPattern|string|array $sortExpr
17
     * @param array $args
18
     */
19
    public function __construct(IRelationDefinition $relationDefinition, $sortExpr, ...$args)
20
    {
21
        if ($args) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $args of type array[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
22
            if (is_array($sortExpr)) {
23
                throw new \InvalidArgumentException('$args not supported for array of sort expressions');
24
            } elseif ($sortExpr instanceof ISqlSortExpression) {
25
                throw new \InvalidArgumentException(
26
                    '$args not supported for ' . ISqlSortExpression::class . ' sort expression'
27
                );
28
            }
29
        }
30
31
        $this->baseRelDef = $relationDefinition;
32
        $this->sortExpr = $sortExpr;
33
        $this->args = $args;
34
    }
35
36
    public function toSql(ITypeDictionary $typeDictionary): string
37
    {
38
        $relSql = $this->baseRelDef->toSql($typeDictionary);
39
40
        $sortSql = self::getSortSql($typeDictionary, $this->sortExpr, ...$this->args);
41
        if ($sortSql !== null) {
42
            return "SELECT *\nFROM (\n$relSql\n) t\nORDER BY $sortSql";
43
        } else {
44
            return $relSql;
45
        }
46
    }
47
48
    private static function getSortSql(ITypeDictionary $typeDictionary, $expr, ...$args) // PHP 7.1: declare returning ?string
49
    {
50
        if ($expr instanceof ISqlSortExpression) {
51
            $sortSql = $expr->getExpression()->getSql();
52
            switch ($expr->getDirection()) {
53
                case ISqlSortExpression::ASC:
54
                    break;
55
                case ISqlSortExpression::DESC:
56
                    $sortSql .= ' DESC';
57
                    break;
58
                default:
59
                    throw new \LogicException("Unexpected direction of sort expression: {$expr->getDirection()}");
60
            }
61
            return $sortSql;
62
        } elseif (is_array($expr)) {
63
            $sqlParts = [];
64
            foreach ($expr as $sortSpec) {
65
                if (is_array($sortSpec)) {
66
                    $sqlPart = self::getSortSql($typeDictionary, ...$sortSpec);
67
                } else {
68
                    $sqlPart = self::getSortSql($typeDictionary, $sortSpec);
69
                }
70
                if ($sqlPart !== null) {
71
                    $sqlParts[] = $sqlPart;
72
                }
73
            }
74
            return ($sqlParts ? implode(', ', $sqlParts) : null);
75
        } else {
76
            $sortDef = SqlRelationDefinition::fromPattern($expr, ...$args);
77
            return $sortDef->toSql($typeDictionary);
78
        }
79
    }
80
}
81