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_footnote_info()
9{
10	return [
11		'name' => tra('Footnote'),
12		'documentation' => 'PluginFootnote',
13		'description' => tra('Create automatically numbered footnotes (together with PluginFootnoteArea)'),
14		'prefs' => ['wikiplugin_footnote'],
15		'body' => tra('The footnote'),
16		'iconname' => 'superscript',
17		'filter' => 'wikicontent',
18		'format' => 'html',
19		'introduced' => 3,
20		'params' => [
21			'tag' => [
22				'required' => false,
23				'name' => tra('Tag'),
24				'description' => tra('Tag footnote with unique identifier'),
25				'since' => '15.0',
26				'default' => '',
27				'filter' => 'alnum',
28				'accepted' => tra('One word made of alphanumeric characters'),
29			],
30			'sameastag' => [
31				'required' => false,
32				'name' => tra('Same as Tag'),
33				'description' => tra('Tag to existing footnote by its Tag'),
34				'since' => '15.0',
35				'default' => '',
36				'filter' => 'alnum',
37				'accepted' => tra('One word made of alphanumeric characters'),
38			],
39			'sameas' => [
40				'required' => false,
41				'name' => tra('Same as'),
42				'description' => tra('Tag to existing footnote number'),
43				'since' => '5.0',
44				'default' => '',
45				'filter' => 'alnum',
46				'accepted' => tra('tag name (since 17) or footnote number'),
47			],
48			'class' => [
49				'required' => false,
50				'name' => tra('Class'),
51				'description' => tra('Add class to footnotearea'),
52				'since' => '14.0',
53				'default' => '',
54				'filter' => 'alnumspace',
55				'accepted' => tra('Valid CSS class'),
56			],
57			'scheme' => [
58				'required' => false,
59				'name' => tra('Scheme'),
60				'description' => tra('Segregate footnotes by class in footnotearea. Apply different numbering style (optional)'),
61				'since' => '17.0',
62				'default' => '',
63				'filter' => 'text',
64				'accepted' => tra('Scheme strings (ClassName:((Number Style|numStyle))). Multiples may be separated by | (roman-upper:className|decimal)'),
65			],
66		]
67	];
68}
69
70/**
71 * @param string $data
72 * @param $params
73 * @param int $offset
74 * @param WikiParser_Parsable $context
75 * @return string
76 * @throws Exception
77 *
78 * @see wikiplugin_footnotearea()
79 */
80function wikiplugin_footnote($data, $params, $offset, $context)
81{
82	/** @var int $globalId Globally unique number of the next footnote, used for intra-document (anchor) links */
83	static $globalId = 1;
84	global $prefs;
85
86	$footnotes = &$context->footnotes;
87	$smarty = TikiLib::lib('smarty');
88
89	// By default, we allow popovers to display the footnote content on mouseover
90	if ( isset($prefs['footnote_popovers']) && $prefs['footnote_popovers'] != 'n' ) {
91		$headerlib = TikiLib::lib('header');
92		$headerlib->add_jsfile('lib/jquery_tiki/tiki-popovers_for_footnotes.js');
93	}
94
95	if (! isset($footnotes['lists'])) {   // if this is the first time the script has run, initialise
96		$footnotes['count'] = 0;
97		$footnotes['nest'] = 0;
98		$footnotes['tag'] = [];      // record of tags and associated footnote numbers
99		$footnotes['lists'] = [];    // data for general footnotes
100		$footnotes['lists']['.def.']['listType'] = 'decimal';    // set the default display type for lists
101	}
102
103	if (isset($params['scheme'])) {
104		setScheme($params['scheme']);
105	}
106
107	$data = trim($data);
108	if (! empty($data)) {
109		$footnotes['count']++;                      // keep a record of how many times footones is called to generate unique id's
110
111		// Create an array of classes to be applied
112		$classes = (isset($params['class'])) ? explode(' ', trim($params["class"])) : [];
113		if ($footnotes['nest'] > 0) {   // if we are in a nested footnote, add a nested class
114			$classes[] = 'footnest' . $footnotes['nest'];
115		}
116
117		//set the current list to create
118		$list = '.def.';                            // Set the default to illegal class name to prevent conflicts
119		foreach ($classes as $class) {
120			if (isset($footnotes['lists'][$class])) {
121				$list = $class;                         // set list the the first occurrence, if there happens to be multiplies.
122				break;
123			}
124		}
125
126		// wow, thats a mouth full, lets make it a little more pleasing to the eyes.
127		$footnote = &$footnotes['lists'][$list]['entry'];
128
129		// set the current number of list entries
130		$listNum = count($footnote) + 1;
131
132		if (isset($params["tag"]) && ! isset($footnotes['tag'][$params["tag"]])) {  // do nothing if duplicate tag
133			// Keep track of where data can be found for this Tag
134			$footnotes['tag'][$params["tag"]]['class'] = $list;
135			$footnotes['tag'][$params["tag"]]['num'] = $listNum;
136			$footnote[$listNum]['unique'] = $params["tag"];
137		} else {
138			$footnote[$listNum]['unique'] = $footnotes['count'];
139		}
140
141		$footnote[$listNum]['class'] = implode(' ', $classes);
142
143		$footnotes['nest']++;
144		$footnote[$listNum]['data'] = TikiLib::lib('parser')->parse_data_plugin($data, true);
145		$footnotes['nest']--;
146
147
148		$smarty->assign('uniqueId', $footnote[$listNum]['unique']);
149		$smarty->assign('unique', $footnote[$listNum]['unique']);
150		$smarty->assign('listNum', $listNum);
151		$smarty->assign('class', $footnote[$listNum]['class']);
152		$smarty->assign('listType', $footnotes['lists'][$list]['listType']);
153		return $smarty->fetch('templates/wiki-plugins/wikiplugin_footnote.tpl');
154	} else {                             // if there is no data
155		if (isset($params['sameastag'])) {
156			$sameas = $params['sameastag'];
157		} elseif (isset($params['sameas'])) {
158			$sameas = $params['sameas'];
159		}
160		if (isset($sameas)) {
161			if (isset($footnotes['tag'][$sameas])) {
162				$listNum = $footnotes['tag'][$sameas]['num'];
163				$uniqueId = $sameas . '-' . (@count($footnotes['lists'][ $footnotes['tag'][$sameas]['class'] ]['entry'][$listNum]['sameas']) + 1);
164				$footnotes['lists'][$footnotes['tag'][$sameas]['class']]['entry'][$listNum]['sameas'][] = $uniqueId;
165				$smarty->assign('listNum', $listNum);
166				$smarty->assign('uniqueId', $uniqueId);
167				$smarty->assign('unique', $sameas);
168				$smarty->assign('listType', $footnotes['lists'][$footnotes['tag'][$sameas]['class']]['listType']);
169				$smarty->assign('class', $footnotes['lists'][$footnotes['tag'][$sameas]['class']]['entry'][$listNum]['class']);
170			} elseif ((string)(int)$sameas === (string)$sameas) {   // else if the value is a integer
171				$smarty->assign('listNum', $sameas);// legacy support for number pointing.
172				$smarty->assign('listType', $footnotes['lists']['.def.']['listType']);
173				if (isset($footnotes['lists']['.def.']['entry'][$sameas])) {    // if the entry already exists
174					$uniqueId = $sameas . '-' . (count($footnotes['lists']['.def.']['entry'][$sameas]['sameas']) + 1);
175					$footnotes['lists']['.def.']['entry'][$sameas]['sameas'][] = $uniqueId;
176					$smarty->assign('uniqueId', $uniqueId);
177					$smarty->assign('unique', $footnotes['lists']['.def.']['entry'][$sameas]['unique']);
178					$smarty->assign('class', $footnotes['lists']['.def.']['entry'][$sameas]['class']);
179				} else {                 // legacy support. These values use to be static
180					$smarty->assign('unique', $sameas);
181					$smarty->assign('uniqueId', '');
182					$smarty->assign('class', '');
183				}
184			} else {
185				// The tag does not exist (yet) !!!!
186				return '<sup>' . tra('Error: Tag not found in any previous footnote') . '</sup>';
187			}
188			return $smarty->fetch('templates/wiki-plugins/wikiplugin_footnote.tpl');
189		}
190	}
191
192	return '';
193}
194
195function setScheme($rawScheme)
196{
197	global $footnotes;
198	$classes = explode('|', $rawScheme);
199	foreach ($classes as $class) {
200		$scheme = explode(':', $class);
201		if (! isset($scheme[1])) {
202			$scheme[1] = '.def.';                      // if no class specified, use the default list
203		}
204		$footnotes['lists'][$scheme[1]]['listType'] = $scheme[0];
205	}
206}
207