Issues (201)

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.

src/Api/Php/Clazz.php (2 issues)

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
/*
4
 * This file is part of the puli/manager package.
5
 *
6
 * (c) Bernhard Schussek <[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 Puli\Manager\Api\Php;
13
14
use OutOfBoundsException;
15
use RuntimeException;
16
use Webmozart\Assert\Assert;
17
use Webmozart\PathUtil\Path;
18
19
/**
20
 * A model of a class.
21
 *
22
 * @since  1.0
23
 *
24
 * @author Bernhard Schussek <[email protected]>
25
 */
26
class Clazz
27
{
28
    /**
29
     * @var string
30
     */
31
    private $namespaceName;
32
33
    /**
34
     * @var string
35
     */
36
    private $shortClassName;
37
38
    /**
39
     * @var string
40
     */
41
    private $directory;
42
43
    /**
44
     * @var string
45
     */
46
    private $fileName;
47
48
    /**
49
     * @var string
50
     */
51
    private $parentClass;
52
53
    /**
54
     * @var bool[]
55
     */
56
    private $implementedInterfaces = array();
57
58
    /**
59
     * @var Import[]
60
     */
61
    private $imports = array();
62
63
    /**
64
     * @var string[]
65
     */
66
    private $importedSymbols = array();
67
68
    /**
69
     * @var Method[]
70
     */
71
    private $methods = array();
72
73
    /**
74
     * @var string
75
     */
76
    private $description;
77
78
    /**
79
     * Creates a new factory class.
80
     *
81
     * @param string $className The fully-qualified class name.
82
     */
83 208
    public function __construct($className)
84
    {
85 208
        $this->setClassName($className);
86 208
    }
87
88
    /**
89
     * Sets the fully-qualified name of the factory class.
90
     *
91
     * @param string $className The fully-qualified class name.
92
     *
93
     * @return static The current instance.
94
     */
95 208
    public function setClassName($className)
96
    {
97 208
        Assert::stringNotEmpty($className, 'The class name must be a non-empty string. Got: %s');
98
99 208
        $pos = strrpos($className, '\\');
100
101 208 View Code Duplication
        if (false === $pos) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
102 67
            $this->namespaceName = '';
103 67
            $this->shortClassName = $className;
104
        } else {
105 144
            $this->namespaceName = substr($className, 0, $pos);
106 144
            $this->shortClassName = substr($className, $pos + 1);
107
        }
108
109 208
        return $this;
110
    }
111
112
    /**
113
     * Returns the fully-qualified name of the factory class.
114
     *
115
     * @return string The fully-qualified class name.
116
     */
117 9
    public function getClassName()
118
    {
119 9
        return $this->namespaceName
120 5
            ? $this->namespaceName.'\\'.$this->shortClassName
121 9
            : $this->shortClassName;
122
    }
123
124
    /**
125
     * Returns the namespace of the factory class.
126
     *
127
     * @return string The namespace or an empty string if the class is in the
128
     *                global namespace.
129
     */
130 53
    public function getNamespaceName()
131
    {
132 53
        return $this->namespaceName;
133
    }
134
135
    /**
136
     * Returns the short class name.
137
     *
138
     * @return string The short name of the factory class.
139
     */
140 53
    public function getShortClassName()
141
    {
142 53
        return $this->shortClassName;
143
    }
144
145
    /**
146
     * Returns the path to the directory holding the factory class file.
147
     *
148
     * @return string The absolute directory path.
149
     */
150 91
    public function getDirectory()
151
    {
152 91
        return $this->directory;
153
    }
154
155
    /**
156
     * Sets the path to the directory holding the factory class file.
157
     *
158
     * @param string $directory The absolute directory path.
159
     *
160
     * @return static The current instance.
161
     */
162 118
    public function setDirectory($directory)
163
    {
164 118
        Assert::stringNotEmpty($directory, 'The factory directory must be a non-empty string. Got: %s');
165
166 115
        $this->directory = Path::canonicalize($directory);
167
168 115
        return $this;
169
    }
170
171
    /**
172
     * Returns the name of the factory class file.
173
     *
174
     * If no file name was set, the file is named after the short class name
175
     * suffixed with ".php".
176
     *
177
     * @return string The file name.
178
     */
179 60
    public function getFileName()
180
    {
181 60
        if (!$this->fileName) {
182 30
            return $this->shortClassName.'.php';
183
        }
184
185 30
        return $this->fileName;
186
    }
