1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8function wikiplugin_module_info()
9{
10	global $lang;
11
12	$modlib = TikiLib::lib('mod');
13	$cachelib = TikiLib::lib('cache');
14
15	if (! $modules_options = $cachelib->getSerialized('module_list_for_plugin' . $lang)) {
16		$all_modules = $modlib->get_all_modules();
17		$all_modules_info = array_combine($all_modules, array_map([ $modlib, 'get_module_info' ], $all_modules));
18		uasort($all_modules_info, 'compare_names');
19		$modules_options = [];
20		foreach ($all_modules_info as $module => $module_info) {
21			$modules_options[] = ['text' => $module_info['name'] . ' (' . $module . ')', 'value' => $module];
22		}
23
24		$cachelib->cacheItem('module_list_for_plugin' . $lang, serialize($modules_options));
25	}
26
27	return [
28		'name' => tra('Module'),
29		'documentation' => 'PluginModule',
30		'description' => tra('Display a module'),
31		'prefs' => [ 'wikiplugin_module' ],
32		'validate' => 'all',
33		'format' => 'html',
34		'iconname' => 'module',
35		'introduced' => 1,
36		'extraparams' => true,
37		'tags' => [ 'basic' ],
38		'params' => [
39			'module' => [
40				'required' => true,
41				'name' => tra('Module Name'),
42				'description' => tra('Module name as known in Tiki'),
43				'since' => '1',
44				'default' => '',
45				'filter' => 'text',
46				'options' => $modules_options,
47			],
48			'notitle' => [
49				'required' => false,
50				'name' => tra('No Title'),
51				'description' => tr('Select Yes (%0y%1) to hide the title (default is to show the title)', '<code>', '</code>'),
52				'since' => '3.0',
53				'options' => [
54					['text' => '', 'value' => ''],
55					['text' => tra('Yes'), 'value' => 'y'],
56					['text' => tra('No'), 'value' => 'n'],
57				],
58				'filter' => 'alpha',
59				'advanced' => true,
60			],
61			'title' => [
62				'name' => tra('Module Title'),
63				'description' => tr(
64					'Title to display at the top of the box, assuming No Title is not set to Yes (%0y%1).',
65					'<code>',
66					'</code>'
67				),
68				'since' => '1',
69				'filter' => 'text',
70				'advanced' => true,
71			],
72			'float' => [
73				'required' => false,
74				'name' => tra('Float'),
75				'description' => tra('Align the module to the left or right on the page allowing other elements to align against it'),
76				'since' => '1',
77				'default' => '',
78				'filter' => 'word',
79				'advanced' => true,
80				'options' => [
81					['text' => '', 'value' => ''],
82					['text' => 'No Float', 'value' => 'nofloat'],
83					['text' => tra('Left'), 'value' => 'left'],
84					['text' => tra('Right'), 'value' => 'right']
85				]
86			],
87			'max' => [
88				'required' => false,
89				'name' => tra('Max'),
90				'description' => tr('Number of rows (default: %010%1)', '<code>', '</code>'),
91				'since' => '1',
92				'default' => 10,
93				'filter' => 'digits',
94				'advanced' => true,
95			],
96			'np' => [
97				'required' => false,
98				'name' => tra('Parse'),
99				'description' => tra('Parse wiki syntax.') . ' ' . tra('Default:') . ' ' . tra('No'),
100				'since' => '1',
101				'default' => '1',
102				'filter' => 'digits',
103				'options' => [
104					['text' => '', 'value' => ''],
105					['text' => tra('Yes'), 'value' => '0'],
106					['text' => tra('No'), 'value' => '1'],
107				],
108				'advanced' => true,
109			],
110			'nobox' => [
111				'name' => tra('No Box'),
112				'description' => 'y|n ' . tra('Show only the content with no title or borders, etc. around the content.'),
113				'since' => '9.0',
114				'section' => 'appearance',
115				'filter' => 'alpha',
116				'advanced' => true,
117				'options' => [
118					['text' => '', 'value' => ''],
119					['text' => tra('Yes'), 'value' => 'y'],
120					['text' => tra('No'), 'value' => 'n']
121				]
122			],
123			'decoration' => [
124				'required' => false,
125				'name' => tra('Title, background, etc'),
126				'description' => tra('Show module title (heading) background, etc. (default is to show them)'),
127				'since' => '1',
128				'advanced' => true,
129				'filter' => 'digits',
130				'options' => [
131					['text' => '', 'value' => ''],
132					['text' => tra('Yes'), 'value' => '1'],
133					['text' => tra('No'), 'value' => '0'],
134				]
135			],
136			'flip' => [
137				'required' => false,
138				'name' => tra('Flip'),
139				'description' => tra('Add ability to show/hide the content of the module (default is the site admin
140					setting for modules)'),
141				'since' => '1',
142				'section' => 'appearance',
143				'filter' => 'digits',
144				'options' => [
145					['text' => '', 'value' => ''],
146					['text' => tra('Yes'), 'value' => '1'],
147					['text' => tra('No'), 'value' => '0'],
148				],
149				'advanced' => true,
150			],
151			'bgcolor' => [
152				'required' => false,
153				'name' => tra('Title Background'),
154				'description' => tr(
155					'Override the background color for the title (if the title is shown). The value
156					can be a color name (ex: %0bgcolor="blue"%1) or a hexadecimal value (ex: %0bgcolor="#FFEBCD"%1)',
157					'<code>',
158					'</code>'
159				),
160				'since' => '9.0',
161				'default' => '',
162				'filter' => 'text',
163				'advanced' => true,
164			],
165			'module_style' => [
166				'required' => false,
167				'name' => tra('Module Style'),
168				'description' => tr(
169					'Inline CSS for the containing div element, for example, %0max-width:80%%1',
170					'<code>',
171					'</code>'
172				),
173				'since' => '9.0',
174				'filter' => 'text',
175				'accepted' => tra('Valid CSS styling'),
176				'default' => '',
177				'advanced' => true,
178			],
179			'style' => [
180				'name' => tra('Style'),
181				'description' => tra('CSS styling for the module data itself.'),
182				'since' => '9.0',
183				'filter' => 'text',
184				'section' => 'appearance',
185				'accepted' => tra('Valid CSS styling'),
186				'advanced' => true,
187			],
188			'topclass' => [
189				'name' => tra('Containing Class'),
190				'description' => tra('Custom CSS class of div around the module.'),
191				'since' => '9.0',
192				'filter' => 'text',
193				'section' => 'appearance',
194				'accepted' => tra('Valid CSS class'),
195				'advanced' => true,
196			],
197			'class' => [
198				'name' => tra('Class'),
199				'description' => tra('Custom CSS class.'),
200				'since' => '9.0',
201				'section' => 'appearance',
202				'filter' => 'text',
203				'accepted' => tra('Valid CSS class'),
204				'advanced' => true,
205			],
206			'category' => [
207				'name' => tra('Category'),
208				'description' => tra('Module displayed depending on category. Multiple category ids or names can be
209					separated by semi-colons.'),
210				'since' => '9.0',
211				'section' => 'visibility',
212				'separator' => ';',
213				'filter' => 'alnum',
214				'advanced' => true,
215			],
216			'nocategory' => [
217				'name' => tra('No Category'),
218				'description' => tra('Module hidden depending on category. Multiple category ids or names can be
219					separated by semi-colons. This takes precedence over the category parameter above.'),
220				'since' => '9.0',
221				'section' => 'visibility',
222				'separator' => ';',
223				'filter' => 'alnum',
224				'advanced' => true,
225			],
226			'perspective' => [
227				'name' => tra('Perspective'),
228				'description' => tra('Only display the module if in one of the listed perspective IDs. Semi-colon
229					separated.'),
230				'since' => '9.0',
231				'separator' => ';',
232				'filter' => 'digits',
233				'section' => 'visibility',
234				'advanced' => true,
235			],
236			'lang' => [
237				'name' => tra('Language'),
238				'description' => tra('Module only applicable for the specified languages. Languages are defined as two
239					character language codes. Multiple values can be separated by semi-colons.'),
240				'since' => '9.0',
241				'separator' => ';',
242				'filter' => 'lang',
243				'section' => 'visibility',
244				'advanced' => true,
245			],
246			'section' => [
247				'name' => tra('Section'),
248				'description' => tra('Module only applicable for the specified sections. Multiple values can be
249					separated by semi-colons.'),
250				'since' => '9.0',
251				'separator' => ';',
252				'filter' => 'text',
253				'section' => 'visibility',
254				'advanced' => true,
255			],
256			'page' => [
257				'name' => tra('Page Filter'),
258				'description' => tra('Module only applicable on the specified page names. Multiple values can be
259					separated by semi-colons.'),
260				'since' => '9.0',
261				'separator' => ';',
262				'filter' => 'pagename',
263				'section' => 'visibility',
264				'advanced' => true,
265			],
266			'nopage' => [
267				'name' => tra('No Page'),
268				'description' => tra('Module not applicable on the specified page names. Multiple values can be
269					separated by semi-colons.'),
270				'since' => '9.0',
271				'separator' => ';',
272				'filter' => 'pagename',
273				'section' => 'visibility',
274				'advanced' => true,
275			],
276			'theme' => [
277				'name' => tra('Theme'),
278				'description' => tr('Module enabled or disabled depending on the theme file name (e.g.
279					%0thenews.css%1). Specified themes can be either included or excluded. Theme names prefixed by %0!%1
280					are in the exclusion list. Multiple values can be separated by semi-colons.', '<code>', '</code>'),
281				'since' => '9.0',
282				'separator' => ';',
283				'filter' => 'themename',
284				'section' => 'visibility',
285				'advanced' => true,
286			],
287			'creator' => [
288				'name' => tra('Creator'),
289				'description' => tr('Module only available based on the relationship of the user with the wiki page.
290					Either only creators (%0y%1) or only non-creators (%0n%1) will see the module.', '<code>', '</code>'),
291				'since' => '9.0',
292				'filter' => 'alpha',
293				'section' => 'visibility',
294				'advanced' => true,
295			],
296			'contributor' => [
297				'name' => tra('Contributor'),
298				'description' => tra(
299					'Module only available based on the relationship of the user with the wiki page.
300					Either only contributors (%0y%1) or only non-contributors (%0n%1) will see the module.',
301					'<code>',
302					'</code>'
303				),
304				'since' => '9.0',
305				'filter' => 'alpha',
306				'section' => 'visibility',
307				'advanced' => true,
308			],
309		]
310	];
311}
312
313function wikiplugin_module($data, $params)
314{
315	static $instance = 0;
316
317	$out = '';
318
319	extract($params, EXTR_SKIP);
320
321	if (! isset($float)) {
322		$float = 'nofloat';
323	}
324
325	if (! isset($max)) {
326		if (! isset($rows)) {
327			$max = 10; // default value
328		} else {
329			$max = $rows; // rows=> used instead of max=> ?
330		}
331	}
332
333	if (! isset($np)) {
334		$np = '1';
335	}
336
337	if (! isset($module) or ! $module) {
338		$out = '<form class="box" id="modulebox">';
339
340		$out .= '<br /><select name="choose">';
341		$out .= '<option value="">' . tra('Please choose a module') . '</option>';
342		$out .= '<option value="" style="background-color:#bebebe;">' . tra('to be used as argument') . '</option>';
343		$out .= '<option value="" style="background-color:#bebebe;">{MODULE(module=>name_of_module)}</option>';
344		$handle = opendir('modules');
345
346		while ($file = readdir($handle)) {
347			if ((substr($file, 0, 4) == "mod-") and (substr($file, -4, 4) == ".php")) {
348				$mod = substr(substr(basename($file), 4), 0, -4);
349
350				$out .= "<option value=\"$mod\">$mod</option>";
351			}
352		}
353
354		$out .= '</select></form>';
355	} else {
356		$instance++;
357		if (empty($moduleId)) {
358			$moduleId = 'wikiplugin_' . $instance;
359		}
360
361		$module_reference = [
362			'moduleId' => $moduleId,
363			'name' => $module,
364			'params' => $params,
365			'rows' => $max,
366			'position' => '_wp_',
367			'ord' => $instance,
368			'cache_time' => 0,
369		];
370
371		if (! empty($module_style)) {
372			$module_reference['module_style'] = $module_style;
373		}
374
375		$modlib = TikiLib::lib('mod');
376		$out = $modlib->execute_module($module_reference);
377	}
378
379	if ($out) {
380		if ($float != 'nofloat') {
381			$data = "<div style='float: $float;'>$out</div>";
382		} else {
383			$data = "<div>$out</div>";
384		}
385	} else {
386		// Display error message
387		$data = "<div class=\"alert alert-danger\" role=\"alert\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"" . tra("Close") . "\"><span aria-hidden=\"true\">&times;</span></button>" . tra("Sorry, no such module") . "<br><b>$module</b></div>" . $data;
388	}
389
390	if ($module == 'register') {
391		// module register (maybe others too?) adds ~np~ to plugin output so remove them
392		$data = preg_replace('/~[\/]?np~/ms', '', $data);
393	}
394	return $data;
395}
396