Base   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 287
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 287
rs 10
c 0
b 0
f 0
wmc 29
lcom 2
cbo 2

19 Methods

Rating   Name   Duplication   Size   Complexity  
A getName() 0 4 1
getDescription() 0 1 ?
doAction() 0 1 ?
getActionRequiredParameters() 0 1 ?
getEventRequiredParameters() 0 1 ?
getCompatibleEvents() 0 1 ?
hasRequiredCondition() 0 1 ?
A __toString() 0 10 2
A setProjectId() 0 6 1
A getProjectId() 0 4 1
A setParam() 0 6 1
A getParam() 0 4 2
A isExecutable() 0 7 4
A hasCompatibleEvent() 0 4 1
A hasRequiredProject() 0 5 4
B hasRequiredParameters() 0 14 6
A execute() 0 20 3
A addEvent() 0 10 2
A getEvents() 0 4 1
1
<?php
2
3
/*
4
 * This file is part of Jitamin.
5
 *
6
 * Copyright (C) Jitamin Team
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Jitamin\Action;
13
14
use Jitamin\Bus\Event\GenericEvent;
15
16
/**
17
 * Base class for automatic actions.
18
 */
19
abstract class Base extends \Jitamin\Foundation\Base
20
{
21
    /**
22
     * Extended events.
23
     *
24
     * @var array
25
     */
26
    private $compatibleEvents = [];
27
28
    /**
29
     * Flag for called listener.
30
     *
31
     * @var bool
32
     */
33
    private $called = false;
34
35
    /**
36
     * Project id.
37
     *
38
     * @var int
39
     */
40
    private $projectId = 0;
41
42
    /**
43
     * User parameters.
44
     *
45
     * @var array
46
     */
47
    private $params = [];
48
49
    /**
50
     * Get automatic action name.
51
     *
52
     * @final
53
     *
54
     * @return string
55
     */
56
    final public function getName()
57
    {
58
        return '\\'.get_called_class();
59
    }
60
61
    /**
62
     * Get automatic action description.
63
     *
64
     * @abstract
65
     *
66
     * @return string
67
     */
68
    abstract public function getDescription();
69
70
    /**
71
     * Execute the action.
72
     *
73
     * @abstract
74
     *
75
     * @param array $data Event data dictionary
76
     *
77
     * @return bool True if the action was executed or false when not executed
78
     */
79
    abstract public function doAction(array $data);
80
81
    /**
82
     * Get the required parameter for the action (defined by the user).
83
     *
84
     * @abstract
85
     *
86
     * @return array
87
     */
88
    abstract public function getActionRequiredParameters();
89
90
    /**
91
     * Get the required parameter for the event (check if for the event data).
92
     *
93
     * @abstract
94
     *
95
     * @return array
96
     */
97
    abstract public function getEventRequiredParameters();
98
99
    /**
100
     * Get the compatible events.
101
     *
102
     * @abstract
103
     *
104
     * @return array
105
     */
106
    abstract public function getCompatibleEvents();
107
108
    /**
109
     * Check if the event data meet the action condition.
110
     *
111
     * @param array $data Event data dictionary
112
     *
113
     * @return bool
114
     */
115
    abstract public function hasRequiredCondition(array $data);
116
117
    /**
118
     * Return class information.
119
     *
120
     * @return string
121
     */
122
    public function __toString()
123
    {
124
        $params = [];
125
126
        foreach ($this->params as $key => $value) {
127
            $params[] = $key.'='.var_export($value, true);
128
        }
129
130
        return $this->getName().'('.implode('|', $params).')';
131
    }
132
133
    /**
134
     * Set project id.
135
     *
136
     * @param int $project_id
137
     *
138
     * @return Base
139
     */
140
    public function setProjectId($project_id)
141
    {
142
        $this->projectId = $project_id;
143
144
        return $this;
145
    }
146
147
    /**
148
     * Get project id.
149
     *
150
     * @return int
151
     */
152
    public function getProjectId()
153
    {
154
        return $this->projectId;
155
    }
156
157
    /**
158
     * Set an user defined parameter.
159
     *
160
     * @param string $name  Parameter name
161
     * @param mixed  $value Value
162
     *
163
     * @return Base
164
     */
165
    public function setParam($name, $value)
166
    {
167
        $this->params[$name] = $value;
168
169
        return $this;
170
    }
171
172
    /**
173
     * Get an user defined parameter.
174
     *
175
     * @param string $name    Parameter name
176
     * @param mixed  $default Default value
177
     *
178
     * @return mixed
179
     */
180
    public function getParam($name, $default = null)
181
    {
182
        return isset($this->params[$name]) ? $this->params[$name] : $default;
183
    }
184
185
    /**
186
     * Check if an action is executable (right project and required parameters).
187
     *
188
     * @param array  $data
189
     * @param string $eventName
190
     *
191
     * @return bool
192
     */
193
    public function isExecutable(array $data, $eventName)
194
    {
195
        return $this->hasCompatibleEvent($eventName) &&
196
               $this->hasRequiredProject($data) &&
197
               $this->hasRequiredParameters($data) &&
198
               $this->hasRequiredCondition($data);
199
    }
200
201
    /**
202
     * Check if the event is compatible with the action.
203
     *
204
     * @param string $eventName
205
     *
206
     * @return bool
207
     */
208
    public function hasCompatibleEvent($eventName)
209
    {
210
        return in_array($eventName, $this->getEvents());
211
    }
212
213
    /**
214
     * Check if the event data has the required project.
215
     *
216
     * @param array $data Event data dictionary
217
     *
218
     * @return bool
219
     */
220
    public function hasRequiredProject(array $data)
221
    {
222
        return (isset($data['project_id']) && $data['project_id'] == $this->getProjectId()) ||
223
            (isset($data['task']['project_id']) && $data['task']['project_id'] == $this->getProjectId());
224
    }
225
226
    /**
227
     * Check if the event data has required parameters to execute the action.
228
     *
229
     * @param array $data Event data dictionary
230
     *
231
     * @return bool True if all keys are there
232
     */
233
    public function hasRequiredParameters(array $data, array $parameters = [])
234
    {
235
        $parameters = $parameters ?: $this->getEventRequiredParameters();
236
237
        foreach ($parameters as $key => $value) {
238
            if (is_array($value)) {
239
                return isset($data[$key]) && $this->hasRequiredParameters($data[$key], $value);
240
            } elseif (!isset($data[$value])) {
241
                return false;
242
            }
243
        }
244
245
        return true;
246
    }
247
248
    /**
249
     * Execute the action.
250
     *
251
     * @param \Jitamin\Event\GenericEvent $event
252
     * @param string                      $eventName
253
     *
254
     * @return bool
255
     */
256
    public function execute(GenericEvent $event, $eventName)
257
    {
258
        // Avoid infinite loop, a listener instance can be called only one time
259
        if ($this->called) {
260
            return false;
261
        }
262
263
        $data = $event->getAll();
264
        $executable = $this->isExecutable($data, $eventName);
265
        $executed = false;
266
267
        if ($executable) {
268
            $this->called = true;
269
            $executed = $this->doAction($data);
270
        }
271
272
        $this->logger->debug($this.' ['.$eventName.'] => executable='.var_export($executable, true).' exec_success='.var_export($executed, true));
0 ignored issues
show
Documentation introduced by
The property logger does not exist on object<Jitamin\Action\Base>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
273
274
        return $executed;
275
    }
276
277
    /**
278
     * Register a new event for the automatic action.
279
     *
280
     * @param string $event
281
     * @param string $description
282
     *
283
     * @return Base
284
     */
285
    public function addEvent($event, $description = '')
286
    {
287
        if ($description !== '') {
288
            $this->eventManager->register($event, $description);
0 ignored issues
show
Documentation introduced by
The property eventManager does not exist on object<Jitamin\Action\Base>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
289
        }
290
291
        $this->compatibleEvents[] = $event;
292
293
        return $this;
294
    }
295
296
    /**
297
     * Get all compatible events of an automatic action.
298
     *
299
     * @return array
300
     */
301
    public function getEvents()
302
    {
303
        return array_unique(array_merge($this->getCompatibleEvents(), $this->compatibleEvents));
304
    }
305
}
306