Issues (46)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

library/Mockery/Generator/MockConfiguration.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Mockery
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.txt.
9
 * It is also available through the world-wide-web at this URL:
10
 * http://github.com/padraic/mockery/blob/master/LICENSE
11
 * If you did not receive a copy of the license and are unable to
12
 * obtain it through the world-wide-web, please send an email
13
 * to [email protected] so we can send you a copy immediately.
14
 *
15
 * @category   Mockery
16
 * @package    Mockery
17
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
18
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
19
 */
20
21
namespace Mockery\Generator;
22
23
/**
24
 * This class describes the configuration of mocks and hides away some of the
25
 * reflection implementation
26
 */
27
class MockConfiguration
28
{
29
    protected static $mockCounter = 0;
30
31
    /**
32
     * A class that we'd like to mock
33
     */
34
    protected $targetClass;
35
    protected $targetClassName;
36
37
    /**
38
     * A number of interfaces we'd like to mock, keyed by name to attempt to
39
     * keep unique
40
     */
41
    protected $targetInterfaces = array();
42
    protected $targetInterfaceNames = array();
43
44
    /**
45
     * A number of traits we'd like to mock, keyed by name to attempt to
46
     * keep unique
47
     */
48
    protected $targetTraits = array();
49
    protected $targetTraitNames = array();
50
51
    /**
52
     * An object we'd like our mock to proxy to
53
     */
54
    protected $targetObject;
55
56
    /**
57
     * The class name we'd like to use for a generated mock
58
     */
59
    protected $name;
60
61
    /**
62
     * Methods that should specifically not be mocked
63
     *
64
     * This is currently populated with stuff we don't know how to deal with,
65
     * should really be somewhere else
66
     */
67
    protected $blackListedMethods = array();
68
69
    /**
70
     * If not empty, only these methods will be mocked
71
     */
72
    protected $whiteListedMethods = array();
73
74
    /**
75
     * An instance mock is where we override the original class before it's
76
     * autoloaded
77
     */
78
    protected $instanceMock = false;
79
80
    /**
81
     * Param overrides
82
     */
83
    protected $parameterOverrides = array();
84
85
    /**
86
     * Instance cache of all methods
87
     */
88
    protected $allMethods;
89
90
    /**
91
     * If true, overrides original class destructor
92
     */
93
    protected $mockOriginalDestructor = false;
94
95 444
    public function __construct(
96
        array $targets = array(),
97
        array $blackListedMethods = array(),
98
        array $whiteListedMethods = array(),
99
        $name = null,
100
        $instanceMock = false,
101
        array $parameterOverrides = array(),
102
        $mockOriginalDestructor = false
103
    ) {
104 444
        $this->addTargets($targets);
105 444
        $this->blackListedMethods = $blackListedMethods;
106 444
        $this->whiteListedMethods = $whiteListedMethods;
107 444
        $this->name = $name;
108 444
        $this->instanceMock = $instanceMock;
109 444
        $this->parameterOverrides = $parameterOverrides;
110 444
        $this->mockOriginalDestructor = $mockOriginalDestructor;
111 444
    }
112
113
    /**
114
     * Attempt to create a hash of the configuration, in order to allow caching
115
     *
116
     * @TODO workout if this will work
117
     *
118
     * @return string
119
     */
120 424
    public function getHash()
121
    {
122
        $vars = array(
123 424
            'targetClassName'        => $this->targetClassName,
124 424
            'targetInterfaceNames'   => $this->targetInterfaceNames,
125 424
            'targetTraitNames'       => $this->targetTraitNames,
126 424
            'name'                   => $this->name,
127 424
            'blackListedMethods'     => $this->blackListedMethods,
128 424
            'whiteListedMethod'      => $this->whiteListedMethods,
129 424
            'instanceMock'           => $this->instanceMock,
130 424
            'parameterOverrides'     => $this->parameterOverrides,
131 424
            'mockOriginalDestructor' => $this->mockOriginalDestructor
132 424
        );
133
134 424
        return md5(serialize($vars));
135
    }
136
137
    /**
138
     * Gets a list of methods from the classes, interfaces and objects and
139
     * filters them appropriately. Lot's of filtering going on, perhaps we could
140
     * have filter classes to iterate through
141
     */
142 405
    public function getMethodsToMock()
143
    {
144 405
        $methods = $this->getAllMethods();
145
146 405
        foreach ($methods as $key => $method) {
147 131
            if ($method->isFinal()) {
148 12
                unset($methods[$key]);
149 12
            }
150 405
        }
151
152
        /**
153
         * Whitelist trumps everything else
154
         */
155 405
        if (count($this->getWhiteListedMethods())) {
156 19
            $whitelist = array_map('strtolower', $this->getWhiteListedMethods());
157
            $methods = array_filter($methods, function ($method) use ($whitelist) {
158 19
                return $method->isAbstract() || in_array(strtolower($method->getName()), $whitelist);
159 19
            });
160
161 19
            return $methods;
162
        }
163
164
        /**
165
         * Remove blacklisted methods
166
         */
167 387
        if (count($this->getBlackListedMethods())) {
168 385
            $blacklist = array_map('strtolower', $this->getBlackListedMethods());
169
            $methods = array_filter($methods, function ($method) use ($blacklist) {
170 110
                return !in_array(strtolower($method->getName()), $blacklist);
171 385
            });
172 385
        }
173
174
        /**
175
         * Internal objects can not be instantiated with newInstanceArgs and if
176
         * they implement Serializable, unserialize will have to be called. As
177
         * such, we can't mock it and will need a pass to add a dummy
178
         * implementation
179
         */
180 387
        if ($this->getTargetClass()
181 387
            && $this->getTargetClass()->implementsInterface("Serializable")
182 387
            && $this->getTargetClass()->hasInternalAncestor()) {
183
            $methods = array_filter($methods, function ($method) {
184 1
                return $method->getName() !== "unserialize";
185 1
            });
186 1
        }
187
188 387
        return array_values($methods);
189
    }
190
191
    /**
192
     * We declare the __call method to handle undefined stuff, if the class
193
     * we're mocking has also defined it, we need to comply with their interface
194
     */
195 398
    public function requiresCallTypeHintRemoval()
196
    {
197 398
        foreach ($this->getAllMethods() as $method) {
198 123
            if ("__call" === $method->getName()) {
199 6
                $params = $method->getParameters();
200 6
                return !$params[1]->isArray();
201
            }
202 392
        }
203
204 392
        return false;
205
    }
206
207
    /**
208
     * We declare the __callStatic method to handle undefined stuff, if the class
209
     * we're mocking has also defined it, we need to comply with their interface
210
     */
211 397
    public function requiresCallStaticTypeHintRemoval()
212
    {
213 397
        foreach ($this->getAllMethods() as $method) {
214 123
            if ("__callStatic" === $method->getName()) {
215 1
                $params = $method->getParameters();
216 1
                return !$params[1]->isArray();
217
            }
218 396
        }
219
220 396
        return false;
221
    }
222
223 397
    public function rename($className)
224
    {
225 397
        $targets = array();
226
227 397
        if ($this->targetClassName) {
228 373
            $targets[] = $this->targetClassName;
229 373
        }
230
231 397
        if ($this->targetInterfaceNames) {
232 19
            $targets = array_merge($targets, $this->targetInterfaceNames);
233 19
        }
234
235 397
        if ($this->targetTraitNames) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->targetTraitNames of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
236 3
            $targets = array_merge($targets, $this->targetTraitNames);
237 3
        }
238
239 397
        if ($this->targetObject) {
240 14
            $targets[] = $this->targetObject;
241 14
        }
242
243 397
        return new self(
244 397
            $targets,
245 397
            $this->blackListedMethods,
246 397
            $this->whiteListedMethods,
247 397
            $className,
248 397
            $this->instanceMock,
249 397
            $this->parameterOverrides,
250 397
            $this->mockOriginalDestructor
251 397
        );
252
    }
