Completed
Push — master ( 01ca5d...148252 )
by Andreas
17:12
created

midcom_helper_misc::load_from_snippet()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.7085

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 10
ccs 4
cts 7
cp 0.5714
crap 3.7085
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 12
    public static function random_string(int $length, string $characters) : string
24
    {
25 12
        if ($length < 1) {
26
            throw new InvalidArgumentException('invalid length');
27
        }
28 12
        $size = strlen($characters) - 1;
29 12
        if ($size < 1) {
30
            throw new InvalidArgumentException('invalid characters');
31
        }
32 12
        $return = '';
33 12
        for ($i = 0; $i < $length; $i++) {
34 12
            $return .= $characters[random_int(0, $size)];
35
        }
36 12
        return $return;
37
    }
38
39
    /**
40
     * @param string $input
41
     */
42 27
    public static function urlize(string $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 479
    public static function parse_config($data, string $path) : array
52
    {
53
        try {
54 479
            return eval("return [{$data}\n];");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
55
        } catch (ParseError $e) {
0 ignored issues
show
Unused Code introduced by
catch (\ParseError $e) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
56
            throw new midcom_error('Failed to parse config data: ' . $e->getMessage() . ' in ' . $path . ' line ' . $e->getLine());
57
        }
58
    }
59
60
    /**
61
     * This helper function searches for a snippet either in the Filesystem
62
     * or in the database and returns its content or code-field, respectively.
63
     *
64
     * Prefix the snippet Path with 'file:' for retrieval of a file relative to
65
     * MIDCOM_ROOT; omit it to get the code field of a Snippet.
66
     *
67
     * Any error (files not found) will return null. If you want to trigger an error,
68
     * look for midcom_helper_misc::get_snippet_content.
69
     *
70
     * @return string       The content of the snippet/file.
71
     */
72 479
    public static function get_snippet_content_graceful(string $path)
73
    {
74 479
        static $cached_snippets = [];
75
76 479
        if (!array_key_exists($path, $cached_snippets)) {
77 63
            if (str_starts_with($path, 'file:')) {
78 45
                $cached_snippets[$path] = self::load_from_file($path);
79 22
            } elseif (str_starts_with($path, 'conf:')) {
80 22
                $cached_snippets[$path] = self::load(midcom::get()->config->get('midcom_config_basedir') . '/midcom' . substr($path, 5));
81
            } else {
82 17
                $cached_snippets[$path] = self::load_from_snippet($path);
83
            }
84
        }
85
86 479
        return $cached_snippets[$path];
87
    }
88
89 17
    private static function load_from_snippet(string $path) : ?string
90
    {
91 17
        $snippet = new midgard_snippet();
92 17
        if (!$snippet->get_by_path($path)) {
93 17
            return null;
94
        }
95
        if (isset(midcom::get()->cache->content)) {
96
            midcom::get()->cache->content->register($snippet->guid);
97
        }
98
        return $snippet->code;
99
    }
100
101 45
    private static function load_from_file(string $path)
102
    {
103 45
        $filename = MIDCOM_ROOT . substr($path, 5);
104 45
        if (!file_exists($filename)) {
105
            // try in src
106 2
            $filename = preg_replace('/\/lib\/?$/', '/src', MIDCOM_ROOT) . substr($path, 5);
107 2
            if (!file_exists($filename)) {
108
                //If we can't find the file in-tree, we look for out-of-tree components before giving up
109
                $filename = substr($path, 6);
110
                if (preg_match('|.+?/.+?/.+?/|', $filename)) {
111
                    $component_name = preg_replace('|(.+?)/(.+?)/(.+?)/.+|', '$1.$2.$3', $filename);
112
                    if (midcom::get()->componentloader->is_installed($component_name)) {
113
                        $filename = substr($filename, strlen($component_name));
114
                        $filename = midcom::get()->componentloader->path_to_snippetpath($component_name) . $filename;
115
                    }
116
                }
117
            }
118
        }
119 45
        return self::load($filename);
120
    }
121
122 63
    private static function load(string $filename)
123
    {
124 63
        if (!is_readable($filename)) {
125 22
            return null;
126
        }
127 45
        return file_get_contents($filename);
128
    }
129
130
    /**
131
     * This helper function searches for a snippet either in the Filesystem
132
     * or in the database and returns its content or code-field, respectively.
133
     *
134
     * Prefix the snippet Path with 'file:' for retrieval of a file relative to
135
     * MIDCOM_ROOT; omit it to get the code field of a Snippet.
136
     *
137
     * Any error (files not found) will raise a MidCOM Error. If you want a more
138
     * graceful behavior, look for midcom_helper_misc::get_snippet_content_graceful
139
     */
140 248
    public static function get_snippet_content(string $path) : string
141
    {
142 248
        $data = self::get_snippet_content_graceful($path);
143 248
        if ($data === null) {
0 ignored issues
show
introduced by
The condition $data === null is always false.
Loading history...
144
            throw new midcom_error("Could not load the contents of the snippet {$path}: Snippet does not exist.");
145
        }
146 248
        return $data;
147
    }
148
149
    /**
150
     * Find MIME type image for a document
151
     *
152
     * Used in midcom.helper.imagepopup, midgard.admin.asgard and org.openpsa.documents.
153
     *
154
     * @return string    Path to the icon
155
     */
156
    public static function get_mime_icon(string $mimetype) : string
157
    {
158
        $mime_fspath = MIDCOM_STATIC_ROOT . '/stock-icons/mime';
159
        $mime_urlpath = MIDCOM_STATIC_URL . '/stock-icons/mime';
160
        $mimetype_filename = str_replace('/', '-', $mimetype);
161
        if (!is_readable($mime_fspath)) {
162
            debug_add("Couldn't read directory {$mime_fspath}", MIDCOM_LOG_WARN);
163
        }
164
165
        if ($mimetype_filename == 'application-x-zip-compressed') {
166
            $filename = "gnome-application-zip.png";
167
        } else {
168
            $filename = "gnome-{$mimetype_filename}.png";
169
        }
170
        if (is_readable("{$mime_fspath}/{$filename}")) {
171
            return "{$mime_urlpath}/{$filename}";
172
        }
173
        // Default icon if there is none for the MIME type
174
        return $mime_urlpath . '/gnome-unknown.png';
175
    }
176
177
    /**
178
     * Pretty print file sizes
179
     *
180
     * @param int $size  File size in bytes
181
     */
182 7
    public static function filesize_to_string(int $size) : string
183
    {
184 7
        if ($size >= 1048576) {
185
            // More than a meg
186
            return sprintf("%01.1f", $size / 1048576) . " MB";
187
        }
188 7
        if ($size >= 1024) {
189
            // More than a kilo
190
            return sprintf("%01.1f", $size / 1024) . " KB";
191
        }
192 7
        return $size . " Bytes";
193
    }
194
195
    /**
196
     * Returns the first instance of a given component on the site.
197
     *
198
     * @return array NAP array of the first component instance found
199
     */
200 5
    public static function find_node_by_component(string $component) : ?array
201
    {
202 5
        static $cache = [];
203
204 5
        if (!array_key_exists($component, $cache)) {
205 1
            $cache[$component] = null;
206
207 1
            $nap = new midcom_helper_nav;
208 1
            $node_id = $nap->get_root_node();
209 1
            $root_node = $nap->get_node($node_id);
210
211 1
            if ($root_node[MIDCOM_NAV_COMPONENT] == $component) {
212
                $cache[$component] = $root_node;
213
            } else {
214 1
                $qb = midcom_db_topic::new_query_builder();
215 1
                $qb->add_constraint('component', '=', $component);
216 1
                $qb->add_constraint('name', '<>', '');
217 1
                $qb->add_constraint('up', 'INTREE', $node_id);
218 1
                $qb->set_limit(1);
219 1
                $topics = $qb->execute();
220
221 1
                if (count($topics) === 1) {
222
                    $cache[$component] = $nap->get_node($topics[0]->id);
223
                }
224
            }
225
        }
226
227 5
        return $cache[$component];
228
    }
229
}
230