Completed
Push — develop ( c4d989...a97889 )
by Jaap
12s
created

Renderer::renderLink()   D

Complexity

Conditions 10
Paths 30

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
rs 4.8196
cc 10
eloc 19
nc 30
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace phpDocumentor\DomainModel\Renderer\Router;
4
5
use phpDocumentor\Descriptor\Collection;
6
use phpDocumentor\Descriptor\DescriptorAbstract;
7
use phpDocumentor\Descriptor\Type\CollectionDescriptor;
8
9
/**
10
 * Renders an HTML anchor pointing to the location of the provided element.
11
 */
12
class Renderer
13
{
14
    /** @var string */
15
    protected $destination = '';
16
17
    /** @var Queue */
18
    private $routers;
19
20
    /**
21
     * Initializes this renderer with a set of routers that are checked.
22
     *
23
     * @param Queue $routers
24
     */
25
    public function __construct($routers)
26
    {
27
        $this->routers = $routers;
28
    }
29
30
    /**
31
     * Overwrites the associated routers with a new set of routers.
32
     *
33
     * @param Queue $routers
34
     *
35
     * @return void
36
     */
37
    public function setRouters($routers)
38
    {
39
        $this->routers = $routers;
40
    }
41
42
    /**
43
     * Returns the routers used in generating the URLs for the anchors.
44
     *
45
     * @return Queue
46
     */
47
    public function getRouters()
48
    {
49
        return $this->routers;
50
    }
51
52
    /**
53
     * Sets the destination directory relative to the Project's Root.
54
     *
55
     * The destination is the target directory containing the resulting
56
     * file. This destination is relative to the Project's root and can
57
     * be used for the calculation of nesting depths, etc.
58
     *
59
     * For this specific extension the destination is provided in the
60
     * Twig writer itself.
61
     *
62
     * @param string $destination
63
     *
64
     * @see phpDocumentor\Application\Renderer\Action\TwigHandler for the invocation of this method.
65
     *
66
     * @return void
67
     */
68
    public function setDestination($destination)
69
    {
70
        $this->destination = $destination;
71
    }
72
73
    /**
74
     * Returns the target directory relative to the Project's Root.
75
     *
76
     * @return string
77
     */
78
    public function getDestination()
79
    {
80
        return $this->destination;
81
    }
82
83
    /**
84
     * @param mixed $value
85
     * @param string $presentation
86
     *
87
     * @return bool|mixed|string|\string[]
88
     */
89
    public function render($value, $presentation)
90
    {
91
        if (is_array($value) || $value instanceof \Traversable || $value instanceof Collection) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Descriptor\Collection does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
92
            return $this->renderASeriesOfLinks($value, $presentation);
93
        }
94
95
        if ($value instanceof CollectionDescriptor) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Descriptor\Type\CollectionDescriptor does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
96
            return $this->renderTypeCollection($value, $presentation);
97
        }
98
99
        return $this->renderLink($value, $presentation);
100
    }
101
102
    /**
103
     * Converts the given path to be relative to the root of the documentation
104
     * target directory.
105
     *
106
     * It is not possible to use absolute paths in documentation templates since
107
     * they may be used locally, or in a subfolder. As such we need to calculate
108
     * the number of levels to go up from the current document's directory and
109
     * then append the given path.
110
     *
111
     * For example:
112
     *
113
     *     Suppose you are in <root>/classes/my/class.html and you want open
114
     *     <root>/my/index.html then you provide 'my/index.html' to this method
115
     *     and it will convert it into ../../my/index.html (<root>/classes/my is
116
     *     two nesting levels until the root).
117
     *
118
     * This method does not try to normalize or optimize the paths in order to
119
     * save on development time and performance, and because it adds no real
120
     * value.
121
     *
122
     * @param string $relative_path
123
     *
124
     * @return string
125
     */
126
    public function convertToRootPath($relative_path)
127
    {
128
        // get the path to the root directory
129
        $path_parts   = explode(DIRECTORY_SEPARATOR, $this->getDestination());
130
        $path_to_root = (count($path_parts) > 1)
131
            ? implode('/', array_fill(0, count($path_parts) -1, '..')).'/'
132
            : '';
133
134
        // append the relative path to the root
135
        if (is_string($relative_path) && ($relative_path[0] != '@')) {
136
            return $path_to_root . ltrim($relative_path, '/');
137
        }
138
139
        $rule = $this->routers->match($relative_path);
140
        if (!$rule) {
141
            return null;
142
        }
143
144
        $generatedPath = $rule->generate($relative_path);
145
146
        return $generatedPath ? $path_to_root . ltrim($generatedPath, '/') : null;
147
    }
148
149
    /**
150
     * Returns a series of anchors and strings for the given collection of routable items.
151
     *
152
     * @param array|\Traversable|Collection $value
153
     * @param string                        $presentation
154
     *
155
     * @return string[]
156
     */
157
    protected function renderASeriesOfLinks($value, $presentation)
158
    {
159
        if ($value instanceof Collection) {
0 ignored issues
show
Bug introduced by
The class phpDocumentor\Descriptor\Collection does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
160
            $value = $value->getAll();
161
        }
162
163
        $result = array();
164
        foreach ($value as $path) {
165
            $result[] = $this->render($path, $presentation);
166
        }
167
168
        return $result;
169
    }
170
171
    /**
172
     * Renders the view representation for an array or collection.
173
     *
174
     * @param CollectionDescriptor $value
175
     * @param string               $presentation
176
     *
177
     * @return string
178
     */
179
    protected function renderTypeCollection($value, $presentation)
180
    {
181
        $baseType = $this->render($value->getBaseType(), $presentation);
182
        $keyTypes = $this->render($value->getKeyTypes(), $presentation);
183
        $types = $this->render($value->getTypes(), $presentation);
184
185
        $arguments = array();
186
        if ($keyTypes) {
187
            $arguments[] = implode('|', $keyTypes);
188
        }
189
        $arguments[] = implode('|', $types);
190
191
        if ($value->getName() == 'array' && count($value->getKeyTypes()) == 0) {
192
            $typeString = (count($types) > 1) ? '(' . reset($arguments) . ')' : reset($arguments);
193
            $collection = $typeString . '[]';
194
        } else {
195
            $collection = ($baseType ? : $value->getName()) . '&lt;' . implode(',', $arguments) . '&gt;';
196
        }
197
198
        return $collection;
199
    }
200
201
    protected function renderLink($path, $presentation)
0 ignored issues
show
Complexity introduced by
This operation has 300 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

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

Loading history...
202
    {
203
        $url  = false;
204
        $rule = $this->routers->match($path);
205
        if ($rule) {
206
            $generatedUrl = $rule->generate($path);
207
            $url = $generatedUrl ? ltrim($generatedUrl, '/') : false;
208
        }
209
210
        if (is_string($url)
211
            && $url[0] != '/'
212
            && (strpos($url, 'http://') !== 0)
213
            && (strpos($url, 'https://') !== 0)
214
        ) {
215
            $url = $this->convertToRootPath($url);
216
        }
217
218
        switch ($presentation) {
219
            case 'url': // return the first url
220
                return $url;
221
            case 'class:short':
222
                $parts = explode('\\', $path);
223
                $path = end($parts);
224
                break;
225
        }
226
227
        return $url ? sprintf('<a href="%s">%s</a>', $url, $path) : $path;
228
    }
229
}
230