253
254 411
    protected function addTarget($target)
255
    {
256 411
        if (is_object($target)) {
257 14
            $this->setTargetObject($target);
258 14
            $this->setTargetClassName(get_class($target));
259 14
            return $this;
260
        }
261
262 411
        if ($target[0] !== "\\") {
263 408
            $target = "\\" . $target;
264 408
        }
265
266 411
        if (class_exists($target)) {
267 382
            $this->setTargetClassName($target);
268 382
            return $this;
269
        }
270
271 43
        if (interface_exists($target)) {
272 24
            $this->addTargetInterfaceName($target);
273 24
            return $this;
274
        }
275
276 20
        if (trait_exists($target)) {
277 3
            $this->addTargetTraitName($target);
278 3
            return $this;
279
        }
280
281
        /**
282
         * Default is to set as class, or interface if class already set
283
         *
284
         * Don't like this condition, can't remember what the default
285
         * targetClass is for
286
         */
287 17
        if ($this->getTargetClassName()) {
288 1
            $this->addTargetInterfaceName($target);
289 1
            return $this;
290
        }
291
292 17
        $this->setTargetClassName($target);
293 17
    }
294
295 444
    protected function addTargets($interfaces)
296
    {
297 444
        foreach ($interfaces as $interface) {
298 411
            $this->addTarget($interface);
299 444
        }
300 444
    }
