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

src/phpDocumentor/Transformer/ServiceProvider.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\Transformer;
13
14
use Cilex\Application;
15
use Pimple\Container;
16
use Pimple\ServiceProviderInterface;
17
use phpDocumentor\Compiler\Compiler;
18
use phpDocumentor\Compiler\Linker\Linker;
19
use phpDocumentor\Compiler\Pass\ClassTreeBuilder;
20
use phpDocumentor\Compiler\Pass\Debug;
21
use phpDocumentor\Compiler\Pass\ElementsIndexBuilder;
22
use phpDocumentor\Compiler\Pass\ExampleTagsEnricher;
23
use phpDocumentor\Compiler\Pass\InterfaceTreeBuilder;
24
use phpDocumentor\Compiler\Pass\NamespaceTreeBuilder;
25
use phpDocumentor\Compiler\Pass\PackageTreeBuilder;
26
use phpDocumentor\Compiler\Pass\MarkerFromTagsExtractor;
27
use phpDocumentor\Compiler\Pass\ResolveInlineLinkAndSeeTags;
28
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
29
use phpDocumentor\Event\Dispatcher;
30
use phpDocumentor\Fileset\Collection;
31
use phpDocumentor\Transformer\Command\Project\TransformCommand;
32
use phpDocumentor\Transformer\Command\Template\ListCommand;
33
use phpDocumentor\Transformer\Event\PreTransformEvent;
34
use phpDocumentor\Transformer\Template\Factory;
35
use phpDocumentor\Transformer\Template\PathResolver;
36
37
/**
38
 * This provider is responsible for registering the transformer component with the given Application.
39
 */
