This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the SlotMachine library. |
||
5 | * |
||
6 | * (c) Adam Elsodaney <[email protected]> |
||
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 SlotMachine; |
||
13 | |||
14 | use Symfony\Component\HttpFoundation\Request; |
||
15 | |||
16 | /** |
||
17 | * SlotMachine is a content container for dynamic pages written for PHP 5.3 and |
||
18 | * above. Each component on a page that can change its value is called a slot, |
||
19 | * and works is much the same way a slot machine does, except that the slot's |
||
20 | * cards are not randomly displayed, (but it can be if you wanted it to). |
||
21 | * |
||
22 | * Please visit the official git repository for any issues you may have. |
||
23 | * |
||
24 | * @link https://github.com/archfizz/slotmachine |
||
25 | * |
||
26 | * @author Adam Elsodaney <[email protected]> |
||
27 | */ |
||
28 | class SlotMachine extends \Pimple implements \Countable |
||
29 | { |
||
30 | const VERSION = '2.0.0'; |
||
31 | const MAJOR_VERSION = 2; |
||
32 | const MINOR_VERSION = 0; |
||
33 | const PATCH_VERSION = 0; |
||
34 | |||
35 | /** |
||
36 | * @var array |
||
37 | */ |
||
38 | protected $config; |
||
39 | |||
40 | /** |
||
41 | * @var array |
||
42 | */ |
||
43 | protected $reels; |
||
44 | |||
45 | /** |
||
46 | * @var Request |
||
47 | */ |
||
48 | protected $request; |
||
49 | |||
50 | /** |
||
51 | * @var array |
||
52 | */ |
||
53 | protected $delimiter = array('{', '}'); |
||
54 | |||
55 | /** |
||
56 | * @var integer |
||
57 | */ |
||
58 | protected $undefinedCardResolution = UndefinedCardResolution::DEFAULT_CARD; |
||
59 | |||
60 | const NOT_SET_PARAMETER = "not_set"; |
||
61 | |||
62 | /** |
||
63 | * @param array $config The SlotMachine configuration data |
||
64 | * @param Request|null $request The Request object |
||
65 | */ |
||
66 | public function __construct(array $config = array(), Request $request = null) |
||
67 | { |
||
68 | parent::__construct(); |
||
69 | |||
70 | $this->config = $config; |
||
71 | $this->request = !is_null($request) ? $request : Request::createFromGlobals(); |
||
72 | |||
73 | $this->initialize(); |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * Set up the SlotMachine in a ready to use state |
||
78 | */ |
||
79 | private function initialize() |
||
80 | { |
||
81 | $this->undefinedCardResolution = isset($this->config['options']['undefined_card']) |
||
82 | ? static::translateUndefinedCardResolution($this->config['options']['undefined_card']) |
||
83 | : UndefinedCardResolution::DEFAULT_CARD; |
||
84 | |||
85 | if (isset($this->config['options']['delimiter'])) { |
||
86 | $this->delimiter = $this->config['options']['delimiter']; |
||
87 | } |
||
88 | |||
89 | foreach ($this->config['slots'] as $slotName => &$slotData) { |
||
90 | $slotData['name'] = $slotName; |
||
91 | |||
92 | if (is_string($slotData['reel'])) { |
||
93 | $slotData['reel'] = $this->config['reels'][$slotData['reel']]; |
||
94 | } |
||
95 | |||
96 | if (!isset($slotData['nested'])) { |
||
97 | $slotData['nested'] = array(); |
||
98 | } |
||
99 | |||
100 | $slotData['undefined_card'] = (!isset($slotData['undefined_card'])) |
||
101 | ? $this->undefinedCardResolution |
||
102 | : static::translateUndefinedCardResolution($slotData['undefined_card']); |
||
103 | |||
104 | $this->offsetSet($slotName, function () use ($slotData) { |
||
105 | return new Slot($slotData); |
||
106 | }); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * @param string $option The name of the constant |
||
112 | * |
||
113 | * @return integer |
||
114 | * |
||
115 | * @throws \InvalidArgumentException |
||
116 | */ |
||
117 | public static function translateUndefinedCardResolution($option) |
||
118 | { |
||
119 | if (defined($setting = '\\SlotMachine\\UndefinedCardResolution::' . $option)) { |
||
120 | return constant($setting); |
||
121 | } |
||
122 | |||
123 | throw new \InvalidArgumentException($setting . ' is not a valid option'); |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Interpolates cards values into the cards nested slot placeholders. |
||
128 | * Based on the example given in the PSR-3 specification. |
||
129 | * |
||
130 | * @link https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md PSR-3 specification |
||
131 | * @param string $card |
||
132 | * @param array $nestedCards |
||
133 | * @param array $delimiter |
||
134 | * @throws \LengthException if less than two delimiter tokens are giving. |
||
135 | * @return string |
||
136 | */ |
||
137 | public static function interpolate($card, array $nestedCards = array(), array $delimiter = array('{', '}')) |
||
138 | { |
||
139 | if (2 > $tokens = count($delimiter)) { |
||
140 | throw new \LengthException('Number of delimiter tokens too short. Method requires exactly 2.'); |
||
141 | } |
||
142 | |||
143 | // SlotMachine can still function with more than two delimiter tokens, |
||
144 | // but will generate a warning. |
||
145 | if ($tokens > 2) { |
||
146 | trigger_error('Too many delimiter tokens given', E_USER_WARNING); |
||
147 | } |
||
148 | |||
149 | // build a replacement array with braces around the context keys |
||
150 | $replace = array(); |
||
151 | foreach ($nestedCards as $slot => $nestedCard) { |
||
152 | $replace[$delimiter[0] . $slot . $delimiter[1]] = $nestedCard; |
||
153 | } |
||
154 | |||
155 | // interpolate replacement values into the message and return |
||
156 | return strtr($card, $replace); |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * @param string $slot |
||
161 | * @param integer $default |
||
162 | * @return string |
||
163 | */ |
||
164 | public function get($slot, $default = null) |
||
165 | { |
||
166 | // Resolve default index. The one passed to the second augument will |
||
167 | // take presidence, followed by the slot's default index. |
||
168 | |||
169 | // Check if the slot's default value has been set and the method's |
||
170 | // default value is empty |
||
171 | if (!is_null($slotDefault = $this->offsetGet($slot)->getDefaultIndex()) && is_null($default)) { |
||
172 | $default = $slotDefault; |
||
173 | } |
||
174 | |||
175 | // If default has not be set in the slot or the method, use 0. |
||
176 | if (is_null($default)) { |
||
177 | $default = 0; |
||
178 | } |
||
179 | |||
180 | // If no nested slots, return the card as is. |
||
181 | if (0 === count($nested = $this->offsetGet($slot)->getNested())) { |
||
182 | return $this->offsetGet($slot)->getCard($this->resolveIndex($slot, $default)); |
||
183 | } |
||
184 | |||
185 | // Resolve Nested Slots |
||
186 | $nestedCards = array(); |
||
187 | |||
188 | // Get the cards of the nested slots |
||
189 | foreach ($nested as $nestedSlot) { |
||
190 | $nestedCards[$nestedSlot] = $this->offsetGet($nestedSlot)->getCard( |
||
191 | $this->resolveIndex($nestedSlot, $this->offsetGet($nestedSlot)->getDefaultIndex()) |
||
192 | ); |
||
193 | } |
||
194 | |||
195 | // Translate the placeholders in the parent card. |
||
196 | return static::interpolate( |
||
197 | $this->offsetGet($slot)->getCard($this->resolveIndex($slot, $default)), |
||
198 | $nestedCards, |
||
199 | $this->delimiter |
||
200 | ); |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * @param string $slot |
||
205 | * @param integer $default |
||
206 | * @return integer |
||
207 | */ |
||
208 | protected function resolveIndex($slot, $default = 0) |
||
209 | { |
||
210 | $keyWithSetValue = false; |
||
211 | $slotKeys = $this->offsetGet($slot)->getKeys(); |
||
212 | |||
213 | // Perform a dry-run to find out if a value has been set, if it hasn't |
||
214 | // then assign a string. The `has()` method for the Request's `query` |
||
215 | // property won't work recursively for array parameters. |
||
216 | foreach ($slotKeys as $key) { |
||
217 | $dry = $this->request->query->get($key, static::NOT_SET_PARAMETER, true); |
||
0 ignored issues
–
show
|
|||
218 | if (static::NOT_SET_PARAMETER !== $dry) { |
||
219 | $keyWithSetValue = $key; |
||
220 | break; |
||
221 | } |
||
222 | } |
||
223 | |||
224 | // If a key was not set a value, return the default value of the first key assigned to the slot. |
||
225 | return $this->request->query->getInt(($keyWithSetValue ?: $slotKeys[0]), $default, true); |
||
0 ignored issues
–
show
The call to
ParameterBag::getInt() has too many arguments starting with true .
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the ![]() |
|||
226 | } |
||
227 | |||
228 | /** |
||
229 | * @param Request $request |
||
230 | */ |
||
231 | public function setRequest(Request $request) |
||
0 ignored issues
–
show
You have injected the Request via parameter
$request . This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest() .
![]() |
|||
232 | { |
||
233 | $this->request = $request; |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * @return Request |
||
238 | */ |
||
239 | public function getRequest() |
||
240 | { |
||
241 | return $this->request; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * @return array |
||
246 | */ |
||
247 | public function getConfig() |
||
248 | { |
||
249 | return $this->config; |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * The number of Slots in the machine |
||
254 | * |
||
255 | * @return integer |
||
256 | */ |
||
257 | public function count() |
||
258 | { |
||
259 | $c = 0; |
||
260 | // Using Pimple::$values will return the Closures, so instead get the |
||
261 | // values in the container via ArrayAccess. |
||
262 | foreach ($this->keys() as $valueName) { |
||
263 | if ($this[$valueName] instanceof Slot) { |
||
264 | ++$c; |
||
265 | } |
||
266 | } |
||
267 | return $c; |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Return all the slots. |
||
272 | * |
||
273 | * @return array |
||
274 | */ |
||
275 | public function all() |
||
276 | { |
||
277 | $all = array(); |
||
278 | |||
279 | // Pimple::keys() |
||
280 | foreach ($this->keys() as $slotName) { |
||
281 | $all[$slotName] = $this->get($slotName); |
||
282 | } |
||
283 | |||
284 | return $all; |
||
285 | } |
||
286 | |||
287 | /** |
||
288 | * Export current values for all slots in JSON format. |
||
289 | * |
||
290 | * @return string |
||
291 | */ |
||
292 | public function toJson() |
||
293 | { |
||
294 | return json_encode($this->all()); |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * Export to JSON by treating the object as a string. |
||
299 | * |
||
300 | * @return string |
||
301 | */ |
||
302 | public function __toString() |
||
303 | { |
||
304 | return $this->toJson(); |
||
305 | } |
||
306 | } |
||
307 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.