Absolutize   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 6
dl 0
loc 121
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A drawNodes() 0 20 3
A resolveServerUrl() 0 11 3
C removeDotSegments() 0 41 14
1
<?php
2
/**
3
 * Webino (http://webino.sk)
4
 *
5
 * @link        https://github.com/webino/WebinoDraw for the canonical source repository
6
 * @copyright   Copyright (c) 2012-2017 Webino, s. r. o. (http://webino.sk)
7
 * @author      Peter Bačinský <[email protected]>
8
 * @license     BSD-3-Clause
9
 */
10
11
namespace WebinoDraw\Draw\Helper;
12
13
use DOMAttr as DomAttr;
14
use WebinoDraw\Dom\NodeList;
15
use WebinoDraw\Exception\RuntimeException;
16
use Zend\View\Helper\ServerUrl;
17
use Zend\View\Helper\BasePath;
18
19
/**
20
 * Draw helper used for prepend relative URL with basePath
21
 */
22
class Absolutize extends AbstractHelper
23
{
24
    /**
25
     * Draw helper service name
26
     */
27
    const SERVICE = 'webinodrawabsolutize';
28
29
    /**
30
     * @var ServerUrl
31
     */
32
    protected $serverUrl;
33
34
    /**
35
     * @var BasePath
36
     */
37
    protected $basePath;
38
39
    /**
40
     * @param ServerUrl $serverUrl
41
     * @param BasePath $basePath
42
     */
43
    public function __construct(ServerUrl $serverUrl, BasePath $basePath)
44
    {
45
        $this->serverUrl = $serverUrl;
46
        $this->basePath  = $basePath;
47
    }
48
49
    /**
50
     * @param NodeList $nodes
51
     * @param array $spec
52
     * @return void
53
     * @throw RuntimeException
54
     */
55
    public function drawNodes(NodeList $nodes, array $spec)
56
    {
57
        $varTranslator = $this->getVarTranslator();
58
        $translation   = $varTranslator->createTranslation($this->getVars());
59
        $varTranslator->apply($translation, $spec);
60
61
        $translationVars = $translation->getVarTranslation();
62
        $basePath        = $this->basePath->__invoke();
63
        $serverUrl       = $this->resolveServerUrl($spec);
64
65
        foreach ($nodes as $node) {
66
            if (!($node instanceof DomAttr)) {
67
                throw new RuntimeException('Expected DOMAttr for spec ' . print_r($spec, true));
68
            }
69
70
            $nodeValue = $node->nodeValue;
71
            $translationVars->translate($nodeValue);
72
            $node->nodeValue = $serverUrl . $this->removeDotSegments($basePath . '/' . ltrim((string) $nodeValue, '/'));
73
        }
74
    }
75
76
    /**
77
     * @param array $spec
78
     * @return string
79
     */
80
    private function resolveServerUrl(array $spec)
81
    {
82
        if (!array_key_exists('serverUrl', $spec)) {
83
            return '';
84
        }
85
        if (true === $spec['serverUrl']) {
86
            return $this->serverUrl->__invoke();
87
        }
88
89
        return (string) $spec['serverUrl'];
90
    }
91
92
    /**
93
     * Removes dots as described in RFC 3986, section 5.2.4
94
     *
95
     * Taken from the PEAR Net_URL2, cos don't want to make a dependency.
96
     *
97
     * @link http://pear.php.net/package/Net_URL2/ PEAR package
98
     * @param string $path a path
99
     * @return string a path
100
     */
101
    private function removeDotSegments($path)
102
    {
103
        $output = '';
104
105
        // Make sure not to be trapped in an infinite loop due to a bug in this
106
        // method
107
        $j = 0;
108
        while ($path && $j++ < 100) {
109
            if (substr($path, 0, 2) === './') {
110
                // Step 2.A
111
                $path = substr($path, 2);
112
            } elseif (substr($path, 0, 3) === '../') {
113
                // Step 2.A
114
                $path = substr($path, 3);
115
            } elseif (substr($path, 0, 3) === '/./' || $path === '/.') {
116
                // Step 2.B
117
                $path = '/' . substr($path, 3);
118
            } elseif (substr($path, 0, 4) === '/../' || $path === '/..') {
119
                // Step 2.C
120
                $path   = '/' . substr($path, 4);
121
                $i      = strrpos($output, '/');
122
                $output = $i === false ? '' : substr($output, 0, $i);
123
            } elseif ($path === '.' || $path === '..') {
124
                // Step 2.D
125
                $path = '';
126
            } else {
127
                // Step 2.E
128
                $i = strpos($path, '/');
129
                if ($i === 0) {
130
                    $i = strpos($path, '/', 1);
131
                }
132
                if ($i === false) {
133
                    $i = strlen($path);
134
                }
135
                $output.= substr($path, 0, $i);
136
                $path = substr($path, $i);
137
            }
138
        }
139
140
        return $output;
141
    }
142
}
143