40
class ServiceProvider extends \stdClass implements ServiceProviderInterface
41
{
42
    /**
43
     * Registers services on the given app.
44
     *
45
     * @param Container $app An Application instance.
46
     *
47
     * @throws Exception\MissingDependencyException if the application does not have a descriptor.builder service.
48
     * @throws Exception\MissingDependencyException if the application does not have a serializer service.
49
     */
50 17
    public function register(Container $app)
51
    {
52 17
        if (!isset($app['descriptor.builder'])) {
53 1
            throw new Exception\MissingDependencyException(
54 1
                'The builder object that is used to construct the ProjectDescriptor is missing'
55
            );
56
        }
57 16
        if (!isset($app['serializer'])) {
58 1
            throw new Exception\MissingDependencyException(
59 1
                'The serializer object that is used to read the template configuration with is missing'
60
            );
61
        }
62
63
        // parameters
64 15
        $app['linker.substitutions'] = array(
65
            'phpDocumentor\Descriptor\ProjectDescriptor'      => array('files'),
66
            'phpDocumentor\Descriptor\FileDescriptor'         => array(
67
                'tags',
68
                'classes',
69
                'interfaces',
70
                'traits',
71
                'functions',
72
                'constants'
73
            ),
74
            'phpDocumentor\Descriptor\ClassDescriptor'        => array(
75
                'tags',
76
                'parent',
77
                'interfaces',
78
                'constants',
79
                'properties',
80
                'methods',
81
                'usedTraits',
82
            ),
83
            'phpDocumentor\Descriptor\InterfaceDescriptor'       => array(
84
                'tags',
85
                'parent',
86
                'constants',
87
                'methods',
88
            ),
89
            'phpDocumentor\Descriptor\TraitDescriptor'           => array(
90
                'tags',
91
                'properties',
92
                'methods',
93
                'usedTraits',
94
            ),
95
            'phpDocumentor\Descriptor\FunctionDescriptor'        => array('tags', 'arguments'),
96
            'phpDocumentor\Descriptor\MethodDescriptor'          => array('tags', 'arguments'),
97
            'phpDocumentor\Descriptor\ArgumentDescriptor'        => array('types'),
98
            'phpDocumentor\Descriptor\PropertyDescriptor'        => array('tags', 'types'),
99
            'phpDocumentor\Descriptor\ConstantDescriptor'        => array('tags', 'types'),
100
            'phpDocumentor\Descriptor\Tag\ParamDescriptor'       => array('types'),
101
            'phpDocumentor\Descriptor\Tag\ReturnDescriptor'      => array('types'),
102
            'phpDocumentor\Descriptor\Tag\SeeDescriptor'         => array('reference'),
103
            'phpDocumentor\Descriptor\Tag\UsesDescriptor'        => array('reference'),
104
            'phpDocumentor\Descriptor\Type\CollectionDescriptor' => array('baseType', 'types', 'keyTypes'),
105
        );
106
107
        // services
108 15
        $app['compiler'] = function ($container) {
109 15
            $compiler = new Compiler();
110 15
            $compiler->insert(new ElementsIndexBuilder(), ElementsIndexBuilder::COMPILER_PRIORITY);
111 15
            $compiler->insert(new MarkerFromTagsExtractor(), MarkerFromTagsExtractor::COMPILER_PRIORITY);
112 15
            $compiler->insert(
113 15
                new ExampleTagsEnricher($container['parser.example.finder']),
114 15
                ExampleTagsEnricher::COMPILER_PRIORITY
115
            );
116 15
            $compiler->insert(new PackageTreeBuilder(), PackageTreeBuilder::COMPILER_PRIORITY);
117 15
            $compiler->insert(new NamespaceTreeBuilder(), NamespaceTreeBuilder::COMPILER_PRIORITY);
118 15
            $compiler->insert(new ClassTreeBuilder(), ClassTreeBuilder::COMPILER_PRIORITY);
119 15
            $compiler->insert(new InterfaceTreeBuilder(), InterfaceTreeBuilder::COMPILER_PRIORITY);
120 15
            $compiler->insert(
121 15
                new ResolveInlineLinkAndSeeTags($container['transformer.routing.queue']),
122 15
                ResolveInlineLinkAndSeeTags::COMPILER_PRIORITY
123
            );
124 15
            $compiler->insert($container['linker'], Linker::COMPILER_PRIORITY);
125 15
            $compiler->insert($container['transformer'], Transformer::COMPILER_PRIORITY);
126 15
            $compiler->insert(
127 15
                new Debug($container['monolog'], $container['descriptor.analyzer']),
128 15
                Debug::COMPILER_PRIORITY
129
            );
130
131 15
            return $compiler;
132
        };
133
134 15
        $app['linker'] = function ($app) {
135 15
            return new Linker($app['linker.substitutions']);
136
        };
137
138 15
        $app['transformer.behaviour.collection'] = function () {
139 15
            return new Behaviour\Collection();
140
        };
141
142 15
        $app['transformer.routing.standard'] = function ($container) {
143
            /** @var ProjectDescriptorBuilder $projectDescriptorBuilder */
144 15
            $projectDescriptorBuilder = $container['descriptor.builder'];
145
146 15
            return new Router\StandardRouter($projectDescriptorBuilder);
147
        };
148
149 15
        $app['transformer.routing.external'] = function ($container) {
150 15
            return new Router\ExternalRouter($container['config']);
151
        };
152
153 15
        $app['transformer.routing.queue'] = function ($container) {
154 15
            $queue = new Router\Queue();
155
156
            // TODO: load from app configuration instead of hardcoded
157 15
            $queue->insert($container['transformer.routing.external'], 10500);
158 15
            $queue->insert($container['transformer.routing.standard'], 10000);
159
160 15
            return $queue;
161
        };
162
163 15
        $app['transformer.writer.collection'] = function ($container) {
164 15
            return new Writer\Collection($container['transformer.routing.queue']);
165
        };
166
167 15
        $this->provideTemplatingSystem($app);
168
169 15
        $app['transformer'] = function ($container) {
170 15
            $transformer = new Transformer(
171 15
                $container['transformer.template.collection'],
172 15
                $container['transformer.writer.collection']
173
            );
174
175
            /** @var Behaviour\Collection $behaviourCollection */
176 15
            $behaviourCollection = $container['transformer.behaviour.collection'];
177 15
            Dispatcher::getInstance()->addListener(
178 15
                Transformer::EVENT_PRE_TRANSFORM,
179 15
                function (PreTransformEvent $event) use ($behaviourCollection) {
180
                    $behaviourCollection->process($event->getProject());
181 15
                }
182
            );
183
184 15
            return $transformer;
185
        };
186
187 15
        $app->command(new TransformCommand($app['descriptor.builder'], $app['transformer'], $app['compiler']));
188 15
        $app->command(new ListCommand($app['transformer.template.factory']));
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...
189 15
    }
190
191
    /**
192
     * Initializes the templating system in the container.
193
     *
194
     * @param Application $app
195
     *
196
     * @return void
197
     */
198 15
    protected function provideTemplatingSystem(Application $app)
199
    {
200 15
        $templateDir = __DIR__ . '/../../../data/templates';
201
202
        // when installed using composer the templates are in a different folder
203 15
        $composerTemplatePath = __DIR__ . '/../../../../templates';
204 15
        if (file_exists($composerTemplatePath)) {
205
            $templateDir = $composerTemplatePath;
206
        }
207
208
        // parameters
209 15
        $app['transformer.template.location'] = $templateDir;
210
211
        // services
212 15
        $app['transformer.template.path_resolver'] = function ($container) {
213 15
            return new PathResolver($container['transformer.template.location']);
214
        };
215
216 15
        $app['transformer.template.factory'] = function ($container) {
217 15
            return new Factory(
218 15
                $container['transformer.template.path_resolver'],
219 15
                $container['serializer']
220
            );
221
        };
222
223 15
        $app['transformer.template.collection'] = function ($container) {
224 15
            return new Template\Collection(
225 15
                $container['transformer.template.factory'],
226 15
                $container['transformer.writer.collection']
227
            );
228
        };
229 15
    }
230
}
231