GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 02ca20...d0e3db )
by Rolf
05:30 queued 03:14
created

Utils::wrapToStateMachineException()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
cc 3
eloc 6
nc 4
nop 3
crap 3
1
<?php
2
namespace izzum\statemachine\utils;
3
use izzum\command\NullCommand;
4
use izzum\command\Composite;
5
use izzum\statemachine\Exception;
6
use izzum\statemachine\Context;
7
use izzum\command\ICommand;
8
use izzum\statemachine\State;
9
use izzum\statemachine\StateMachine;
10
use izzum\statemachine\Transition;
11
12
/**
13
 * utils class that has some helper methods for diverse purposes
14
 *
15
 * @author Rolf Vreijdenberger
16
 *
17
 */
18
class Utils {
19
    const STATE_CONCATENATOR = '_to_';
20
21
22
    /**
23
     * Checks a fully loaded statemachine for a valid configuration.
24
     *
25
     * This is useful in a debug situation so you can check for the validity of
26
     * rules, commands and callables in guard logic, transition logic and state entry/exit logic
27
     * before they hit a
28
     *
29
     * This does not instantiate any objects. It just checks if callables can be found
30
     * and if classes for rules and commands can be found
31
     *
32
     * @param StateMachine $machine
33
     * @return Exception[] an array of exceptions if anything is wrong with the configuration
34
     */
35 3
    public static function checkConfiguration(StateMachine $machine)
36
    {
37
38
        //TODO: also check the rules and commands
39
40 3
        $exceptions = array();
41 3
        $output = array();
42
        //check state callables
43 3
        foreach($machine->getStates() as $state)
44
        {
45 3
            $exceptions[] = self::getExceptionForCheckingCallable($state->getExitCallable(), State::CALLABLE_ENTRY, $state);
46 3
            $exceptions[] = self::getExceptionForCheckingCallable($state->getEntryCallable(), State::CALLABLE_ENTRY, $state);
47 3
        }
48
49
        //check transition callables
50 3
        foreach($machine->getTransitions() as $transition)
51
        {
52 3
            $exceptions[] = self::getExceptionForCheckingCallable($transition->getGuardCallable(), Transition::CALLABLE_GUARD, $transition);
53 3
            $exceptions[] = self::getExceptionForCheckingCallable($transition->getTransitionCallable(), Transition::CALLABLE_TRANSITION, $transition);
54 3
        }
55
        //get the exceptions
56 3
        foreach($exceptions as $e)
57
        {
58 3
            if(is_a($e, '\Exception')){
59 1
                $output[] = $e;
60 1
            }
61 3
        }
62 3
        return $output;
63
    }
64
65
    /**
66
     * @param callable $callable
67
     * @param string $type a type description of the callable eg: State::CALLABLE_ENTRY
68
     * @param string $info extra info for exception message purposes
69
     * @param Context $context optional: the context the callable is called in
70
     * @return Exception if the callable does not pass the check
71
     */
72 3
    private static function getExceptionForCheckingCallable($callable, $type, $info, $context = null)
73
    {
74
        try {
75 3
            self::checkCallable($callable, $type, $info, $context);
76 3
        } catch(\Exception $e) {
77 1
            return $e;
78
        }
79 3
        return null;
80
    }
81
82
83
    /**
84
     * @param callable $callable
85
     * @param string $type a type description of the callable eg: State::CALLABLE_ENTRY
86
     * @param string $info extra info for exception message purposes
87
     * @param Context $context optional: the context the callable is called in
88
     * @return bool
89
     * @throws Exception if the callable does not pass the check
90
     */
91 16
    public static function checkCallable($callable, $type, $info, $context = null)
92
    {
93 16
        if($callable !== null && !is_callable($callable)) {
94 3
            throw new Exception(sprintf("not a valid '%s' callable for '%s'. %s",
95 3
                $type, $info, $context ),
96 3
                Exception::CALLABLE_FAILURE);
97
        }
98 14
        return true;
99
    }
100
    
101
    
102
    /**
103
     * gets the transition name by two state names, using the default convention
104
     * for a transition name (which is concatenating state-from to state-to with
105
     * '_to_')
106
     *
107
     * @param string $from
108
     *            the state from which the transition is made
109
     * @param string $to
110
     *            the state to which the transition will be made
111
     * @return string <state_from>_to_<state_to>
112
     */
113 68
    public static function getTransitionName($from, $to)
114
    {
115 68
        return $from . self::STATE_CONCATENATOR . $to;
116
    }
117
118
    /**
119
     * returns the associated Command for the entry/exit/transition action on a
120
     * State or a Transition.
121
     * the Command will be configured with the 'reference' of the stateful
122
     * object
123
     *
124
     * @param string $command_name
125
     *            entry~,exit~ or transition command name.
126
     *            multiple commands can be split by a ',' in which case a
127
     *            composite command will be returned.
128
     * @param Context $context
129
     *            to be able to get the entity
130
     * @return ICommand
131
     * @throws Exception
132
     */
133 41
    public static function getCommand($command_name, Context $context)
134
    {
135
        // it's oke to have no command, as there might be 'marker' states, where
136
        // we just need to transition something to a next state (according to a
137
        // rule)
138
        // where useful work can be done (eg: from the 'initial' type state to
139
        // a 'shortcut' state for special cases.
140 41
        if ($command_name === '' || $command_name === null) {
141
            // return a command without side effects
142 28
            return new NullCommand();
143
        }
144
145 26
        $output = new Composite();
146
147
        // a command string can be made up of multiple commands seperated by a
148
        // comma
149 26
        $all_commands = explode(',', $command_name);
150
151
        // get the correct object to inject in the command(s)
152 26
        $entity = $context->getEntity();
153
154 26
        foreach ($all_commands as $single_command) {
155 26
            if (!class_exists($single_command)) {
156 3
                $e = new Exception(sprintf("failed command creation, class does not exist: (%s) for Context (%s)", $single_command, $context->toString()), Exception::COMMAND_CREATION_FAILURE);
157 3
                throw $e;
158
            }
159
160
            try {
161 23
                $command = new $single_command($entity);
162 21
                $output->add($command);
163 23
            } catch(\Exception $e) {
164 2
                $e = new Exception(sprintf("command (%s) objects to construction for Context (%s). message: '%s'", $single_command, $context->toString(), $e->getMessage()), Exception::COMMAND_CREATION_FAILURE);
165 2
                throw $e;
166
            }
167 21
        }
168 21
        return $output;
169
    }
170
171
    /**
172
     * Always returns an izzum exception (converts a non-izzum exception to an
173
     * izzum exception).
174
     * optionally throws it.
175
     *
176
     * @param \Exception $e
177
     * @param int $code
178
     * @return Exception
179
     * @throws Exception
180
     */
181 4
    public static function wrapToStateMachineException(\Exception $e, $code, $throw = false)
182
    {
183 4
        if (!is_a($e, 'izzum\statemachine\Exception')) {
184
            // wrap the exception and use the code provided.
185 2
            $e = new Exception($e->getMessage(), $code, $e);
186 2
        }
187 4
        if ($throw) {
188 1
            throw $e;
189
        }
190 3
        return $e;
191
    }
192
193
    /**
194
     * get all states that match a possible regex state from the set of states
195
     * provided
196
     *
197
     * @param State $regex
198
     *            a possible regex state.
199
     * @param State[] $targets
200
     *            all target State instances that we check the regex against.
201
     * @return State[] an array of State instances from the $targets State
202
     *         instances that matched the (negated) regex, or the $regex State if it was
203
     *         not a regex State after all.
204
     * @link https://php.net/manual/en/function.preg-match.php
205
     * @link http://regexr.com/ for trying out regular expressions
206
     */
207 44
    public static function getAllRegexMatchingStates(State $regex, $targets)
208
    {
209 44
        $all = array();
210 44
        if ($regex->isRegex()) {
211
            // lookup all from states that conform to this rgex
212 19
            foreach ($targets as $target) {
213 19
                if (!$target->isRegex() && self::matchesRegex($regex, $target)) {
214 19
                    $all [] = $target;
215 19
                }
216 19
            }
217 19
        } else {
218 40
            $all [] = $regex;
219
        }
220 44
        return $all;
221
    }
222
223
    /**
224
     * does an input regex state match a target states' name?
225
     *
226
     * @param State $regex
227
     *            the regex state
228
     * @param State $target
229
     *            the state to match the regular expression to
230
     * @return boolean
231
     * @link https://php.net/manual/en/function.preg-match.php
232
     * @link http://regexr.com/ for trying out regular expressions
233
     */
234 20
    public static function matchesRegex(State $regex, State $target)
235
    {
236 20
        $matches = false;
237 20
        if ($regex->isNormalRegex()) {
238 20
            $expression = str_replace(State::REGEX_PREFIX, '', $regex->getName());
239 20
            $matches = preg_match($expression, $target->getName()) === 1;
240 20
        }
241 20
        if($regex->isNegatedRegex()) {
242 1
            $expression = str_replace(State::REGEX_PREFIX_NEGATED, '', $regex->getName());
243 1
            $matches = preg_match($expression, $target->getName()) !== 1;
244 1
        }
245 20
        return $matches;
246
    }
247
}