DirectoryService   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 2
dl 0
loc 111
ccs 0
cts 55
cp 0
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B getDataDirectory() 0 23 6
B normalizeAbsolutePath() 0 43 6
1
<?php
2
3
/**
4
 * admin
5
 *
6
 * @category    Tollwerk
7
 * @package     Tollwerk\Admin
8
 * @subpackage  Tollwerk\Admin\Infrastructure\Service
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2018 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2018 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 Tollwerk\Admin\Infrastructure\Service;
38
39
use Tollwerk\Admin\Domain\Account\AccountInterface;
40
use Tollwerk\Admin\Infrastructure\App;
41
42
/**
43
 * Account directory service
44
 *
45
 * @package Tollwerk\Admin
46
 * @subpackage Tollwerk\Admin\Infrastructure
47
 */
48
class DirectoryService
49
{
50
    /**
51
     * Account
52
     *
53
     * @var AccountInterface
54
     */
55
    protected $account;
56
    /**
57
     * Account base directory
58
     *
59
     * @var string
60
     */
61
    protected $basedir;
62
63
    /**
64
     * Constructor
65
     *
66
     * @param AccountInterface $account Account
67
     */
68
    public function __construct(AccountInterface $account)
69
    {
70
        $this->account = $account;
71
        $this->basedir = rtrim(App::getConfig('general.basedir'), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.
72
            $this->account->getName().DIRECTORY_SEPARATOR;
73
    }
74
75
    /**
76
     * Return the data directory (or a sub directory)
77
     *
78
     * @param string|null $path Optional: Subdirectory
79
     * @param boolean $absolute Return the absolute path
80
     * @return string Data directory
81
     * @throws \RuntimeException If the directory doesn't exist or is invalid
82
     */
83
    public function getDataDirectory($path = null, $absolute = true)
84
    {
85
        $dataDirectory = $dataBaseDirectory = $this->basedir.'data';
86
        if (strlen($path)) {
87
            $dataDirectory .= DIRECTORY_SEPARATOR.trim($path, DIRECTORY_SEPARATOR);
88
        }
89
90
        // Strip all symbolic links etc.
91
        $absDataDirectory = $this->normalizeAbsolutePath($dataDirectory);
92
93
        // If the directory doesn't exist or is otherwise invalid
94
        if (!$absDataDirectory
95
            || !is_dir($absDataDirectory)
96
            || strncmp($dataBaseDirectory, $absDataDirectory, strlen($dataBaseDirectory))
97
        ) {
98
            throw new \RuntimeException(sprintf('Path "%s" doesn\'t exist or is not a valid data directory',
99
                $dataDirectory), 1475929558);
100
        }
101
102
        return $absolute ?
103
            $absDataDirectory :
104
            trim(substr($absDataDirectory, strlen($dataBaseDirectory)), DIRECTORY_SEPARATOR);
105
    }
106
107
    /**
108
     * Normalize an absolute path by stripping (but not resolving) symbolic links and multiple directory separators
109
     *
110
     * @param string $absolutePath Absolute path
111
     * @return string Normalized absolute path
112
     * @throws \RuntimeException If the path is not absolute
113
     * @throws \RuntimeException If there's no parent directory to traverse to
114
     */
115
    protected function normalizeAbsolutePath($absolutePath)
116
    {
117
        // If the path isn't absolute
118
        if (strncmp(DIRECTORY_SEPARATOR, $absolutePath, strlen(DIRECTORY_SEPARATOR))) {
119
            throw new \RuntimeException(sprintf('The path "%s" is not absolute', $absolutePath), 1479636650);
120
        }
121
122
        // Collapse multiple directory separators
123
        $absolutePath = trim($absolutePath, DIRECTORY_SEPARATOR);
124
        $absolutePath = preg_replace('%'.preg_quote(DIRECTORY_SEPARATOR).'+%', DIRECTORY_SEPARATOR, $absolutePath);
125
126
        // Run through all local paths
127
        $normalizedPath = [];
128
        foreach (explode(DIRECTORY_SEPARATOR, $absolutePath) as $localPath) {
129
            switch ($localPath) {
130
                // Skip symlinks to the current directory
131
                case '.':
132
                    break;
133
134
                // Strip parent directory symlinks
135
                case '..':
136
                    // If there's no parent directory to traverse to
137
                    if (!count($normalizedPath)) {
138
                        throw new \RuntimeException(
139
                            sprintf(
140
                                'Cannot traverse to parent directory of "%s"',
141
                                implode(DIRECTORY_SEPARATOR, $normalizedPath)
142
                            ),
143
                            1479636941
144
                        );
145
                    }
146
                    array_pop($normalizedPath);
147
                    break;
148
149
                // Add local path to result
150
                default:
151
                    $normalizedPath[] = $localPath;
152
                    break;
153
            }
154
        }
155
156
        return DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $normalizedPath);
157
    }
158
}
159