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