Completed
Push — develop ( 37deef...f45442 )
by Jaap
05:54
created

phpDocumentor/Descriptor/InterfaceDescriptor.php (1 issue)

Labels
Severity

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
 * phpDocumentor
4
 *
5
 * PHP Version 5.3
6
 *
7
 * @copyright 2010-2014 Mike van Riel / Naenius (http://www.naenius.com)
8
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
9
 * @link      http://phpdoc.org
10
 */
11
12
namespace phpDocumentor\Descriptor;
13
14
/**
15
 * Descriptor representing an Interface.
16
 */
17
class InterfaceDescriptor extends DescriptorAbstract implements Interfaces\InterfaceInterface
18
{
19
    /** @var Collection $extends */
20
    protected $parents;
21
22
    /** @var Collection $constants */
23
    protected $constants;
24
25
    /** @var Collection $methods */
26
    protected $methods;
27
28
    /**
29
     * Initializes the all properties representing a collection with a new Collection object.
30
     */
31 1
    public function __construct()
32
    {
33 1
        parent::__construct();
34
35 1
        $this->setParent(new Collection());
36 1
        $this->setConstants(new Collection());
37 1
        $this->setMethods(new Collection());
38 1
    }
39
40
    /**
41
     * {@inheritDoc}
42
     */
43 1
    public function setParent($parents)
44
    {
45 1
        $this->parents = $parents;
46 1
    }
47
48
    /**
49
     * {@inheritDoc}
50
     */
51 1
    public function getParent()
52
    {
53 1
        return $this->parents;
54
    }
55
56
    /**
57
     * {@inheritDoc}
58
     */
59 1
    public function setConstants(Collection $constants)
60
    {
61 1
        $this->constants = $constants;
62 1
    }
63
64
    /**
65
     * {@inheritDoc}
66
     */
67 1
    public function getConstants()
68
    {
69 1
        return $this->constants;
70
    }
71
72
    /**
73
     * {@inheritDoc}
74
     */
75 2
    public function getInheritedConstants()
76
    {
77 2
        if (!$this->getParent() || !$this->getParent() instanceof Collection || $this->getParent()->count() === 0) {
78 2
            return new Collection();
79
        }
80
81 1
        $inheritedConstants = new Collection();
82
83
        /** @var self $parent */
84 1
        foreach ($this->getParent() as $parent) {
85 1
            if (!$parent instanceof Interfaces\InterfaceInterface) {
86
                continue;
87
            }
88
89 1
            $inheritedConstants = $inheritedConstants->merge($parent->getConstants());
90 1
            $inheritedConstants = $inheritedConstants->merge($parent->getInheritedConstants());
91
        }
92
93 1
        return $inheritedConstants;
94
    }
95
96
    /**
97
     * {@inheritDoc}
98
     */
99 1
    public function setMethods(Collection $methods)
100
    {
101 1
        $this->methods = $methods;
102 1
    }
103
104
    /**
105
     * {@inheritDoc}
106
     */
107 1
    public function getMethods()
108
    {
109 1
        return $this->methods;
110
    }
111
112
    /**
113
     * {@inheritDoc}
114
     */
115 2
    public function getInheritedMethods()
116
    {
117 2
        if (!$this->getParent() || !$this->getParent() instanceof Collection || $this->getParent()->count() === 0) {
118 2
            return new Collection();
119
        }
120
121 1
        $inheritedMethods = new Collection();
122
123
        /** @var self $parent */
124 1
        foreach ($this->getParent() as $parent) {
125 1
            if (!$parent instanceof Interfaces\InterfaceInterface) {
126
                continue;
127
            }
128
129 1
            $inheritedMethods = $inheritedMethods->merge($parent->getMethods());
130 1
            $inheritedMethods = $inheritedMethods->merge($parent->getInheritedMethods());
131
        }
132
133 1
        return $inheritedMethods;
134
    }
135
136
    public function setPackage($package)
137
    {
138
        parent::setPackage($package);
139
140
        foreach ($this->getConstants() as $constant) {
141
            $constant->setPackage($package);
142
        }
143
144
        foreach ($this->getMethods() as $method) {
145
            $method->setPackage($package);
146
        }
147
    }
148
149
    public function getInheritedElement()
150
    {
151
        return $this->getParent() && $this->getParent()->count() > 0
152
            ? $this->getParent()->getIterator()->current()
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Traversable as the method current() does only exist in the following implementations of said interface: APCUIterator, AppendIterator, ArrayIterator, Behat\Behat\Gherkin\Spec...ion\LazyFeatureIterator, Behat\Testwork\Specifica...edSpecificationIterator, Behat\Testwork\Specifica...oSpecificationsIterator, Behat\Testwork\Specifica...cificationArrayIterator, CachingIterator, CallbackFilterIterator, CoreTestIterator, DirectoryIterator, EmptyIterator, File_Iterator, FilesystemIterator, FilterIterator, Generator, GlobIterator, HttpMessage, HttpRequestPool, Imagick, ImagickPixelIterator, InfiniteIterator, Issue523, IteratorIterator, LimitIterator, MongoCommandCursor, MongoCursor, MongoGridFSCursor, MultipleIterator, NoRewindIterator, PHPUnit\Framework\TestSuiteIterator, PHPUnit\Runner\Filter\ExcludeGroupFilterIterator, PHPUnit\Runner\Filter\GroupFilterIterator, PHPUnit\Runner\Filter\IncludeGroupFilterIterator, PHPUnit\Runner\Filter\NameFilterIterator, PHP_Token_Stream, ParentIterator, Phar, PharData, PharIo\Manifest\AuthorCollectionIterator, PharIo\Manifest\AuthorElementCollection, PharIo\Manifest\BundledComponentCollectionIterator, PharIo\Manifest\ComponentElementCollection, PharIo\Manifest\ElementCollection, PharIo\Manifest\ExtElementCollection, PharIo\Manifest\RequirementCollectionIterator, Pimple\ServiceIterator, RecursiveArrayIterator, RecursiveCachingIterator, RecursiveCallbackFilterIterator, RecursiveDirectoryIterator, RecursiveFilterIterator, RecursiveIteratorIterator, RecursiveRegexIterator, RecursiveTreeIterator, RegexIterator, SQLiteResult, SebastianBergmann\CodeCoverage\Node\Iterator, SimpleXMLIterator, SplDoublyLinkedList, SplFileObject, SplFixedArray, SplHeap, SplMaxHeap, SplMinHeap, SplObjectStorage, SplPriorityQueue, SplQueue, SplStack, SplTempFileObject, Symfony\Component\Finder...or\CustomFilterIterator, Symfony\Component\Finder...DateRangeFilterIterator, Symfony\Component\Finder...epthRangeFilterIterator, Symfony\Component\Finder...DirectoryFilterIterator, Symfony\Component\Finder...rator\FilePathsIterator, Symfony\Component\Finder...\FileTypeFilterIterator, Symfony\Component\Finder...lecontentFilterIterator, Symfony\Component\Finder...\FilenameFilterIterator, Symfony\Component\Finder\Iterator\FilterIterator, Symfony\Component\Finder...tiplePcreFilterIterator, Symfony\Component\Finder...ator\PathFilterIterator, Symfony\Component\Finder...ursiveDirectoryIterator, Symfony\Component\Finder...SizeRangeFilterIterator, Symfony\Component\Finder...rator\InnerNameIterator, Symfony\Component\Finder...rator\InnerSizeIterator, Symfony\Component\Finder...rator\InnerTypeIterator, Symfony\Component\Finder\Tests\Iterator\Iterator, Symfony\Component\Finder...or\MockFileListIterator, Symfony\Component\Finder...tiplePcreFilterIterator, TestIterator, TestIterator2, TheSeer\Tokenizer\TokenCollection, TwigTestFoo, Twig\Util\TemplateDirIterator, Twig_Util_TemplateDirIterator, Zend\Cache\Storage\Adapter\ApcIterator, Zend\Cache\Storage\Adapter\ApcuIterator, Zend\Cache\Storage\Adapter\DbaIterator, Zend\Cache\Storage\Adapter\FilesystemIterator, Zend\Cache\Storage\Adapter\KeyListIterator, Zend\Config\Config, Zend\EventManager\ResponseCollection, Zend\Hydrator\Iterator\HydratingArrayIterator, Zend\Hydrator\Iterator\HydratingIteratorIterator, Zend\Stdlib\FastPriorityQueue, Zend\Stdlib\Hydrator\Ite...\HydratingArrayIterator, Zend\Stdlib\Hydrator\Ite...dratingIteratorIterator, Zend\Stdlib\PriorityList, Zend\Stdlib\SplPriorityQueue, Zend\Stdlib\SplQueue, Zend\Stdlib\SplStack, ezcBaseAutoloadOptions, ezcBaseOptions, ezcBaseTestOptions, ezcDocumentBBCodeOptions, ezcDocumentConverterOptions, ezcDocumentDocbookOptions, ezcDocumentDocbookToEzXmlConverterOptions, ezcDocumentDocbookToHtmlConverterOptions, ezcDocumentDocbookToHtmlXsltConverterOptions, ezcDocumentDocbookToOdtConverterOptions, ezcDocumentDocbookToRstConverterOptions, ezcDocumentDocbookToWikiConverterOptions, ezcDocumentEzXmlOptions, ezcDocumentEzXmlToDocbookConverterOptions, ezcDocumentHtmlConverterOptions, ezcDocumentOdtOptions, ezcDocumentOptions, ezcDocumentParserOptions, ezcDocumentPdfFooterOptions, ezcDocumentPdfOptions, ezcDocumentRstOptions, ezcDocumentWikiOptions, ezcDocumentXhtmlOptions, ezcDocumentXmlOptions, ezcDocumentXsltConverterOptions, org\bovigo\vfs\vfsStreamContainerIterator, phpDocumentor\Compiler\Compiler, phpDocumentor\Reflection...y\ClassConstantIterator, phpDocumentor\Reflection...actory\PropertyIterator, phpDocumentor\Transformer\Router\Queue, phpDocumentor\Transformer\Template.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
153
            : null;
154
    }
155
}
156