Completed
Push — develop ( 4b49c4...89d32a )
by Jaap
09:06 queued 05:30
created

src/phpDocumentor/Parser/ServiceProvider.php (4 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
 * 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\Parser;
13
14
use Cilex\Application;
15
use League\Flysystem\MountManager;
16
use phpDocumentor\Infrastructure\FlySystemFactory;
17
use phpDocumentor\Infrastructure\Parser\FlySystemCollector;
18
use phpDocumentor\Infrastructure\Parser\SpecificationFactory;
19
use Pimple\Container;
20
use Pimple\ServiceProviderInterface;
21
use phpDocumentor\Fileset\Collection;
22
use phpDocumentor\Parser\Command\Project\ParseCommand;
23
use phpDocumentor\Parser\Middleware\CacheMiddleware;
24
use phpDocumentor\Parser\Middleware\ErrorHandlingMiddleware;
25
use phpDocumentor\Parser\Middleware\StopwatchMiddleware;
26
use phpDocumentor\Parser\Middleware\EmittingMiddleware;
27
use phpDocumentor\Plugin\Core\Descriptor\Validator\ValidatorAbstract;
28
use phpDocumentor\Reflection\DocBlockFactory;
29
use phpDocumentor\Reflection\Php\Factory;
30
use phpDocumentor\Reflection\Php\NodesFactory;
31
use phpDocumentor\Reflection\Php\ProjectFactory;
32
use phpDocumentor\Reflection\PrettyPrinter;
33
use phpDocumentor\Translator\Translator;
34
use Stash\Driver\FileSystem;
35
use Stash\Pool;
36
37
/**
38
 * This provider is responsible for registering the parser component with the given Application.
39
 */
40
class ServiceProvider implements ServiceProviderInterface
41
{
42
    /**
43
     * Registers services on the given app.
44
     *
45
     * @param Container|Application $app An Application instance
46
     *
47
     * @throws Exception\MissingDependencyException if the Descriptor Builder is not present.
48
     * @throws \Stash\Exception\RuntimeException
49
     *
50
     * @return void
51
     *
52
     */
53
    public function register(Container $app)
54
    {
55
        if (!isset($app['descriptor.builder'])) {
56
            throw new Exception\MissingDependencyException(
57
                'The builder object that is used to construct the ProjectDescriptor is missing'
58
            );
59
        }
60
61
        $app['parser.middleware.cache'] = function () {
62
                return new CacheMiddleware(
63
                    new Pool(new FileSystem(['path' => 'build/api-cache']))
64
                );
65
            };
0 ignored issues
show
Closing brace indented incorrectly; expected 8 spaces, found 12
Loading history...
66
67
        $app['parser'] = function ($app) {
68
            $stopWatch = $app['kernel.stopwatch'];
69
70
            $adapter = new FileSystem(['path' => 'build/api-cache']);
71
            $cachePool = new Pool($adapter);
0 ignored issues
show
$cachePool is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
72
73
            $strategies = [
74
                new Factory\Argument(new PrettyPrinter()),
75
                new Factory\Class_(),
76
                new Factory\Constant(new PrettyPrinter()),
77
                new Factory\DocBlock(DocBlockFactory::createInstance()),
78
                new Factory\Function_(),
79
                new Factory\Interface_(),
80
                new Factory\Method(),
81
                new Factory\Property(new PrettyPrinter()),
82
                new Factory\Trait_(),
83
                new Factory\File(
84
                    NodesFactory::createInstance(),
85
                    [
86
                        new StopwatchMiddleware(
87
                            $stopWatch
88
                        ),
89
                        $app['parser.middleware.cache'],
90
                        new EmittingMiddleware(),
91
                        new ErrorHandlingMiddleware()
92
                    ]
93
                )
94
            ];
95
96
            $parser = new Parser(
97
                new ProjectFactory($strategies),
98
                $stopWatch
99
            );
100
101
            return $parser;
102
        };
103
104
        /** @var Translator $translator */
105
        $translator = $app['translator'];
106
        $translator->addTranslationFolder(__DIR__ . DIRECTORY_SEPARATOR . 'Messages');
107
108
        $fileCollector = new FlySystemCollector(
109
            new SpecificationFactory(),
110
            new FlySystemFactory(new MountManager())
111
        );
112
113
        $app->command(
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class Pimple\Container as the method command() does only exist in the following sub-classes of Pimple\Container: Cilex\Application, phpDocumentor\Application. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
114
            new ParseCommand(
115
                $app['descriptor.builder'],
116
                $app['parser'],
117
                $fileCollector,
118
                $translator,
119
                $app['descriptor.cache'],
120
                $app['parser.example.finder'],
121
                $app['partials']
122
            )
123
        );
124
    }
125
126
    /**
127
     * Load the configuration for given element (deprecated/required)
128
     *
129
     * @param array  $configOptions The configuration from the plugin.xml file
130
     * @param string $configType    Required/Deprecated for the time being
131
     *
132
     * @return array
133
     */
134
    protected function loadConfigurationByElement($configOptions, $configType)
135
    {
136
        $validatorOptions = array();
137
138
        if (isset($configOptions[$configType]->tag)) {
0 ignored issues
show
Blank line found at start of control structure
Loading history...
139
140
            foreach ($configOptions[$configType]->tag as $tag) {
141
                $tagName = (string)$tag['name'];
142
143
                if (isset($tag->element)) {
144
                    foreach ($tag->element as $type) {
145
                        $typeName = (string)$type;
146
                        $validatorOptions[$typeName][] = $tagName;
147
                    }
148
                } else {
149
                    $validatorOptions['__ALL__'][] = $tagName;
150
                }
151
            }
152
        }
153
154
        return $validatorOptions;
155
    }
156
}
157