301
302 17
    public function getTargetClassName()
303
    {
304 17
        return $this->targetClassName;
305
    }
306
307 408
    public function getTargetClass()
308
    {
309 408
        if ($this->targetClass) {
310 380
            return $this->targetClass;
311
        }
312
313 408
        if (!$this->targetClassName) {
314 31
            return null;
315
        }
316
317 382
        if (class_exists($this->targetClassName)) {
318 369
            $dtc = DefinedTargetClass::factory($this->targetClassName);
319
320 369
            if ($this->getTargetObject() == false && $dtc->isFinal()) {
321 2
                throw new \Mockery\Exception(
322 2
                    'The class ' . $this->targetClassName . ' is marked final and its methods'
323 2
                    . ' cannot be replaced. Classes marked final can be passed in'
324 2
                    . ' to \Mockery::mock() as instantiated objects to create a'
325 2
                    . ' partial mock, but only if the mock is not subject to type'
326 2
                    . ' hinting checks.'
327 2
                );
328
            }
329
330 367
            $this->targetClass = $dtc;
331 367
        } else {
332 17
            $this->targetClass = UndefinedTargetClass::factory($this->targetClassName);
333
        }
334
335 380
        return $this->targetClass;
336
    }
337
338 406
    public function getTargetTraits()
339
    {
340 406
        if (!empty($this->targetTraits)) {
341 3
            return $this->targetTraits;
342
        }
343
344 406
        foreach ($this->targetTraitNames as $targetTrait) {
345 3
            $this->targetTraits[] = DefinedTargetClass::factory($targetTrait);
346 406
        }
347
348 406
        $this->targetTraits = array_unique($this->targetTraits); // just in case
349 406
        return $this->targetTraits;
350
    }
351
352 410
    public function getTargetInterfaces()
353
    {
354 410
        if (!empty($this->targetInterfaces)) {
355 19
            return $this->targetInterfaces;
356
        }
357
358 410
        foreach ($this->targetInterfaceNames as $targetInterface) {
359 24
            if (!interface_exists($targetInterface)) {
360 1
                $this->targetInterfaces[] = UndefinedTargetClass::factory($targetInterface);
361 1
                return;
362
            }
363
364 24
            $dtc = DefinedTargetClass::factory($targetInterface);
365 24
            $extendedInterfaces = array_keys($dtc->getInterfaces());
366 24
            $extendedInterfaces[] = $targetInterface;
367
368 24
            $traversableFound = false;
369 24
            $iteratorShiftedToFront = false;
370 24
            foreach ($extendedInterfaces as $interface) {
371 24
                if (!$traversableFound && preg_match("/^\\?Iterator(|Aggregate)$/i", $interface)) {
372
                    break;
373
                }
374
375 24
                if (preg_match("/^\\\\?IteratorAggregate$/i", $interface)) {
376 3
                    $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
377 3
                    $iteratorShiftedToFront = true;
378 24
                } elseif (preg_match("/^\\\\?Iterator$/i", $interface)) {
379 3
                    $this->targetInterfaces[] = DefinedTargetClass::factory("\\Iterator");
380 3
                    $iteratorShiftedToFront = true;
381 24
                } elseif (preg_match("/^\\\\?Traversable$/i", $interface)) {
382 11
                    $traversableFound = true;
383 11
                }
384 24
            }
385
386 24
            if ($traversableFound && !$iteratorShiftedToFront) {
387 5
                $this->targetInterfaces[] = DefinedTargetClass::factory("\\IteratorAggregate");
388 5
            }
389
390
            /**
391
             * We never straight up implement Traversable
392
             */
393 24
            if (!preg_match("/^\\\\?Traversable$/i", $targetInterface)) {
394 23
                $this->targetInterfaces[] = $dtc;
395 23
            }
396 410
        }
397 409
        $this->targetInterfaces = array_unique($this->targetInterfaces); // just in case
398 409
        return $this->targetInterfaces;
399
    }
