Completed
Push — master ( cc2765...340ff8 )
by Richard
08:19
created

Relation::check_arguments()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4.125

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
ccs 4
cts 8
cp 0.5
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
crap 4.125
1
<?php
2
/******************************************************************************
3
 * An implementation of dicto (scg.unibe.ch/dicto) in and for PHP.
4
 *
5
 * Copyright (c) 2016 Richard Klees <[email protected]>
6
 *
7
 * This software is licensed under The MIT License. You should have received
8
 * a copy of the license along with the code.
9
 */
10
11
namespace Lechimp\Dicto\Rules;
12
13
use Lechimp\Dicto\Definition as Def;
14
use Lechimp\Dicto\Indexer\Insert;
15
use Lechimp\Dicto\Indexer\Location;
16
use Lechimp\Dicto\Analysis\Query;
17
use Lechimp\Dicto\Variables\Variable;
18
19
/**
20
 * This is a rule that checks a relation between two entities
21
 * in the code.
22
 */
23
abstract class Relation extends Schema {
24
    /**
25
     * @inheritdoc
26
     */
27 6
    public function fetch_arguments(ArgumentParser $parser) {
28 6
        $var = $parser->fetch_variable();
29 6
        return array($var);
30
    }
31
32
    /**
33
     * @inheritdoc
34
     */
35 59
    public function arguments_are_valid(array &$arguments) {
36 59
         if (count($arguments) != 1) {
37
            return false;
38
        }
39 59
        if (!($arguments[0] instanceof Variable)) {
40
            return false;
41
        }
42 59
        return true;
43
    }
44
45
    /**
46
     * @inheritdoc
47
     */
48 14
    public function pprint(Rule $rule) {
49 14
        return $this->name()." ".$rule->argument(0)->name();
50
    }
51
52
    /**
53
     * @inheritdoc
54
     */
55 37
    public function compile(Query $query, Rule $rule) {
56 37
        $builder = $query->builder();
57 37
        $b = $builder->expr();
58 37
        $mode = $rule->mode();
59 37
        $entity = $rule->checked_on();
60 37
        $reference = $rule->argument(0);
61 37
        if ($mode == Rule::MODE_CANNOT || $mode == Rule::MODE_ONLY_CAN) {
62
            return $builder
0 ignored issues
show
Bug Compatibility introduced by
The expression $builder->select('rel.en...e($b, 'r'))->execute(); of type Doctrine\DBAL\Driver\Statement|integer adds the type integer to the return on line 62 which is incompatible with the return type declared by the abstract method Lechimp\Dicto\Rules\Schema::compile of type Doctrine\DBAL\Driver\Statement.
Loading history...
63 29
                ->select
64 29
                    ( "rel.entity_id as entity_id"
65 29
                    , "rel.reference_id as reference_id"
66 29
                    , "r.file as file"
67 29
                    , "r.line as line"
68 29
                    , "src.source as source"
69 29
                    )
70 29
                ->from($query->relations_table(), "rel")
71 29
                ->innerJoin("rel", $query->entity_table(), "e", "rel.entity_id = e.id")
72 29
                ->innerJoin("rel", $query->reference_table(), "r", "rel.reference_id = r.id")
73
                ->innerJoin
74 29
                    ( "rel", $query->source_file_table(), "src"
75 29
                    , $b->andX
76 29
                        ( $b->eq("src.line", "r.line")
77 29
                        , $b->eq("src.name", "r.file")
78 29
                        )
79 29
                    )
80
                ->where
81 29
                    ( $b->eq("rel.name", $b->literal($this->name()))
82 29
                    , $entity->compile($b, "e")
83 29
                    , $reference->compile($b, "r")
84 29
                    )
85 29
                ->execute();
86
        }
87 8
        if ($mode == Rule::MODE_MUST) {
88
            return $builder
0 ignored issues
show
Bug Compatibility introduced by
The expression $builder->select('e.id a...ll('r.id'))->execute(); of type Doctrine\DBAL\Driver\Statement|integer adds the type integer to the return on line 88 which is incompatible with the return type declared by the abstract method Lechimp\Dicto\Rules\Schema::compile of type Doctrine\DBAL\Driver\Statement.
Loading history...
89 8
                ->select
90 8
                    ( "e.id as entity_id"
91 8
                    , "e.file as file"
92 8
                    , "e.start_line as line"
93 8
                    , "src.source as source"
94 8
                    )
95 8
                ->from($query->entity_table(), "e")
96
                ->leftJoin
97 8
                    ("e", $query->relations_table(), "rel"
98 8
                    , $b->andX
99 8
                        ( $b->eq("rel.name", $b->literal($this->name()))
100 8
                        , $b->eq("rel.entity_id", "e.id")
101 8
                        )
102 8
                    )
103
                ->leftJoin
104 8
                    ("rel", $query->reference_table(), "r"
105 8
                    , $b->andX
106 8
                        ( $b->eq("rel.reference_id", "r.id")
107 8
                        , $reference->compile($b, "r")
108 8
                        )
109 8
                    )
110
                ->innerJoin
111 8
                    ( "e", $query->source_file_table(), "src"
112 8
                    , $b->andX
113 8
                        ( $b->eq("src.line", "e.start_line")
114 8
                        , $b->eq("src.name", "e.file")
115 8
                        )
116 8
                    )
117
118
                ->where
119 8
                    ( $entity->compile($b, "e")
120 8
                    , $b->isNull("r.id")
121 8
                    )
122 8
                ->execute();
123
        }
124
        throw new \LogicException("Unknown rule mode: '$mode'");
125
    }
126
127
    /**
128
     * Insert this relation somewhere, where it is recorded for all
129
     * entities that the current location is in, except for files.
130
     *
131
     * @param   Insert      $insert
132
     * @param   Location    $location
133
     * @param   int         $ref_id
134
     * @return  null
135
     */
136 17
    protected function insert_relation_into(Insert $insert, Location $location, $ref_id) {
137 17
        assert('is_int($ref_id)');
138 17
        foreach ($location->in_entities() as $entity) {
139 17
            if ($entity[0] == Variable::FILE_TYPE) {
140 17
                continue;
141
            }
142 17
            $insert->relation
143 17
                ( $this->name()
144 17
                , $entity[1]
145 17
                , $ref_id
146 17
                );
147 17
        }
148 17
    }
149
}
150