Passed
Push — master ( 8cf186...255a0a )
by Andreas
24:16
created

midcom_connection   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 232
Duplicated Lines 0 %

Test Coverage

Coverage 67%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 87
c 1
b 0
f 0
dl 0
loc 232
ccs 67
cts 100
cp 0.67
rs 9.28
wmc 39

15 Methods

Rating   Name   Duplication   Size   Complexity  
A set_error() 0 3 1
A get_error_string() 0 3 1
A setup() 0 12 3
A get_error() 0 3 1
A set_loglevel() 0 3 1
A prepare_password() 0 10 3
A verify_password() 0 10 3
A login() 0 20 5
A check_page_exists() 0 12 3
A logout() 0 4 2
A _get() 0 7 2
B _parse_url() 0 29 6
A get_user() 0 6 2
A get_schema_types() 0 10 2
A get_url() 0 16 4
1
<?php
2
/**
3
 * @package midcom
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use midgard\portable\storage\connection;
10
use midgard\portable\api\error\exception as mgd_exception;
11
use midgard\portable\api\mgdobject;
12
13
/**
14
 * Wrapper for Midgard-related functionality
15
 *
16
 * @package midcom
17
 */
18
class midcom_connection
19
{
20
    /**
21
     * @var array
22
     */
23
    private static $_data = [];
24
25
    /**
26
     * DB connection setup routine
27
     *
28
     * @throws Exception We use regular exceptions here, because this might run before things are properly set up
29
     */
30
    public static function setup(string $basedir) : bool
31
    {
32
        if (file_exists($basedir . 'config/midgard-portable.inc.php')) {
33
            include $basedir . 'config/midgard-portable.inc.php';
34
            return midgard_connection::get_instance()->is_connected();
35
        }
36
        if (file_exists($basedir . 'config/midgard-portable-default.inc.php')) {
37
            include $basedir . 'config/midgard-portable-default.inc.php';
38
            //default config has in-memory db, so all the tables may be missing
39
            return midgard_storage::class_storage_exists('midgard_user');
40
        }
41
        throw new Exception("Could not connect to database, configuration file not found");
42
    }
43
44
    /**
45
     * Set Midgard log level
46
     *
47
     * @param string $loglevel Midgard log level
48
     */
49
    static function set_loglevel($loglevel) : bool
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
50
    {
51
        return midgard_connection::get_instance()->set_loglevel($loglevel);
52
    }
53
54
    /**
55
     * Set Midgard error code
56
     */
57 18
    public static function set_error(int $errorcode)
58
    {
59 18
        midgard_connection::get_instance()->set_error($errorcode);
60 18
    }
61
62
    /**
63
     * Get Midgard error code
64
     */
65 35
    public static function get_error() : int
66
    {
67 35
        return midgard_connection::get_instance()->get_error();
68
    }
69
70
    /**
71
     * Get Midgard error message
72
     */
73 50
    public static function get_error_string() : string
74
    {
75 50
        return midgard_connection::get_instance()->get_error_string();
76
    }
77
78
    /**
79
     * Perform a login against the midgard backend
80
     */
81 62
    public static function login(string $username, string $password, bool $trusted = false) : ?midgard_user
82
    {
83
        $login_tokens = [
84 62
            'login' => $username,
85 62
            'authtype' => midcom::get()->config->get('auth_type'),
86
        ];
87
88
        try {
89 62
            $user = new midgard_user($login_tokens);
90
        } catch (mgd_exception $e) {
91
            return null;
92
        }
93 62
        if (!$trusted && !self::verify_password($password, $user->password)) {
94
            return null;
95
        }
96
97 62
        if (!$user->login()) {
98
            return null;
99
        }
100 62
        return $user;
101
    }
102
103 67
    public static function verify_password(string $password, string $hash) : bool
104
    {
105 67
        if (midcom::get()->config->get('auth_type') == 'Legacy') {
106 67
            return password_verify($password, $hash);
107
        }
108
        if (midcom::get()->config->get('auth_type') == 'SHA256') {
109
            $password = hash('sha256', $password);
110
        }
111
112
        return $password === $hash;
113
    }
114
115 85
    public static function prepare_password(string $password)
116
    {
117 85
        if (midcom::get()->config->get('auth_type') == 'Legacy') {
118 85
            return password_hash($password, PASSWORD_DEFAULT);
119
        }
120
        if (midcom::get()->config->get('auth_type') == 'SHA256') {
121
            return hash('sha256', $password);
122
        }
123
124
        return $password;
125
    }
126
127
    /**
128
     * Get current Midgard user ID
129
     */
130 52
    public static function get_user() : int
131
    {
132 52
        if ($user = midgard_connection::get_instance()->get_user()) {
133 30
            return $user->get_person()->id;
134
        }
135 22
        return 0;
136
    }
137
138
    /**
139
     * Logout the current user, if any
140
     */
141 1
    public static function logout()
142
    {
143 1
        if ($user = midgard_connection::get_instance()->get_user()) {
144 1
            $user->logout();
145
        }
146 1
    }
147
148 355
    private static function _get(string $key)
149
    {
150 355
        if (isset(self::$_data[$key])) {
151 355
            return self::$_data[$key];
152
        }
153
154
        return null;
155
    }
156
157
    /**
158
     * Lists all available MgdSchema types
159
     */
160 6
    public static function get_schema_types() : array
161
    {
162 6
        if (!isset(self::$_data['schema_types'])) {
163
            $classnames = connection::get_em()->getConfiguration()->getMetadataDriverImpl()->getAllClassNames();
164
165
            self::$_data['schema_types'] = array_filter($classnames, function($input) {
166
                return is_subclass_of($input, mgdobject::class);
167
            });
168
        }
169 6
        return self::$_data['schema_types'];
170
    }
171
172
    /**
173
     * Get various pieces of information extracted from the URL
174
     *
175
     * @return mixed The data for the requested key or null if it doesn't exist
176
     */
177 355
    public static function get_url(string $key)
178
    {
179 355
        static $parsed = false;
180 355
        if (!$parsed) {
181
            $self = defined('OPENPSA2_PREFIX') ? OPENPSA2_PREFIX : '/';
182
183
            // we're only interested in the path, so use a dummy domain for simplicity's sake
184
            $url_components = parse_url("https://openpsa2.org{$_SERVER['REQUEST_URI']}");
185
            if ($self !== '/') {
186
                $url_components['path'] = preg_replace('|^' . $self . '|', '/', $url_components['path']);
187
            }
188
            self::_parse_url($url_components['path'], $self, substr($self, 0, -1));
189
            $parsed = true;
190
        }
191
192 355
        return self::_get($key);
193
    }
194
195
    /**
196
     * Enables themes to have subdirectories (which have a similar effect to mgd1 pages)
197
     *
198
     * @param string $uri The request path
199
     * @param string $self The instance's root URL
200
     * @param string $prefix The root URL's prefix, if any (corresponds to mgd1 host)
201
     */
202 1
    private static function _parse_url(string $uri, string $self, string $prefix)
203
    {
204 1
        $uri = preg_replace('/\/[\/]+/i', '/', $uri);
205 1
        $path_parts = explode('/', $uri);
206 1
        $page_style = '';
207 1
        $path = $self;
208
209 1
        self::$_data['argv'] = [];
210 1
        $args_started = false;
211 1
        foreach ($path_parts as $part) {
212 1
            if ($part === '') {
213 1
                continue;
214
            }
215 1
            if (    midcom::get()->config->get('theme')
216 1
                 && !$args_started
217 1
                 && self::check_page_exists($part)) {
218
                $page_style .= '/' . $part;
219
                $self .= $part . '/';
220
            } else {
221 1
                self::$_data['argv'][] = $part;
222 1
                $path .= $part . '/';
223 1
                $args_started = true;
224
            }
225
        }
226
227 1
        self::$_data['page_style'] = $page_style;
228 1
        self::$_data['uri'] = $path;
229 1
        self::$_data['self'] = $self;
230 1
        self::$_data['prefix'] = $prefix;
231 1
    }
232
233
234
    /**
235
     * Iterate through possible page directories in style-tree
236
     * and check if the page exists (as a folder).
237
     */
238 1
    private static function check_page_exists(string $page_name) : bool
239
    {
240 1
        $prefix = midcom::get()->getProjectDir() . '/var/themes/';
241 1
        $path_array = explode('/', midcom::get()->config->get('theme'));
0 ignored issues
show
Bug introduced by
It seems like midcom::get()->config->get('theme') can also be of type null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

241
        $path_array = explode('/', /** @scrutinizer ignore-type */ midcom::get()->config->get('theme'));
Loading history...
242 1
        while (!empty($path_array)) {
243 1
            $theme_path = implode('/', $path_array);
244 1
            if (is_dir($prefix . $theme_path . '/style/' . $page_name)) {
245
                return true;
246
            }
247 1
            array_pop($path_array);
248
        }
249 1
        return false;
250
    }
251
}
252