400
401 431
    public function getTargetObject()
402
    {
403 431
        return $this->targetObject;
404
    }
405
406 430
    public function getName()
407
    {
408 430
        return $this->name;
409
    }
410
411
    /**
412
     * Generate a suitable name based on the config
413
     */
414 377
    public function generateName()
415
    {
416 377
        $name = 'Mockery_' . static::$mockCounter++;
417
418 377
        if ($this->getTargetObject()) {
419 14
            $name .= "_" . str_replace("\\", "_", get_class($this->getTargetObject()));
420 14
        }
421
422 377
        if ($this->getTargetClass()) {
423 356
            $name .= "_" . str_replace("\\", "_", $this->getTargetClass()->getName());
424 356
        }
425
426 376
        if ($this->getTargetInterfaces()) {
427
            $name .= array_reduce($this->getTargetInterfaces(), function ($tmpname, $i) {
428 18
                $tmpname .= '_' . str_replace("\\", "_", $i->getName());
429 18
                return $tmpname;
430 18
            }, '');
431 18
        }
432
433 376
        return $name;
434
    }
435
436 401
    public function getShortName()
437
    {
438 401
        $parts = explode("\\", $this->getName());
439 401
        return array_pop($parts);
440
    }
441
442 401
    public function getNamespaceName()
443
    {
444 401
        $parts = explode("\\", $this->getName());
445 401
        array_pop($parts);
446
447 401
        if (count($parts)) {
448 22
            return implode("\\", $parts);
449
        }
450
451 379
        return "";
452
    }
453
454 387
    public function getBlackListedMethods()
455
    {
456 387
        return $this->blackListedMethods;
457
    }
458
459 405
    public function getWhiteListedMethods()
460
    {
461 405
        return $this->whiteListedMethods;
462
    }
463
464 398
    public function isInstanceMock()
465
    {
466 398
        return $this->instanceMock;
467
    }
468
469 109
    public function getParameterOverrides()
470
    {
471 109
        return $this->parameterOverrides;
472
    }
473
474 373
    public function isMockOriginalDestructor()
475
    {
476 373
        return $this->mockOriginalDestructor;
477
    }
478
479 392
    protected function setTargetClassName($targetClassName)
480
    {
481 392
        $this->targetClassName = $targetClassName;
482 392
    }
483
484 406
    protected function getAllMethods()
485
    {
486 406
        if ($this->allMethods) {
487 123
            return $this->allMethods;
488
        }
489
490 406
        $classes = $this->getTargetInterfaces();
491
492 406
        if ($this->getTargetClass()) {
493 380
            $classes[] = $this->getTargetClass();
494 380
        }
495
496 406
        $methods = array();
497 406
        foreach ($classes as $class) {
498 392
            $methods = array_merge($methods, $class->getMethods());
499 406
        }
500
501 406
        foreach ($this->getTargetTraits() AS $trait) {
502 3
            foreach ($trait->getMethods() as $method) {
503 3
                if ($method->isAbstract()) {
504 2
                    $methods[] = $method;
505 2
                }
506 3
            }
507 406
        }
508
509 406
        $names = array();
510 406
        $methods = array_filter($methods, function ($method) use (&$names) {
511 131
            if (in_array($method->getName(), $names)) {
512 3
                return false;
513
            }
514
515 131
            $names[] = $method->getName();
516 131
            return true;
517 406
        });
518
519 406
        return $this->allMethods = $methods;
520
    }
521
522
    /**
523
     * If we attempt to implement Traversable, we must ensure we are also
524
     * implementing either Iterator or IteratorAggregate, and that whichever one
525
     * it is comes before Traversable in the list of implements.
526
     */
527 24
    protected function addTargetInterfaceName($targetInterface)
528
    {
529 24
        $this->targetInterfaceNames[] = $targetInterface;
530 24
    }
531
532 3
    protected function addTargetTraitName($targetTraitName)
533
    {
534 3
        $this->targetTraitNames[] = $targetTraitName;
535 3
    }
536
537 14
    protected function setTargetObject($object)
538
    {
539 14
        $this->targetObject = $object;
540 14
    }
541
}
542