Completed
Push — develop ( 0cc20e...dccdc9 )
by Mike
07:04
created

src/phpDocumentor/Transformer/Router/Queue.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
declare(strict_types=1);
3
4
/**
5
 * This file is part of phpDocumentor.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @author    Mike van Riel <[email protected]>
11
 * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
12
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
13
 * @link      http://phpdoc.org
14
 */
15
16
namespace phpDocumentor\Transformer\Router;
17
18
use phpDocumentor\Descriptor\Descriptor;
19
use phpDocumentor\Transformer\Transformation;
20
use phpDocumentor\Transformer\Writer\Pathfinder;
21
22
/**
23
 * Provides a queue of routers to determine the order in which they are executed.
24
 */
25
class Queue extends \SplPriorityQueue
26
{
27
    /**
28
     * Tries to match the given node with a rule defined in one of the routers.
29
     *
30
     * @param string|Descriptor $node
31
     *
32 2
     * @return Rule|null
33
     */
34
    public function match($node)
35 2
    {
36 2
        /** @var RouterAbstract $router */
37 2
        foreach (clone $this as $router) {
38 2
            $rule = $router->match($node);
39
            if ($rule) {
40
                return $rule;
41
            }
42 1
        }
43
44
        return null;
45
    }
46
47
    /**
48
     * Uses the currently selected node and transformation to assemble the destination path for the file.
49
     *
50
     * Writers accept the use of a Query to be able to generate output for multiple objects using the same
51
     * template.
52
     *
53
     * The given node is the result of such a query, or if no query given the selected element, and the transformation
54
     * contains the destination file.
55
     *
56
     * Since it is important to be able to generate a unique name per element can the user provide a template variable
57
     * in the name of the file.
58
     * Such a template variable always resides between double braces and tries to take the node value of a given
59
     * query string.
60
     *
61
     * Example:
62
     *
63
     *   An artifact stating `classes/{{name}}.html` will try to find the
64
     *   node 'name' as a child of the given $node and use that value instead.
65
     *
66
     * @throws \InvalidArgumentException if no artifact is provided and no routing rule matches.
67
     * @throws \UnexpectedValueException if the provided node does not contain anything.
68
     *
69
     * @return null|string returns the destination location or false if generation should be aborted.
70
     */
71
    public function destination(Descriptor $descriptor, Transformation $transformation): ?string
72
    {
73
        $path = $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . $transformation->getArtifact();
74
        if (!$transformation->getArtifact()) {
75
            $rule = $this->match($descriptor);
76
            if (!$rule) {
77
                throw new \InvalidArgumentException(
78
                    'No matching routing rule could be found for the given node, please provide an artifact location, '
79
                    . 'encountered: ' . ($descriptor === null ? 'NULL' : get_class($descriptor))
80
                );
81
            }
82
83
            $rule = new ForFileProxy($rule);
84
            $url = $rule->generate($descriptor);
0 ignored issues
show
$descriptor is of type object<phpDocumentor\Descriptor\Descriptor>, but the function expects a string|object<phpDocumen...tor\DescriptorAbstract>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
85
            if ($url === false || $url[0] !== DIRECTORY_SEPARATOR) {
86
                return null;
87
            }
88
89
            $path = $transformation->getTransformer()->getTarget()
90
                . str_replace('/', DIRECTORY_SEPARATOR, $url);
91
        }
92
93
        $finder = new Pathfinder();
94
        $destination = preg_replace_callback(
95
            '/{{([^}]+)}}/', // explicitly do not use the unicode modifier; this breaks windows
96
            function ($query) use ($descriptor, $finder) {
97
                // strip any surrounding \ or /
98
                $filepart = trim((string) current($finder->find($descriptor, $query[1])), '\\/');
99
100
                // make it windows proof
101
                if (extension_loaded('iconv')) {
102
                    $filepart = iconv('UTF-8', 'ASCII//TRANSLIT', $filepart);
103
                }
104
105
                return strpos($filepart, '/') !== false
106
                    ? implode('/', array_map('urlencode', explode('/', $filepart)))
107
                    : implode('\\', array_map('urlencode', explode('\\', $filepart)));
108
            },
109
            $path
110
        );
111
112
        // replace any \ with the directory separator to be compatible with the
113
        // current filesystem and allow the next file_exists to do its work
114
        $destination = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $destination);
115
116
        // create directory if it does not exist yet
117
        if (!file_exists(dirname($destination))) {
118
            mkdir(dirname($destination), 0777, true);
119
        }
120
121
        return $destination;
122
    }
123
}
124