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

phpDocumentor/Descriptor/InterfaceDescriptor.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
 * 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