Issues (806)

lib/midcom/connection.php (2 issues)

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
    private static array $_data = [];
21
22
    /**
23
     * DB connection setup routine
24
     *
25
     * @throws Exception We use regular exceptions here, because this might run before things are properly set up
26
     */
27
    public static function setup(string $basedir) : bool
28
    {
29
        if (file_exists($basedir . 'config/midgard-portable.inc.php')) {
30
            include $basedir . 'config/midgard-portable.inc.php';
31
            return midgard_connection::get_instance()->is_connected();
32
        }
33
        if (file_exists($basedir . 'config/midgard-portable-default.inc.php')) {
34
            include $basedir . 'config/midgard-portable-default.inc.php';
35
            //default config has in-memory db, so all the tables may be missing
36
            return midgard_storage::class_storage_exists('midgard_user');
37
        }
38
        throw new Exception("Could not connect to database, configuration file not found");
39
    }
40
41
    /**
42
     * Set Midgard log level
43
     *
44
     * @param string $loglevel Midgard log level
45
     */
46
    static function set_loglevel($loglevel) : bool
0 ignored issues
show
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...
47
    {
48
        return midgard_connection::get_instance()->set_loglevel($loglevel);
49
    }
50
51
    /**
52
     * Set Midgard error code
53
     */
54 17
    public static function set_error(int $errorcode)
55
    {
56 17
        midgard_connection::get_instance()->set_error($errorcode);
57
    }
58
59
    /**
60
     * Get Midgard error code
61
     */
62 41
    public static function get_error() : int
63
    {
64 41
        return midgard_connection::get_instance()->get_error();
65
    }
66
67
    /**
68
     * Get Midgard error message
69
     */
70 57
    public static function get_error_string() : string
71
    {
72 57
        return midgard_connection::get_instance()->get_error_string();
73
    }
74
75
    /**
76
     * Perform a login against the midgard backend
77
     */
78 65
    public static function login(string $username, string $password, bool $trusted = false) : ?midgard_user
79
    {
80 65
        $login_tokens = [
81 65
            'login' => $username,
82 65
            'authtype' => midcom::get()->config->get('auth_type'),
83 65
        ];
84
85
        try {
86 65
            $user = new midgard_user($login_tokens);
87
        } catch (mgd_exception) {
88
            return null;
89
        }
90 65
        if (!$trusted && !self::verify_password($password, $user->password)) {
91
            return null;
92
        }
93
94 65
        $user->login();
95 65
        return $user;
96
    }
97
98 72
    public static function verify_password(string $password, string $hash) : bool
99
    {
100 72
        if (midcom::get()->config->get('auth_type') == 'Legacy') {
101 72
            return password_verify($password, $hash);
102
        }
103
        if (midcom::get()->config->get('auth_type') == 'SHA256') {
104
            $password = hash('sha256', $password);
105
        }
106
107
        return $password === $hash;
108
    }
109
110 90
    public static function prepare_password(string $password) : string
111
    {
112 90
        if (midcom::get()->config->get('auth_type') == 'Legacy') {
113 90
            return password_hash($password, PASSWORD_DEFAULT);
114
        }
115
        if (midcom::get()->config->get('auth_type') == 'SHA256') {
116
            return hash('sha256', $password);
117
        }
118
119
        return $password;
120
    }
121
122
    /**
123
     * Get current Midgard user ID
124
     */
125 62
    public static function get_user() : int
126
    {
127 62
        if ($user = midgard_connection::get_instance()->get_user()) {
128 34
            return $user->get_person()->id;
129
        }
130 28
        return 0;
131
    }
132
133
    /**
134
     * Logout the current user, if any
135
     */
136 1
    public static function logout()
137
    {
138 1
        if ($user = midgard_connection::get_instance()->get_user()) {
139 1
            $user->logout();
140
        }
141
    }
142
143 365
    private static function _get(string $key)
144
    {
145 365
        return self::$_data[$key] ?? null;
146
    }
147
148
    /**
149
     * Lists all available MgdSchema types
150
     */
151 6
    public static function get_schema_types() : array
152
    {
153 6
        if (!isset(self::$_data['schema_types'])) {
154
            $classnames = connection::get_em()->getConfiguration()->getMetadataDriverImpl()->getAllClassNames();
155
156
            self::$_data['schema_types'] = array_filter($classnames, function(string $input) {
157
                return is_subclass_of($input, mgdobject::class);
158
            });
159
        }
160 6
        return self::$_data['schema_types'];
161
    }
162
163
    /**
164
     * Get various pieces of information extracted from the URL
165
     *
166
     * @return mixed The data for the requested key or null if it doesn't exist
167
     */
168 365
    public static function get_url(string $key)
169
    {
170 365
        static $parsed = false;
171 365
        if (!$parsed) {
172
            $self = defined('OPENPSA2_PREFIX') ? OPENPSA2_PREFIX : '/';
173
174
            // we're only interested in the path, so use a dummy domain for simplicity's sake
175
            $url_path = (string) parse_url("https://openpsa2.org{$_SERVER['REQUEST_URI']}", PHP_URL_PATH);
176
            if ($self !== '/') {
177
                $url_path = preg_replace('|^' . $self . '|', '/', $url_path);
178
            }
179
            self::_parse_url($url_path, $self, substr($self, 0, -1));
180
            $parsed = true;
181
        }
182
183 365
        return self::_get($key);
184
    }
185
186
    /**
187
     * Enables themes to have subdirectories (which have a similar effect to mgd1 pages)
188
     *
189
     * @param string $uri The request path
190
     * @param string $self The instance's root URL
191
     * @param string $prefix The root URL's prefix, if any (corresponds to mgd1 host)
192
     */
193
    private static function _parse_url(string $uri, string $self, string $prefix)
194
    {
195
        $path_parts = explode('/', $uri);
196
        $page_style = '';
197
        $path = $uri;
198
199
        $args_started = false;
200
        foreach ($path_parts as $part) {
201
            if ($part === '') {
202
                continue;
203
            }
204
            if (    midcom::get()->config->get('theme')
205
                && !$args_started
206
                && self::check_page_exists($part)) {
207
                $page_style .= '/' . $part;
208
                $self .= $part . '/';
209
                $path = substr($path, strlen($part) + 1);
210
            } else {
211
                $args_started = true;
212
            }
213
        }
214
215
        self::$_data['page_style'] = $page_style;
216
        self::$_data['uri'] = $path;
217
        self::$_data['self'] = $self;
218
        self::$_data['prefix'] = $prefix;
219
    }
220
221
    /**
222
     * Iterate through possible page directories in style-tree
223
     * and check if the page exists (as a folder).
224
     */
225
    private static function check_page_exists(string $page_name) : bool
226
    {
227
        $prefix = midcom::get()->getProjectDir() . '/var/themes/';
228
        $path_array = explode('/', midcom::get()->config->get('theme'));
0 ignored issues
show
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

228
        $path_array = explode('/', /** @scrutinizer ignore-type */ midcom::get()->config->get('theme'));
Loading history...
229
        while (!empty($path_array)) {
230
            $theme_path = implode('/', $path_array);
231
            if (is_dir($prefix . $theme_path . '/style/' . $page_name)) {
232
                return true;
233
            }
234
            array_pop($path_array);
235
        }
236
        return false;
237
    }
238
}
239