Passed
Push — master ( 388458...bd6289 )
by Andreas
17:20
created

midcom_helper_misc::parse_config()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 7
ccs 4
cts 5
cp 0.8
crap 2.032
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package midcom.helper
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use Cocur\Slugify\Slugify;
10
11
/**
12
 * Miscellaneous helper functions
13
 *
14
 * @package midcom.helper
15
 */
16
class midcom_helper_misc
17
{
18
    /**
19
     * @param integer $length
20
     * @param string $characters
21
     * @throws InvalidArgumentException
22
     */
23 13
    public static function random_string($length, $characters) : string
24
    {
25 13
        if ($length < 1) {
26
            throw new InvalidArgumentException('invalid length');
27
        }
28 13
        $size = strlen($characters) - 1;
29 13
        if ($size < 1) {
30
            throw new InvalidArgumentException('invalid characters');
31
        }
32 13
        $return = '';
33 13
        for ($i = 0; $i < $length; $i++) {
34 13
            $return .= $characters[random_int(0, $size)];
35
        }
36 13
        return $return;
37
    }
38
39
    /**
40
     * @param string $input
41
     */
42 27
    public static function urlize($input) : string
43
    {
44 27
        $slugify = new Slugify;
45 27
        return $slugify->slugify($input);
46
    }
47
48
    /**
49
     * Turn midcom config files into PHP arrays
50
     *
51
     * @param string $data The data to parse
52
     * @throws midcom_error
53
     */
54 513
    public static function parse_config($data) : array
55
    {
56 513
        $data = eval("return [{$data}\n];");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
57 513
        if ($data === false) {
58
            throw new midcom_error("Failed to parse config data, see above for PHP errors.");
59
        }
60 513
        return $data;
61
    }
62
63
    /**
64
     * This helper function searches for a snippet either in the Filesystem
65
     * or in the database and returns its content or code-field, respectively.
66
     *
67
     * Prefix the snippet Path with 'file:' for retrieval of a file relative to
68
     * MIDCOM_ROOT; omit it to get the code field of a Snippet.
69
     *
70
     * Any error (files not found) will return null. If you want to trigger an error,
71
     * look for midcom_helper_misc::get_snippet_content.
72
     *
73
     * @param string $path  The URL to the snippet.
74
     * @return string       The content of the snippet/file.
75
     */
76 513
    public static function get_snippet_content_graceful($path)
77
    {
78 513
        static $cached_snippets = [];
79
80 513
        if (!array_key_exists($path, $cached_snippets)) {
81 63
            if (substr($path, 0, 5) == 'file:') {
82 46
                $cached_snippets[$path] = self::load_from_file($path);
83 22
            } elseif (substr($path, 0, 5) == 'conf:') {
84 22
                $cached_snippets[$path] = self::load(midcom::get()->config->get('midcom_config_basedir') . '/midcom' . substr($path, 5));
85
            } else {
86 17
                $cached_snippets[$path] = self::load_from_snippet($path);
87
            }
88
        }
89
90 513
        return $cached_snippets[$path];
91
    }
92
93 17
    private static function load_from_snippet(string $path)
94
    {
95 17
        $snippet = new midgard_snippet();
96 17
        if (!$snippet->get_by_path($path)) {
97 17
            return null;
98
        }
99
        if (isset(midcom::get()->cache->content)) {
100
            midcom::get()->cache->content->register($snippet->guid);
101
        }
102
        return $snippet->code;
103
    }
104
105 46
    private static function load_from_file(string $path)
106
    {
107 46
        $filename = MIDCOM_ROOT . substr($path, 5);
108 46
        if (!file_exists($filename)) {
109
            // try in src
110 2
            $filename = preg_replace('/\/lib\/?$/', '/src', MIDCOM_ROOT) . substr($path, 5);
111 2
            if (!file_exists($filename)) {
112
                //If we can't find the file in-tree, we look for out-of-tree components before giving up
113
                $filename = substr($path, 6);
114
                if (preg_match('|.+?/.+?/.+?/|', $filename)) {
115
                    $component_name = preg_replace('|(.+?)/(.+?)/(.+?)/.+|', '$1.$2.$3', $filename);
116
                    if (midcom::get()->componentloader->is_installed($component_name)) {
117
                        $filename = substr($filename, strlen($component_name));
118
                        $filename = midcom::get()->componentloader->path_to_snippetpath($component_name) . $filename;
119
                    }
120
                }
121
            }
122
        }
123 46
        return self::load($filename);
124
    }
125
126 63
    private static function load(string $filename)
127
    {
128 63
        if (!file_exists($filename)) {
129 22
            return null;
130
        }
131 46
        return file_get_contents($filename);
132
    }
133
134
    /**
135
     * This helper function searches for a snippet either in the Filesystem
136
     * or in the database and returns its content or code-field, respectively.
137
     *
138
     * Prefix the snippet Path with 'file:' for retrieval of a file relative to
139
     * MIDCOM_ROOT; omit it to get the code field of a Snippet.
140
     *
141
     * Any error (files not found) will raise a MidCOM Error. If you want a more
142
     * graceful behavior, look for midcom_helper_misc::get_snippet_content_graceful
143
     *
144
     * @param string $path    The URL to the snippet.
145
     */
146 247
    public static function get_snippet_content($path) : string
147
    {
148 247
        $data = self::get_snippet_content_graceful($path);
149 247
        if ($data === null) {
0 ignored issues
show
introduced by
The condition $data === null is always false.
Loading history...
150
            throw new midcom_error("Could not load the contents of the snippet {$path}: Snippet does not exist.");
151
        }
152 247
        return $data;
153
    }
154
155
    /**
156
     * Include a theme element
157
     */
158 20
    public static function include_element($name) : string
159
    {
160 20
        if (is_array($name)) {
161 20
            $element = $name[1];
162
        } else {
163
            $element = $name;
164
        }
165
166 20
        switch ($element) {
167 20
            case 'title':
168 10
                return midcom::get()->config->get('midcom_site_title');
169 19
            case 'content':
170 19
                return '<?php midcom_core_context::get()->show(); ?>';
171
            default:
172 9
                $value = self::get_element_content($element);
173
174 9
                if (empty($value)) {
175
                    return '';
176
                }
177 9
                return preg_replace_callback("/<\\(([a-zA-Z0-9 _-]+)\\)>/", [midcom_helper_misc::class, 'include_element'], $value);
178
        }
179
    }
180
181
    /**
182
     * Find MIME type image for a document
183
     *
184
     * Used in midcom.helper.imagepopup, midgard.admin.asgard and org.openpsa.documents.
185
     *
186
     * @param string $mimetype  Document MIME type
187
     * @return string    Path to the icon
188
     */
189
    public static function get_mime_icon($mimetype) : string
190
    {
191
        $mime_fspath = MIDCOM_STATIC_ROOT . '/stock-icons/mime';
192
        $mime_urlpath = MIDCOM_STATIC_URL . '/stock-icons/mime';
193
        $mimetype_filename = str_replace('/', '-', $mimetype);
194
        if (!is_readable($mime_fspath)) {
195
            debug_add("Couldn't read directory {$mime_fspath}", MIDCOM_LOG_WARN);
196
        }
197
198
        $check_files = [];
199
        switch ($mimetype_filename) {
200
            case 'application-x-zip-compressed':
201
                $check_files[] = "gnome-application-zip.png";
202
                break;
203
            default:
204
                $check_files[] = "{$mimetype_filename}.png";
205
                $check_files[] = "gnome-{$mimetype_filename}.png";
206
                break;
207
        }
208
209
        // Return first match
210
        foreach ($check_files as $filename) {
211
            if (is_readable("{$mime_fspath}/{$filename}")) {
212
                return "{$mime_urlpath}/{$filename}";
213
            }
214
        }
215
        // Default icon if there is none for the MIME type
216
        return $mime_urlpath . '/gnome-unknown.png';
217
    }
218
219
    /**
220
     * Pretty print file sizes
221
     *
222
     * @param int $size  File size in bytes
223
     */
224 7
    public static function filesize_to_string($size) : string
225
    {
226 7
        if ($size >= 1048576) {
227
            // More than a meg
228
            return sprintf("%01.1f", $size / 1048576) . " MB";
229
        }
230 7
        if ($size >= 1024) {
231
            // More than a kilo
232
            return sprintf("%01.1f", $size / 1024) . " KB";
233
        }
234 7
        return $size . " Bytes";
235
    }
236
237
    /**
238
     * Fix newline etc encoding issues in serialized data
239
     *
240
     * @param string $data The data to fix.
241
     * @return string $data with serializations fixed.
242
     */
243
    public static function fix_serialization($data)
244
    {
245
        //Skip on empty data
246
        if (empty($data)) {
247
            return $data;
248
        }
249
250
        $preg='/s:([0-9]+):"(.*?)";/ms';
251
        preg_match_all($preg, $data, $matches);
252
        $cache = [];
253
254
        foreach ($matches[0] as $k => $origFullStr) {
255
            $origLen = $matches[1][$k];
256
            $origStr = $matches[2][$k];
257
            $newLen = strlen($origStr);
258
            if ($newLen != $origLen) {
259
                $newFullStr = "s:$newLen:\"$origStr\";";
260
                //For performance we cache information on which strings have already been replaced
261
                if (!array_key_exists($origFullStr, $cache)) {
262
                    $data = str_replace($origFullStr, $newFullStr, $data);
263
                    $cache[$origFullStr] = true;
264
                }
265
            }
266
        }
267
268
        return $data;
269
    }
270
271
    /**
272
     * Returns the first instance of a given component on the site.
273
     *
274
     * @param string $component The component name
275
     * @return array NAP array of the first component instance found
276
     */
277 6
    public static function find_node_by_component($component)
278
    {
279 6
        static $cache = [];
280
281 6
        if (!array_key_exists($component, $cache)) {
282 2
            $cache[$component] = null;
283
284 2
            $nap = new midcom_helper_nav;
285 2
            $node_id = $nap->get_root_node();
286 2
            $root_node = $nap->get_node($node_id);
287
288 2
            if ($root_node[MIDCOM_NAV_COMPONENT] == $component) {
289
                $cache[$component] = $root_node;
290
            } else {
291 2
                $qb = midcom_db_topic::new_query_builder();
292 2
                $qb->add_constraint('component', '=', $component);
293 2
                $qb->add_constraint('name', '<>', '');
294 2
                $qb->add_constraint('up', 'INTREE', $node_id);
295 2
                $qb->set_limit(1);
296 2
                $topics = $qb->execute();
297
298 2
                if (count($topics) === 1) {
299 1
                    $cache[$component] = $nap->get_node($topics[0]->id);
300
                }
301
            }
302
        }
303
304 6
        return $cache[$component];
305
    }
306
307
    /**
308
     * Get the content of the element by the passed element name.
309
     * Tries to resolve path according to theme-name & page
310
     *
311
     * @param string $element_name
312
     */
313 202
    public static function get_element_content($element_name)
314
    {
315 202
        $theme = midcom::get()->config->get('theme');
316 202
        $path_array = explode('/', $theme);
317
318
        //get the page if there is one
319 202
        $page = midcom_connection::get_url('page_style');
320 202
        $substyle = midcom_core_context::get()->get_key(MIDCOM_CONTEXT_SUBSTYLE);
321
        //check if we have elements for the sub-styles
322 202
        while (!empty($path_array)) {
323 202
            $theme_path = implode('/', $path_array);
324 202
            $candidates = [];
325 202
            if ($substyle) {
326 31
                $candidates[] = '/' . $substyle . '/' . $element_name;
327
            }
328 202
            if ($page) {
329
                $candidates[] = $page . '/' . $element_name;
330
            }
331 202
            $candidates[] = '/' . $element_name;
332
333 202
            foreach ($candidates as $candidate) {
334 202
                $filename = OPENPSA2_THEME_ROOT . $theme_path . '/style' . $candidate . '.php';
335 202
                if (file_exists($filename)) {
336 10
                    return file_get_contents($filename);
337
                }
338
            }
339
340
            //remove last theme part
341 202
            array_pop($path_array);
342
        }
343
344 202
        return false;
345
    }
346
}
347