187
188
    /**
189
     * Sets the name of the factory class file.
190
     *
191
     * @param string $fileName The file name.
192
     *
193
     * @return static The current instance.
194
     */
195 90
    public function setFileName($fileName)
196
    {
197 90
        Assert::stringNotEmpty($fileName, 'The factory file name must be a non-empty string. Got: %s');
198
199 87
        $this->fileName = $fileName;
200
201 87
        return $this;
202
    }
203
204
    /**
205
     * Resets the name of the factory class file to the default value.
206
     *
207
     * By default, the file is named after the short class name suffixed with
208
     * ".php".
209
     *
210
     * @return static The current instance.
211
     */
212 1
    public function resetFileName()
213
    {
214 1
        $this->fileName = null;
215
216 1
        return $this;
217
    }
218
219
    /**
220
     * Returns the absolute file path of the factory class file.
221
     *
222
     * @return string The absolute file path.
223
     */
224 51
    public function getFilePath()
225
    {
226 51
        return $this->directory.'/'.$this->getFileName();
227
    }
228
229
    /**
230
     * Sets the absolute file path of the factory class file.
231
     *
232
     * @param string $filePath The absolute file path.
233
     *
234
     * @return static The current instance.
235
     */
236 86
    public function setFilePath($filePath)
237
    {
238 86
        Assert::stringNotEmpty($filePath, 'The factory file path must be a non-empty string. Got: %s');
239
240 83
        $this->setDirectory(Path::getDirectory($filePath));
241 83
        $this->setFileName(Path::getFilename($filePath));
242
243 83
        return $this;
244
    }
245
246
    /**
247
     * Returns the parent class name.
248
     *
249
     * @return string|null The parent class name or `null` if the class has no
250
     *                     parent class.
251
     */
252 4
    public function getParentClass()
253
    {
254 4
        return $this->parentClass;
255
    }
256
257
    /**
258
     * Sets the parent class name.
259
     *
260
     * If you don't pass a fully-qualified name, make sure to import the name
261
     * with {@link addImport()}.
262
     *
263
     * @param string $parentClass The parent class name.
264
     *
265
     * @return static The current instance.
266
     */
267 8
    public function setParentClass($parentClass)
268
    {
269 8
        Assert::stringNotEmpty($parentClass, 'The parent class name must be a non-empty string. Got: %s');
270
271 5
        $this->parentClass = $parentClass;
272
273 5
        return $this;
274
    }
275
276
    /**
277
     * Returns whether the class extends another class.
278
     *
279
     * @return bool Returns `true` if the class has a parent class and `false`
280
     *              otherwise.
281
     */
282 51
    public function hasParentClass()
283
    {
284 51
        return null !== $this->parentClass;
285
    }
286
287
    /**
288
     * Removes the parent class.
289
     *
290
     * @return static The current instance.
291
     */
292 2
    public function removeParentClass()
293
    {
294 2
        $this->parentClass = null;
295
296 2
        return $this;
297
    }
298
299
    /**
300
     * Returns the interfaces that the class implements.
301
     *
302
     * @return string[] The names of the implemented interfaces.
0 ignored issues
show
Should the return type not be integer[]?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
303
     */
304 8
    public function getImplementedInterfaces()
305
    {
306 8
        return array_keys($this->implementedInterfaces);
307
    }
308
309
    /**
310
     * Returns whether the class implements any interfaces.
311
     *
312
     * @return bool Returns `true` if the class implements any interfaces and
313
     *              `false` otherwise.
314
     */
315 51
    public function hasImplementedInterfaces()
316
    {
317 51
        return count($this->implementedInterfaces) > 0;
318
    }
319
320
    /**
321
     * Sets the interfaces that the class implements.
322
     *
323
     * Previously added interfaces are overwritten.
324
     *
325
     * If you don't pass fully-qualified names, make sure to import the names
326
     * with {@link addImport()}.
327
     *
328
     * @param string[] $interfaceNames The names of the implemented interfaces.
329
     *
330
     * @return static The current instance.
331
     */
332 1
    public function setImplementedInterfaces(array $interfaceNames)
333
    {
334 1
        $this->implementedInterfaces = array();
335
336 1
        $this->addImplementedInterfaces($interfaceNames);
337
338 1
        return $this;
339
    }
340
341
    /**
342
     * Adds implemented interfaces to the class definition.
343
     *
344
     * Previously added interfaces are kept.
345
     *
346
     * If you don't pass fully-qualified names, make sure to import the names
347
     * with {@link addImport()}.
348
     *
349
     * @param string[] $interfaceNames The names of the added interfaces.
350
     *
351
     * @return static The current instance.
352
     */
