ApiUrl::resolveSource()   C
last analyzed

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
 * This software package is licensed under `AGPL, Commercial` license[s].
5
 *
6
 * @package maslosoft/zamm
7
 * @license AGPL, Commercial
8
 *
9
 * @copyright Copyright (c) Peter Maselkowski <[email protected]>
10
 * @link https://maslosoft.com/zamm/
11
 */
12
13
namespace Maslosoft\Zamm;
14
15
use Maslosoft\Zamm\Interfaces\SourceAccessorInterface;
16
use Maslosoft\Zamm\Traits\SourceMagic;
17
use UnexpectedValueException;
18
19
/**
20
 * Api Url generator
21
 *
22
 * @author Piotr Maselkowski <pmaselkowski at gmail.com>
23
 */
24
class ApiUrl implements SourceAccessorInterface
25
{
26
27
	use SourceMagic;
28
29
	private static $sources = [];
30
	private $dotName = '';
31
	private $source = '';
0 ignored issues
show
Unused Code introduced by
The property $source is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
32
	private $className = '';
33
34
	public function __construct($className = null, $text = '')
35
	{
36
		$this->dotName = str_replace('\\', '.', $className);
37
38
		$this->className = $className;
39
	}
40
41
	/**
42
	 * Set root url of current project API. This can be relative or absolute url.
43
	 *
44
	 * Set url for many projects with namespaces - this allows cross-linking different projects:
45
	 *
46
	 * ```
47
	 * ApiUrl::setRoot([
48
	 * 		'/mangan/api' => 'Maslosoft\\Mangan\\'
49
	 * 		'/addendum/api' => 'Maslosoft\\Addendum\\'
50
	 * ]);
51
	 * ```
52
	 *
53
	 * Could also be used for one project, but might result in wrong url if
54
	 * used on classes outside of project:
55
	 *
56
	 * ```
57
	 * ApiUrl::setRoot('/mangan/api');
58
	 * ```
59
	 *
60
	 *
61
	 * @param string|string[] $apiUrl
62
	 */
63
	public static function setRoot($apiUrl)
64
	{
65
		if (is_string($apiUrl))
66
		{
67
			self::$sources[rtrim($apiUrl, '/')] = [];
68
		}
69
		elseif (is_array($apiUrl))
70
		{
71
			$urls = [];
72
			foreach ($apiUrl as $url => $ns)
73
			{
74
				if (!is_array($ns))
75
				{
76
					$ns = [$ns];
77
				}
78
				foreach ($ns as $nsIndex => $oneNs)
79
				{
80
					$ns[$nsIndex] = self::normalize($oneNs);
81
				}
82
				$urls[rtrim($url, '/')] = $ns;
83
			}
84
			self::$sources = array_merge(self::$sources, $urls);
85
		}
86
		else
87
		{
88
			throw new UnexpectedValueException(sprintf('Expected `apiUrl` to be string or array, got `%s`', gettype($apiUrl)));
89
		}
90
	}
91
92
	public function method($name)
93
	{
94
		// https://df.home/zamm/api/class-Maslosoft.Zamm.Decorators.AbstractDecorator.html#_decorate
95
		return sprintf('%s/class-%s.html#_%s', $this->resolveSource($this->resolveMethodClass($name)), $this->dotName, $name);
96
	}
97
98
	public function property($name)
99
	{
100
		// https://df.home/zamm/api/class-Maslosoft.Zamm.Zamm.html#$decorators
101
		return sprintf('%s/class-%s.html#$%s', $this->resolveSource($this->resolvePropertyClass($name)), $this->dotName, $name);
102
	}
103
104
	public static function __callStatic($name, $arguments)
105
	{
106
107
	}
108
109
	public function __toString()
110
	{
111
		return sprintf('%s/class-%s.html', $this->resolveSource($this->className), $this->dotName);
112
	}
113
114
	/**
115
	 * TODO: Resolve real class where property was defined
116
	 * @param string $name Property name
117
	 * @return string
118
	 */
119
	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...
120
	{
121
		return $this->className;
122
	}
123
124
	/**
125
	 * TODO: Resolve real class where method was defined
126
	 * @param string $name Method name
127
	 * @return string
128
	 */
129
	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...
130
	{
131
		return $this->className;
132
	}
133
134
	private function resolveSource($className)
135
	{
136
		// Many sources found, search for proper api source
137
		$url = '';
138
		$source = '';
139
		$search = self::normalize($className);
140
		foreach (self::$sources as $url => $nss)
141
		{
142
			foreach ($nss as $ns)
143
			{
144
				if (empty($ns) || !is_string($url))
145
				{
146
					continue;
147
				}
148
				$pos = strpos($search, $ns);
149
150
				if ($pos === false)
151
				{
152
					continue;
153
				}
154
				if ($pos === 0)
155
				{
156
					$source = $url;
157
					break;
158
				}
159
			}
160
		}
161
162
		// Last resort url assigning
163
		if (empty($source))
164
		{
165
			$source = $url;
166
		}
167
		return $source;
168
	}
169
170
	/**
171
	 * Ensure that name starts and ends with slash
172
	 * @param string $name
173
	 * @return string
174
	 */
175
	private static function normalize($name)
176
	{
177
		return sprintf('\\%s\\', trim($name, '\\'));
178
	}
179
180
}
181