Completed
Push — master ( 3be88f...6b71af )
by Peter
06:16
created

ApiUrl::resolveSource()   C

Complexity

Conditions 8
Paths 12

Size

Total Lines 35
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 35
rs 5.3846
cc 8
eloc 17
nc 12
nop 1
1
<?php
2
3
/*
4
 * To change this license header, choose License Headers in Project Properties.
5
 * To change this template file, choose Tools | Templates
6
 * and open the template in the editor.
7
 */
8
9
namespace Maslosoft\Zamm;
10
11
use Maslosoft\Zamm\Interfaces\SourceAccessorInterface;
12
use Maslosoft\Zamm\Traits\SourceMagic;
13
use UnexpectedValueException;
14
15
/**
16
 * Api Url generator
17
 *
18
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
19
 */
20
class ApiUrl implements SourceAccessorInterface
21
{
22
23
	use SourceMagic;
24
25
	private static $sources = [];
26
	private $dotName = '';
27
	private $source = '';
28
	private $className = '';
29
30
	public function __construct($className = null, $text = '')
31
	{
32
		$this->dotName = str_replace('\\', '.', $className);
33
34
		$this->className = $className;
35
	}
36
37
	/**
38
	 * Set root url of current project API. This can be relative or absolute url.
39
	 *
40
	 * Set url for many projects with namespaces - this allows cross-linking different projects:
41
	 *
42
	 * ```
43
	 * ApiUrl::setRoot([
44
	 * 		'/mangan/api' => 'Maslosoft\\Mangan\\'
45
	 * 		'/addendum/api' => 'Maslosoft\\Addendum\\'
46
	 * ]);
47
	 * ```
48
	 *
49
	 * Could also be used for one project, but might result in wrong url if
50
	 * used on classes outside of project:
51
	 *
52
	 * ```
53
	 * ApiUrl::setRoot('/mangan/api);
54
	 * ```
55
	 *
56
	 *
57
	 * @param string $apiUrl
58
	 */
59
	public static function setRoot($apiUrl)
60
	{
61
		if (is_string($apiUrl))
62
		{
63
			self::$sources[rtrim($apiUrl, '/')] = [];
64
		}
65
		elseif (is_array($apiUrl))
66
		{
67
			$urls = [];
68
			foreach ($apiUrl as $url => $ns)
69
			{
70
				if (!is_array($ns))
71
				{
72
					$ns = [$ns];
73
				}
74
				foreach ($ns as $nsIndex => $oneNs)
75
				{
76
					$ns[$nsIndex] = self::normalize($oneNs);
77
				}
78
				$urls[rtrim($url, '/')] = $ns;
79
			}
80
			self::$sources = array_merge(self::$sources, $urls);
81
		}
82
		else
83
		{
84
			throw new UnexpectedValueException(sprintf('Expected `apiUrl` to be string or array, got `%s`', gettype($apiUrl)));
85
		}
86
	}
87
88
	public function method($name)
89
	{
90
		// https://df.home/zamm/api/class-Maslosoft.Zamm.Decorators.AbstractDecorator.html#_decorate
91
		return sprintf('%s/class-%s.html#_%s', $this->resolveSource($this->resolveMethodClass($name)), $this->dotName, $name);
92
	}
93
94
	public function property($name)
95
	{
96
		// https://df.home/zamm/api/class-Maslosoft.Zamm.Zamm.html#$decorators
97
		return sprintf('%s/class-%s.html#$%s', $this->resolveSource($this->resolvePropertyClass($name)), $this->dotName, $name);
98
	}
99
100
	public static function __callStatic($name, $arguments)
101
	{
102
103
	}
104
105
	public function __toString()
106
	{
107
		return sprintf('%s/class-%s.html', $this->resolveSource($this->className), $this->dotName);
108
	}
109
110
	/**
111
	 * TODO: Resolve real class where property was defined
112
	 * @param string $name Property name
113
	 * @return string
114
	 */
115
	private function resolvePropertyClass($name)
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
116
	{
117
		return $this->className;
118
	}
119
120
	/**
121
	 * TODO: Resolve real class where method was defined
122
	 * @param string $name Method name
123
	 * @return string
124
	 */
125
	private function resolveMethodClass($name)
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
126
	{
127
		return $this->className;
128
	}
129
130
	private function resolveSource($className)
131
	{
132
		// Many sources found, search for proper api source
133
		$url = '';
134
		$source = '';
135
		$search = self::normalize($className);
136
		foreach (self::$sources as $url => $nss)
137
		{
138
			foreach ($nss as $ns)
139
			{
140
				if (empty($ns) || !is_string($url))
141
				{
142
					continue;
143
				}
144
				$pos = strpos($search, $ns);
145
146
				if ($pos === false)
147
				{
148
					continue;
149
				}
150
				if ($pos === 0)
151
				{
152
					$source = $url;
153
					break;
154
				}
155
			}
156
		}
157
158
		// Last resort url assigning
159
		if (empty($source))
160
		{
161
			$source = $url;
162
		}
163
		return $source;
164
	}
165
166
	/**
167
	 * Ensure that name starts and ends with slash
168
	 * @param string $name
169
	 * @return string
170
	 */
171
	private static function normalize($name)
172
	{
173
		return sprintf('\\%s\\', trim($name, '\\'));
174
	}
175
176
}
177