353 2
    public function addImplementedInterfaces(array $interfaceNames)
354
    {
355 2
        foreach ($interfaceNames as $interfaceName) {
356 2
            $this->addImplementedInterface($interfaceName);
357
        }
358
359 2
        return $this;
360
    }
361
362
    /**
363
     * Adds an implemented interface to the class definition.
364
     *
365
     * If you don't pass a fully-qualified name, make sure to import the name
366
     * with {@link addImport()}.
367
     *
368
     * @param string $interfaceName The name of the added interfaces.
369
     *
370
     * @return static The current instance.
371
     */
372 12
    public function addImplementedInterface($interfaceName)
373
    {
374 12
        Assert::stringNotEmpty($interfaceName, 'The interface name must be a non-empty string. Got: %s');
375
376 9
        $this->implementedInterfaces[$interfaceName] = true;
377
378 9
        return $this;
379
    }
380
381
    /**
382
     * Removes an implemented interface from the class definition.
383
     *
384
     * @param string $interfaceName The name of the removed interfaces.
385
     *
386
     * @return static The current instance.
387
     */
388 3
    public function removeImplementedInterface($interfaceName)
389
    {
390 3
        unset($this->implementedInterfaces[$interfaceName]);
391
392 3
        return $this;
393
    }
394
395
    /**
396
     * Removes all implemented interfaces from the class definition.
397
     *
398
     * @return static The current instance.
399
     */
400 1
    public function clearImplementedInterfaces()
401
    {
402 1
        $this->implementedInterfaces = array();
403
404 1
        return $this;
405
    }
406
407
    /**
408
     * Returns the import statements of the class file.
409
     *
410
     * @return Import[] The imported fully-qualified class names.
411
     */
412 40
    public function getImports()
413
    {
414 40
        return $this->imports;
415
    }
416
417
    /**
418
     * Returns whether the class file imports any class name.
419
     *
420
     * @return bool Returns `true` if the class file imports class names and
421
     *              `false` otherwise.
422
     */
423 51
    public function hasImports()
424
    {
425 51
        return count($this->imports) > 0;
426
    }
427
428
    /**
429
     * Sets the import statements of the class file.
430
     *
431
     * Previously added imports are overwritten.
432
     *
433
     * @param Import[] $imports The imported fully-qualified class names.
434
     *
435
     * @return static The current instance.
436
     */
437 1
    public function setImports(array $imports)
438
    {
439 1
        $this->imports = array();
440
441 1
        $this->addImports($imports);
442
443 1
        return $this;
444
    }
445
446
    /**
447
     * Adds import statements to the class file.
448
     *
449
     * Previously added imports are kept.
450
     *
451
     * @param Import[] $imports The imported fully-qualified class names.
452
     *
453
     * @return static The current instance.
454
     */
455 2
    public function addImports(array $imports)
456
    {
457 2
        foreach ($imports as $import) {
458 2
            $this->addImport($import);
459
        }
460
461 2
        return $this;
462
    }
463
464
    /**
465
     * Adds an import statement to the class file.
466
     *
467
     * @param Import $import The imported fully-qualified class name.
468
     *
469
     * @return static The current instance.
470
     */
471 72
    public function addImport(Import $import)
472
    {
473 72
        if (isset($this->imports[$import->getClassName()])) {
474 29
            return $this;
475
        }
476
477 72
        $symbol = $import->getAlias() ?: $import->getShortClassName();
478
479 72
        if (isset($this->importedSymbols[$symbol])) {
480 3
            throw new RuntimeException(sprintf(
481 3
                'The symbol "%s" was imported already.',
482 3
                $import->getShortClassName()
483
            ));
484
        }
485
486 72
        $this->imports[$import->getClassName()] = $import;
487 72
        $this->importedSymbols[$symbol] = true;
488
489 72
        ksort($this->imports);
490
491 72
        return $this;
492
    }
493
494
    /**
495
     * Removes an import statement from the class file.
496
     *
497
     * If the import statement is not found, this method does nothing.
498
     *
499
     * @param string $className The removed imported class name.
500
     *
501
     * @return static The current instance.
502
     */
503 2
    public function removeImport($className)
504
    {
505 2
        if (isset($this->imports[$className])) {
506 2
            $import = $this->imports[$className];
507 2
            $symbol = $import->getAlias() ?: $import->getShortClassName();
508
509 2
            unset($this->imports[$className]);
510 2
            unset($this->importedSymbols[$symbol]);
511
        }
512
513 2
        return $this;
514
    }
