Completed
Push — master ( f1c7a7...774eb2 )
by Richard
07:53 queued 02:10
created

Relation::to_violation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
cc 1
eloc 6
nc 1
nop 2
crap 1
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 licence along with the code.
9
 */
10
11
namespace Lechimp\Dicto\Rules;
12
13
use Lechimp\Dicto\Definition as Def;
14
use Lechimp\Dicto\Analysis\Query;
15
use Lechimp\Dicto\Analysis\Violation;
16
use \Lechimp\Dicto\Variables\Variable;
17
18
/**
19
 * This is a rule that checks a relation between two entities
20
 * in the code.
21
 */
22
abstract class Relation extends Schema {
23
    /**
24
     * @inheritdoc
25
     */
26 150
    public function fluid_interface(Def\RuleDefinitionRT $rt, $name, $mode, array $arguments) {
27 150
        if (count($arguments) != 0) {
28
            throw new \InvalidArgumentException(
29
                "No arguments are allowed when using a relational rule schema.");
30
        }
31 150
        return new Def\Fluid\Relation($rt, $name, $mode, $this);
32
    }
33
34 191
    public function check_arguments(array $arguments) {
35 191
         if (count($arguments) != 1) {
36
            throw new \InvalidArgumentException(
37
                "One argument is required when using a relational rule schema.");
38
        }
39 191
       if (!($arguments[0] instanceof Variable)) {
40
            throw new \InvalidArgumentException(
41
                "Expected variable, got '".get_class($arguments[0])."' when using a relational schema.");
42
        }
43
44 191
    }
45
46
    /**
47
     * @inheritdoc
48
     */
49 3
    public function pprint(Rule $rule) {
50 3
        return $this->printable_name()." ".$rule->argument(0)->name();
51
    }
52
53
    /**
54
     * @inheritdoc
55
     */
56 36
    public function compile(Query $query, Rule $rule) {
57 36
        $builder = $query->builder();
58 36
        $b = $builder->expr();
59 36
        $mode = $rule->mode();
60 36
        $entity = $rule->checked_on();
61 36
        $reference = $rule->argument(0);
62 36
        if ($mode == Rule::MODE_CANNOT || $mode == Rule::MODE_ONLY_CAN) {
63
            return $builder
64 28
                ->select
65 28
                    ( "rel.entity_id as entity_id"
66 28
                    , "rel.reference_id as reference_id"
67 28
                    , "rel.file as file"
68 28
                    , "rel.line as line"
69 28
                    , "rel.source_line as source"
70 28
                    )
71 28
                ->from($query->relations_table(), "rel")
72 28
                ->innerJoin("rel", $query->entity_table(), "e", "rel.entity_id = e.id")
73 28
                ->innerJoin("rel", $query->reference_table(), "r", "rel.reference_id = r.id")
74
                ->where
75 28
                    ( $b->eq("rel.name", $b->literal($this->name()))
76 28
                    , $query->compile_var("e", $entity)
77 28
                    , $query->compile_var("r", $reference)
78 28
                    )
79 28
                ->execute();
80
        }
81 8
        if ($mode == Rule::MODE_MUST) {
82
            return $builder
83 8
                ->select
84 8
                    ( "e.id as entity_id"
85 8
                    , "e.file as file"
86 8
                    , "e.start_line as line"
87 8
                    , "e.source as source"
88 8
                    )
89 8
                ->from($query->entity_table(), "e")
90
                ->leftJoin
91 8
                    ("e", $query->relations_table(), "rel"
92 8
                    , $b->andX
93 8
                        ( $b->eq("rel.name", $b->literal($this->name()))
94 8
                        , $b->eq("rel.entity_id", "e.id")
95 8
                        )
96 8
                    )
97
                ->leftJoin
98 8
                    ("rel", $query->reference_table(), "r"
99 8
                    , $b->andX
100 8
                        ( $b->eq("rel.reference_id", "r.id")
101 8
                        , $query->compile_var("r", $reference)
102 8
                        )
103 8
                    )
104
                ->where
105 8
                    ( $query->compile_var("e", $entity)
106 8
                    , $b->isNull("r.id")
107 8
                    )
108 8
                ->execute();
109
        }
110
        throw new \LogicException("Unknown rule mode: '$mode'");
111
    }
112
113 1
    public function to_violation(Rule $rule, array $row) {
114
        return new Violation
115 1
            ( $rule
116 1
            , $row["file"]
117 1
            , (int)$row["line"]
118 1
            , $row["source"]
119 1
            );
120
    }
121
}
122