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
|
532 |
|
public static function parse_config($data, string $path) : array |
44
|
|
|
{ |
45
|
|
|
try { |
46
|
532 |
|
return eval("return [{$data}\n];"); |
|
|
|
|
47
|
|
|
} catch (ParseError $e) { |
|
|
|
|
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
|
532 |
|
public static function get_snippet_content_graceful(string $path) |
65
|
|
|
{ |
66
|
532 |
|
static $cached_snippets = []; |
67
|
|
|
|
68
|
532 |
|
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
|
532 |
|
return $cached_snippets[$path]; |
85
|
|
|
} |
86
|
|
|
|
87
|
192 |
|
public static function resolve_path(string $path) : string |
88
|
|
|
{ |
89
|
192 |
|
if (str_starts_with($path, 'conf:')) { |
90
|
22 |
|
return midcom::get()->config->get('midcom_config_basedir') . '/midcom' . substr($path, 5); |
91
|
|
|
} |
92
|
174 |
|
if (str_starts_with($path, 'file:')) { |
93
|
174 |
|
$filename = MIDCOM_ROOT . substr($path, 5); |
94
|
174 |
|
if (file_exists($filename)) { |
95
|
174 |
|
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
|
174 |
|
public static function load_snippet(string $path) : array |
126
|
|
|
{ |
127
|
174 |
|
$resolved_path = self::resolve_path($path); |
128
|
174 |
|
if (str_ends_with($resolved_path, '.php')) { |
129
|
172 |
|
return include $resolved_path; |
130
|
|
|
} |
131
|
2 |
|
$data = self::get_snippet_content_graceful($path); |
132
|
2 |
|
if ($data === null) { |
|
|
|
|
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
|
|
|
|