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

Rule::explain()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 9.4285
nc 1
cc 1
eloc 4
nop 1
crap 2
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\Definition;
14
use Lechimp\Dicto\Variables\Variable;
15
use Lechimp\Dicto\Variables\ButNot;
16
use Lechimp\Dicto\Variables\Everything;
17
use Lechimp\Dicto\Analysis\Query;
18
use Doctrine\DBAL\Driver\Statement;
19
20
class Rule extends Definition {
21
    const MODE_CANNOT   = "CANNOT";
22
    const MODE_MUST     = "MUST";
23
    const MODE_ONLY_CAN = "ONLY_CAN";
24
25
    static $modes = array
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $modes.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
26
        ( Rule::MODE_CANNOT
27
        , Rule::MODE_MUST
28
        , Rule::MODE_ONLY_CAN
29
        );
30
31
    /**
32
     * @var string
33
     */
34
    private $mode;
35
36
    /**
37
     * @var Vars\Variable
38
     */
39
    private $subject;
40
41
    /**
42
     * @var R\Schema
43
     */
44
    private $schema;
45
46
    /**
47
     * @var array
48
     */
49
    private $arguments;
50
51
    /**
52
     * @param string $mode
53
     */
54 241
    public function __construct($mode, Variable $subject, Schema $schema, array $arguments) {
55 241
        assert('in_array($mode, self::$modes)');
56 241
        $schema->check_arguments($arguments);
57 240
        $this->mode = $mode;
58 240
        $this->subject = $subject;
0 ignored issues
show
Documentation Bug introduced by
It seems like $subject of type object<Lechimp\Dicto\Variables\Variable> is incompatible with the declared type object<Lechimp\Dicto\Rules\Vars\Variable> of property $subject.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
59 240
        $this->schema = $schema;
0 ignored issues
show
Documentation Bug introduced by
It seems like $schema of type object<Lechimp\Dicto\Rules\Schema> is incompatible with the declared type object<Lechimp\Dicto\Rules\R\Schema> of property $schema.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
60 240
        $this->arguments = $arguments;
61 240
    }
62
63
    public function explain($explanation) {
64
        $r = new Rule($this->mode, $this->subject, $this->schema, $this->arguments);
65
        $r->setExplanation($r);
66
        return $r;
67
    }
68
69
    /**
70
     * @return string
71
     */
72 53
    public function mode() {
73 53
        return $this->mode;
74
    }
75
76
    /**
77
     * Definition of the entities this rule was defined for.
78
     *
79
     * @return  Variable
80
     */
81 56
    public function subject() {
82 56
        return $this->subject;
83
    }
84
85
    /**
86
     * Definition of the entities this rule needs to be checked on.
87
     *
88
     * In the default case the rule needs to be checked on every entity that
89
     * is not subject() if the mode is MODE_ONLY_CAN, as this really says
90
     * something about the other entities.
91
     *
92
     * @return  Variable
93
     */
94 50
    public function checked_on() {
95 50
        if ($this->mode() == self::MODE_ONLY_CAN) {
96
            return new ButNot
97 12
                ( "ONLY_CAN_INVERSION"
98 12
                , new Everything("EVERYTHING")
99 12
                , $this->subject()
100 12
                );
101
        }
102 38
        return $this->subject();
103
    }
104
105
    /**
106
     * Get all variables referenced by the rule.
107
     *
108
     * @return  Vars\Variable[]
109
     */
110 5
    public function variables() {
111 5
        $vars = array($this->subject());
112 5
        foreach ($this->arguments as $argument) {
113 5
            if ($argument instanceof Variable) {
114 3
                $vars[] = $argument;
115 3
            }
116 5
        }
117 5
        return $vars;
118
    }
119
120
    /**
121
     * Get the schema that was used for the rule.
122
     *
123
     * @return Schema
124
     */
125 3
    public function schema() {
126 3
        return $this->schema;
127
    }
128
129
    /**
130
     * Pretty print the rule.
131
     *
132
     * @return string
133
     */
134 3
    public function pprint() {
135 3
        $name = $this->subject()->name();
136 3
        switch ($this->mode()) {
137 3
            case self::MODE_CANNOT:
138 2
                return "$name cannot ".$this->schema()->pprint($this);
139 1
            case self::MODE_MUST:
140 1
                return "$name must ".$this->schema()->pprint($this);
141
            case self::MODE_ONLY_CAN:
142
                return "only $name can ".$this->schema()->pprint($this);
143
            default:
144
                throw new \Exception("Unknown rule mode '".$this->mode()."'");
145
        }
146
    }
147
148
    /**
149
     * Compile the rule to SQL.
150
     *
151
     * @param   Query       $query
152
     * @return Statement
153
     */
154 48
    public function compile(Query $query) {
155 48
        return $this->schema->compile($query, $this);
156
    }
157
158
    /**
159
     * Turn a query result into a violation.
160
     *
161
     * @param   array   $row
162
     * @param   string  $file_source
163
     * @return  Violation
164
     */
165 2
    public function to_violation(array $row, array $file_source) {
166 2
        return $this->schema->to_violation($this, $row, $file_source);
167
    }
168
169
    /**
170
     * Get the argument at the index.
171
     *
172
     * @throws  \OutOfRangeException
173
     * @param   int     $index
174
     * @return  mixed 
175
     */
176 51
    public function argument($index) {
177 51
        if ($index < 0 || $index >= count($this->arguments)) {
178
            throw new \OutOfRangeException("'$index' out of range.");
179
        }
180 51
        return $this->arguments[$index];
181
    }
182
}
183
184