515
516
    /**
517
     * Removes all import statements from the class file.
518
     *
519
     * @return static The current instance.
520
     */
521 1
    public function clearImports()
522
    {
523 1
        $this->imports = array();
524
525 1
        return $this;
526
    }
527
528
    /**
529
     * Returns the methods of the factory class.
530
     *
531
     * @return Method[] The methods indexed by their names.
532
     */
533 56
    public function getMethods()
534
    {
535 56
        return $this->methods;
536
    }
537
538
    /**
539
     * Returns the method with the given name.
540
     *
541
     * @param string $name The name of the method.
542
     *
543
     * @return Method The method.
544
     *
545
     * @throws OutOfBoundsException If the method with the given name does not
546
     *                              exist.
547
     */
548 2
    public function getMethod($name)
549
    {
550 2
        if (!isset($this->methods[$name])) {
551 1
            throw new OutOfBoundsException(sprintf(
552 1
                'The method "%s" does not exist.',
553
                $name
554
            ));
555
        }
556
557 1
        return $this->methods[$name];
558
    }
559
560
    /**
561
     * Returns whether the class contains any methods.
562
     *
563
     * @return bool Returns `true` if the class contains methods and `false`
564
     *              otherwise.
565
     */
566 1
    public function hasMethods()
567
    {
568 1
        return count($this->methods) > 0;
569
    }
570
571
    /**
572
     * Returns whether the class contains a method with the given name.
573
     *
574
     * @param string $name The name of the method.
575
     *
576
     * @return bool Returns `true` if the method with the given name exists and
577
     *              `false` otherwise.
578
     */
579 2
    public function hasMethod($name)
580
    {
581 2
        return isset($this->methods[$name]);
582
    }
583
584
    /**
585
     * Sets the methods of the class.
586
     *
587
     * Previously added methods are overwritten.
588
     *
589
     * @param Method[] $methods The methods of the class.
590
     *
591
     * @return static The current instance.
592
     */
593 1
    public function setMethods(array $methods)
594
    {
595 1
        $this->methods = array();
596
597 1
        $this->addMethods($methods);
598
599 1
        return $this;
600
    }
601
602
    /**
603
     * Adds methods to the class.
604
     *
605
     * Previously added methods are kept.
606
     *
607
     * @param Method[] $methods The methods to add to the class.
608
     *
609
     * @return static The current instance.
610
     */
611 2
    public function addMethods(array $methods)
612
    {
613 2
        foreach ($methods as $method) {
614 2
            $this->addMethod($method);
615
        }
616
617 2
        return $this;
618
    }
619
620
    /**
621
     * Adds a method to the class.
622
     *
623
     * @param Method $method The method to add to the class.
624
     *
625
     * @return static The current instance.
626
     */
627 110
    public function addMethod(Method $method)
628
    {
629 110
        if (isset($this->methods[$method->getName()])) {
630 1
            throw new RuntimeException(sprintf(
631 1
                'The method "%s" exists already.',
632 1
                $method->getName()
633
            ));
634
        }
635
636 110
        $this->methods[$method->getName()] = $method;
637
638 110
        $method->setClass($this);
639
640 110
        return $this;
641
    }
642
643
    /**
644
     * Removes a method from the class.
645
     *
646
     * @param string $name The name of the removed method.
647
     *
648
     * @return static The current instance.
649
     */
650 4
    public function removeMethod($name)
651
    {
652 4
        unset($this->methods[$name]);
653
654 4
        return $this;
655
    }
656
657
    /**
658
     * Removes all methods from the class.
659
     *
660
     * @return static The current instance.
661
     */
662 1
    public function clearMethods()
663
    {
664 1
        $this->methods = array();
665
666 1
        return $this;
667
    }
668
669
    /**
670
     * Returns the description of the class.
671
     *
672
     * @return string The class description.
673
     */
674 51
    public function getDescription()
675
    {
676 51
        return $this->description;
677
    }
678
679
    /**
680
     * Sets the description of the class.
681
     *
682
     * @param string $description The class description.
683
     *
684
     * @return static The current instance.
685
     */
686 33
    public function setDescription($description)
687
    {
688 33
        Assert::stringNotEmpty($description, 'The class description must be a non-empty string. Got: %s');
689
690 30
        $this->description = $description;
691
692 30
        return $this;
693
    }
694
}
695