Completed
Push — master ( 81252c...2689ec )
by Joschi
03:10
created

Service::useAutoConnect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 4
Bugs 1 Features 0
Metric Value
dl 0
loc 7
ccs 0
cts 5
cp 0
rs 9.4285
c 4
b 1
f 0
cc 2
eloc 4
nc 2
nop 1
crap 6
1
<?php
2
3
/**
4
 * apparat-object
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Object
8
 * @subpackage  Apparat\Object\Domain
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT	The MIT License (MIT)
0 ignored issues
show
Coding Style introduced by
Spaces must be used for alignment; tabs are not allowed
Loading history...
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Object\Domain\Repository;
38
39
use Apparat\Object\Domain\Model\Object\ManagerInterface;
40
use Apparat\Object\Domain\Model\Path\ApparatUrl;
41
use Apparat\Object\Domain\Model\Path\ObjectUrl;
42
use Apparat\Object\Domain\Model\Path\Url;
43
use Apparat\Object\Module;
44
45
/**
46
 * Repository register
47
 *
48
 * @package Apparat\Object
49
 * @subpackage Apparat\Object\Domain
50
 */
51
class Service
52
{
53
    /**
54
     * Registered repositories
55
     *
56
     * @var array
57
     */
58
    protected $registry = [];
59
    /**
60
     * Repository auto-connector service
61
     *
62
     * @var AutoConnectorInterface
63
     */
64
    protected $autoConnector = null;
65
    /**
66
     * Adapter strategy factory
67
     *
68
     * @var AdapterStrategyFactoryInterface
69
     */
70
    protected $adapterStrategyFactory = null;
71
    /**
72
     * Object manager
73
     *
74
     * @var ManagerInterface
75
     */
76
    protected $objectManager = null;
77
    /**
78
     * Auto-connect to repositories
79
     *
80
     * @var bool
81
     */
82
    protected $autoConnectEnabled = true;
83
84
    /*******************************************************************************
85
     * PUBLIC METHODS
86
     *******************************************************************************/
87
88
    /**
89
     * Repository service constructor
90
     *
91
     * @param AutoConnectorInterface $autoConnector Auto-connector
92
     * @param AdapterStrategyFactoryInterface $adapterStrategyFactory Adapter strategy factory
93
     * @param ManagerInterface $objectManager Object manager
94
     */
95
    public function __construct(
96
        AutoConnectorInterface $autoConnector,
97
        AdapterStrategyFactoryInterface $adapterStrategyFactory,
98
        ManagerInterface $objectManager
99
    ) {
100
        $this->autoConnector = $autoConnector;
101
        $this->adapterStrategyFactory = $adapterStrategyFactory;
102
        $this->objectManager = $objectManager;
103
    }
104
105
    /**
106
     * Pre-register a repository
107
     *
108
     * The purpose of repository pre-registration is to provide custom arguments (like a base
109
     * directory or basic authentication credentials.
110
     * The repository URL may be local or remote, relative or absolute, with Apparat or HTTP scheme.
111
     *
112
     * @param string|Url $url Repository URL
113
     * @param RepositoryInterface $repository Repository
114
     */
115 6
    public function register($url, RepositoryInterface $repository)
116
    {
117
        // Repository registration
118 6
        $repositoryUrl = self::normalizeRepositoryUrl($url);
119 6
        $this->registry[$repositoryUrl] = $repository;
120 6
    }
121
122
    /**
123
     * Return an object repository by URL
124
     *
125
     * If a repository URL hasn't been pre-registered, the method tries to perform an adhoc registration
126
     * based on the URL given.
127
     * The repository URL may be local or remote, relative or absolute, with Apparat or HTTP scheme.
128
     *
129
     * @param string|Url $url Repository URL
130
     * @return \Apparat\Object\Domain\Repository\Repository Object repository
131
     * @throws InvalidArgumentException If the repository URL is invalid
132
     * @throws InvalidArgumentException If the repository URL is unknown
133
     */
134 9
    public function get($url)
135
    {
136 9
        $url = self::normalizeRepositoryUrl($url);
137
138
        // If the repository URL is unknown
139 8
        if (!self::connected($url)) {
140 2
            throw new InvalidArgumentException(
141 2
                sprintf('Unknown repository URL "%s"', $url),
142
                InvalidArgumentException::UNKNOWN_REPOSITORY_URL
143 2
            );
144
        }
145
146
        // Return the repository instance
147 6
        return $this->registry[$url];
148
    }
149
150
    /**
151
     * Test whether a repository URL is registered
152
     *
153
     * @param string $url Repository URL
154
     * @return bool Repository URL is registered
155
     */
156 3
    public function isRegistered($url)
157
    {
158 3
        $url = self::normalizeRepositoryUrl($url);
159 3
        return array_key_exists($url, $this->registry) || self::connected($url);
160
    }
161
162
    /**
163
     * Return the adapter strategy factory
164
     *
165
     * @return AdapterStrategyFactoryInterface Adapter strategy factory
166
     */
167 10
    public function getAdapterStrategyFactory()
168
    {
169 10
        return $this->adapterStrategyFactory;
170
    }
171
172
    /**
173
     * Return the object manager
174
     *
175
     * @return ManagerInterface Object manager
176
     */
177 2
    public function getObjectManager()
178
    {
179 2
        return $this->objectManager;
180
    }
181
182
    /**
183
     * Normalize a repository URL
184
     *
185
     * @param string|Url $url Repository URL
186
     * @return string Normalized repository URL
187
     * @throws InvalidArgumentException If the repository URL is invalid
188
     */
189 17
    public static function normalizeRepositoryUrl($url)
190
    {
191
        // If it's an apparat URL
192 17
        if ($url instanceof ApparatUrl) {
193
            $url = $url->getNormalizedRepositoryUrl();
194
195
            // Else: If it's an object URL
196 17
        } elseif ($url instanceof ObjectUrl) {
197
            $url = $url->getRepositoryUrl();
198
199
            // Else: If it's a simple URL
200 17
        } elseif ($url instanceof Url) {
201
            $url = $url->getPath();
202
203
            // Else: If it's an empty URL
204 17
        } elseif ($url === null) {
205 1
            return '';
206
        }
207
208
        // If the URL is a string
209 16
        if (is_string($url)) {
210
211
            // Strip the leading apparat base URL
212 16
            $apparatBaseUrl = getenv('APPARAT_BASE_URL');
213 16
            if (strpos($url, $apparatBaseUrl) === 0) {
214
                $url = strval(substr($url, strlen($apparatBaseUrl)));
215
            }
216
217
            // Ensure this is a bare URL (without query and fragment)
218 16
            if (Module::isAbsoluteBareUrl($apparatBaseUrl.$url)) {
219 15
                return ltrim($url, '/');
220
            }
221
        }
222
223
        // The URL is invalid, throw an error
224
        throw new InvalidArgumentException(
225
            sprintf('Invalid repository URL "%s"', $url),
226
            InvalidArgumentException::INVALID_REPOSITORY_URL
227
        );
228
    }
229
230
    /**
231
     * Enable repository auto-connections
232
     *
233
     * If the method is called without any arguments it will just return the current auto-connection state.
234
     *
235
     * @param null|boolean $autoConnect Enable / disable auto-connections
236
     * @return bool Status of repository auto-connection
237
     */
238
    public function useAutoConnect($autoConnect = null)
239
    {
240
        if ($autoConnect !== null) {
241
            $this->autoConnectEnabled = (boolean)$autoConnect;
242
        }
243
        return $this->autoConnectEnabled;
244
    }
245
246
    /*******************************************************************************
247
     * PRIVATE METHODS
248
     *******************************************************************************/
249
250
    /**
251
     * Test whether a repository URL registered or can be auto-connected
252
     *
253
     * @param string $url Repository URL
254
     * @return bool Repository is connected
255
     */
256 9
    protected function connected($url)
257
    {
258
        // If the given repository URL is already registered: Success
259 9
        if (!empty($this->registry[$url])) {
260 6
            return true;
261
        }
262
263
        // If auto-connect is enabled and the service is properly configured: Try to auto-connect the repository
264 3
        return $this->autoConnectEnabled && $this->autoConnector->connect($url);
265
    }
266
}
267