Issues (1014)

Themes/default/Post.template.php (4 issues)

Labels
Severity
1
<?php
2
/**
3
 * Simple Machines Forum (SMF)
4
 *
5
 * @package SMF
6
 * @author Simple Machines https://www.simplemachines.org
7
 * @copyright 2022 Simple Machines and individual contributors
8
 * @license https://www.simplemachines.org/about/smf/license.php BSD
9
 *
10
 * @version 2.1.2
11
 */
12
13
/**
14
 * The main template for the post page.
15
 */
16
function template_main()
17
{
18
	global $context, $options, $txt, $scripturl, $modSettings, $counter;
19
20
	// Start the javascript... and boy is there a lot.
21
	echo '
22
		<script>';
23
24
	// When using Go Back due to fatal_error, allow the form to be re-submitted with changes.
25
	if (isBrowser('is_firefox'))
26
		echo '
27
			window.addEventListener("pageshow", reActivate, false);';
28
29
	// Start with message icons - and any missing from this theme.
30
	echo '
31
			var icon_urls = {';
32
33
	foreach ($context['icons'] as $icon)
34
		echo '
35
				\'', $icon['value'], '\': \'', $icon['url'], '\'', $icon['is_last'] ? '' : ',';
36
37
	echo '
38
			};';
39
40
	// If this is a poll - use some javascript to ensure the user doesn't create a poll with illegal option combinations.
41
	if ($context['make_poll'])
42
		echo '
43
			var pollOptionNum = 0, pollTabIndex;
44
			var pollOptionId = ', $context['last_choice_id'], ';
45
			function addPollOption()
46
			{
47
				if (pollOptionNum == 0)
48
				{
49
					for (var i = 0, n = document.forms.postmodify.elements.length; i < n; i++)
50
						if (document.forms.postmodify.elements[i].id.substr(0, 8) == \'options-\')
51
						{
52
							pollOptionNum++;
53
							pollTabIndex = document.forms.postmodify.elements[i].tabIndex;
54
						}
55
				}
56
				pollOptionNum++
57
				pollOptionId++
58
59
				setOuterHTML(document.getElementById(\'pollMoreOptions\'), ', JavaScriptEscape('<dt><label for="options-'), ' + pollOptionId + ', JavaScriptEscape('">' . $txt['option'] . ' '), ' + pollOptionNum + ', JavaScriptEscape('</label>:</dt><dd><input type="text" name="options['), ' + pollOptionId + ', JavaScriptEscape(']" id="options-'), ' + pollOptionId + ', JavaScriptEscape('" value="" size="80" maxlength="255" tabindex="'), ' + pollTabIndex + ', JavaScriptEscape('"></dd><p id="pollMoreOptions"></p>'), ');
60
			}';
61
62
	// If we are making a calendar event we want to ensure we show the current days in a month etc... this is done here.
63
	if ($context['make_event'])
64
		echo '
65
			var monthLength = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];';
66
67
	// End of the javascript, start the form and display the link tree.
68
	echo '
69
		</script>
70
		<form action="', $scripturl, '?action=', $context['destination'], ';', empty($context['current_board']) ? '' : 'board=' . $context['current_board'], '" method="post" accept-charset="', $context['character_set'], '" name="postmodify" id="postmodify" class="flow_hidden" onsubmit="', ($context['becomes_approved'] ? '' : 'alert(\'' . $txt['js_post_will_require_approval'] . '\');'), 'submitonce(this);" enctype="multipart/form-data">';
71
72
	// If the user wants to see how their message looks - the preview section is where it's at!
73
	echo '
74
			<div id="preview_section"', isset($context['preview_message']) ? '' : ' style="display: none;"', '>
75
				<div class="cat_bar">
76
					<h3 class="catbg">
77
						<span id="preview_subject">', empty($context['preview_subject']) ? '&nbsp;' : $context['preview_subject'], '</span>
78
					</h3>
79
				</div>
80
				<div id="preview_body" class="windowbg">
81
					', empty($context['preview_message']) ? '<br>' : $context['preview_message'], '
82
				</div>
83
			</div>
84
			<br>';
85
86
	if ($context['make_event'] && (!$context['event']['new'] || !empty($context['current_board'])))
87
		echo '
88
			<input type="hidden" name="eventid" value="', $context['event']['id'], '">';
89
90
	// Start the main table.
91
	echo '
92
			<div class="cat_bar">
93
				<h3 class="catbg">', $context['page_title'], '</h3>
94
			</div>
95
			<div id="post_area">
96
				<div class="roundframe noup">', isset($context['current_topic']) ? '
97
					<input type="hidden" name="topic" value="' . $context['current_topic'] . '">' : '';
98
99
	// If an error occurred, explain what happened.
100
	echo '
101
					<div class="', empty($context['error_type']) || $context['error_type'] != 'serious' ? 'noticebox' : 'errorbox', '"', empty($context['post_error']) ? ' style="display: none"' : '', ' id="errors">
102
						<dl>
103
							<dt>
104
								<strong id="error_serious">', $txt['error_while_submitting'], '</strong>
105
							</dt>
106
							<dd class="error" id="error_list">
107
								', empty($context['post_error']) ? '' : implode('<br>', $context['post_error']), '
108
							</dd>
109
						</dl>
110
					</div>';
111
112
	// If this won't be approved let them know!
113
	if (!$context['becomes_approved'])
114
		echo '
115
					<div class="noticebox">
116
						<em>', $txt['wait_for_approval'], '</em>
117
						<input type="hidden" name="not_approved" value="1">
118
					</div>';
119
120
	// If it's locked, show a message to warn the replier.
121
	if (!empty($context['locked']))
122
		echo '
123
					<div class="errorbox">
124
						', $txt['topic_locked_no_reply'], '
125
					</div>';
126
127
	if (!empty($modSettings['drafts_post_enabled']))
128
		echo '
129
					<div id="draft_section" class="infobox"', isset($context['draft_saved']) ? '' : ' style="display: none;"', '>',
130
						sprintf($txt['draft_saved'], $scripturl . '?action=profile;u=' . $context['user']['id'] . ';area=showdrafts'), '
131
						', (!empty($modSettings['drafts_keep_days']) ? ' <strong>' . sprintf($txt['draft_save_warning'], $modSettings['drafts_keep_days']) . '</strong>' : ''), '
132
					</div>';
133
134
	// The post header... important stuff
135
	template_post_header();
136
137
	// Are you posting a calendar event?
138
	if ($context['make_event'])
139
	{
140
		// Note to theme writers: The JavaScripts expect the input fields for the start and end dates & times to be contained in a wrapper element with the id "event_time_input"
141
		echo '
142
					<hr class="clear">
143
					<div id="post_event">
144
						<fieldset id="event_options">
145
							<legend', isset($context['post_error']['no_event']) ? ' class="error"' : '', '>', $txt['calendar_event_options'], '</legend>
146
							<input type="hidden" name="calendar" value="1">
147
							<div class="event_options" id="event_title">
148
								<div>
149
									<span class="label">', $txt['calendar_event_title'], '</span>
150
									<input type="text" id="evtitle" name="evtitle" maxlength="255" value="', $context['event']['title'], '" tabindex="', $context['tabindex']++, '">
151
								</div>
152
							</div>
153
							<div class="event_options">
154
								<div class="event_options_left" id="event_time_input">
155
									<div>
156
										<span class="label">', $txt['start'], '</span>
157
										<input type="text" name="start_date" id="start_date" value="', trim($context['event']['start_date_orig']), '" tabindex="', $context['tabindex']++, '" class="date_input start" data-type="date">
158
										<input type="text" name="start_time" id="start_time" maxlength="11" value="', $context['event']['start_time_orig'], '" tabindex="', $context['tabindex']++, '" class="time_input start" data-type="time"', !empty($context['event']['allday']) ? ' disabled' : '', '>
159
									</div>
160
									<div>
161
										<span class="label">', $txt['end'], '</span>
162
										<input type="text" name="end_date" id="end_date" value="', trim($context['event']['end_date_orig']), '" tabindex="', $context['tabindex']++, '" class="date_input end" data-type="date"', $modSettings['cal_maxspan'] == 1 ? ' disabled' : '', '>
163
										<input type="text" name="end_time" id="end_time" maxlength="11" value="', $context['event']['end_time_orig'], '" tabindex="', $context['tabindex']++, '" class="time_input end" data-type="time"', !empty($context['event']['allday']) ? ' disabled' : '', '>
164
									</div>
165
								</div>
166
								<div class="event_options_right" id="event_time_options">
167
									<div id="event_allday">
168
										<label for="allday"><span class="label">', $txt['calendar_allday'], '</span></label>
169
										<input type="checkbox" name="allday" id="allday"', !empty($context['event']['allday']) ? ' checked' : '', ' tabindex="', $context['tabindex']++, '">
170
									</div>
171
									<div id="event_timezone">
172
										<span class="label">', $txt['calendar_timezone'], '</span>
173
										<select name="tz" id="tz"', !empty($context['event']['allday']) ? ' disabled' : '', '>';
174
175
			foreach ($context['all_timezones'] as $tz => $tzname)
176
				echo '
177
											<option', is_numeric($tz) ? ' value="" disabled' : ' value="' . $tz . '"', $tz === $context['event']['tz'] ? ' selected' : '', '>', $tzname, '</option>';
178
179
			echo '
180
										</select>
181
									</div>
182
								</div>
183
							</div>
184
							<div class="event_options">
185
								<div>
186
									<span class="label">', $txt['location'], '</span>
187
									<input type="text" name="event_location" id="event_location" maxlength="255" value="', $context['event']['location'], '" tabindex="', $context['tabindex']++, '">
188
								</div>
189
							</div>
190
						</fieldset>
191
					</div><!-- #post_event -->';
192
	}
193
194
	// If this is a poll then display all the poll options!
195
	if ($context['make_poll'])
196
	{
197
		echo '
198
					<hr class="clear">
199
					<div id="edit_poll">
200
						<fieldset id="poll_main">
201
							<legend><span ', (isset($context['poll_error']['no_question']) ? ' class="error"' : ''), '>', $txt['poll_question'], '</span></legend>
202
							<dl class="settings poll_options">
203
								<dt>', $txt['poll_question'], '</dt>
204
								<dd>
205
									<input type="text" name="question" value="', isset($context['question']) ? $context['question'] : '', '" tabindex="', $context['tabindex']++, '" size="80">
206
								</dd>';
207
208
		// Loop through all the choices and print them out.
209
		foreach ($context['choices'] as $choice)
210
			echo '
211
								<dt>
212
									<label for="options-', $choice['id'], '">', $txt['option'], ' ', $choice['number'], '</label>:
213
								</dt>
214
								<dd>
215
									<input type="text" name="options[', $choice['id'], ']" id="options-', $choice['id'], '" value="', $choice['label'], '" tabindex="', $context['tabindex']++, '" size="80" maxlength="255">
216
								</dd>';
217
218
		echo '
219
								<p id="pollMoreOptions"></p>
220
							</dl>
221
							<strong><a href="javascript:addPollOption(); void(0);">(', $txt['poll_add_option'], ')</a></strong>
222
						</fieldset>
223
						<fieldset id="poll_options">
224
							<legend>', $txt['poll_options'], '</legend>
225
							<dl class="settings poll_options">
226
								<dt>
227
									<label for="poll_max_votes">', $txt['poll_max_votes'], ':</label>
228
								</dt>
229
								<dd>
230
									<input type="text" name="poll_max_votes" id="poll_max_votes" size="2" value="', $context['poll_options']['max_votes'], '">
231
								</dd>
232
								<dt>
233
									<label for="poll_expire">', $txt['poll_run'], ':</label><br>
234
									<em class="smalltext">', $txt['poll_run_limit'], '</em>
235
								</dt>
236
								<dd>
237
									<input type="text" name="poll_expire" id="poll_expire" size="2" value="', $context['poll_options']['expire'], '" onchange="pollOptions();" maxlength="4"> ', $txt['days_word'], '
238
								</dd>
239
								<dt>
240
									<label for="poll_change_vote">', $txt['poll_do_change_vote'], ':</label>
241
								</dt>
242
								<dd>
243
									<input type="checkbox" id="poll_change_vote" name="poll_change_vote"', !empty($context['poll']['change_vote']) ? ' checked' : '', '>
244
								</dd>';
245
246
		if ($context['poll_options']['guest_vote_enabled'])
247
			echo '
248
								<dt>
249
									<label for="poll_guest_vote">', $txt['poll_guest_vote'], ':</label>
250
								</dt>
251
								<dd>
252
									<input type="checkbox" id="poll_guest_vote" name="poll_guest_vote"', !empty($context['poll_options']['guest_vote']) ? ' checked' : '', '>
253
								</dd>';
254
255
		echo '
256
								<dt>
257
									', $txt['poll_results_visibility'], ':
258
								</dt>
259
								<dd>
260
									<input type="radio" name="poll_hide" id="poll_results_anyone" value="0"', $context['poll_options']['hide'] == 0 ? ' checked' : '', '> <label for="poll_results_anyone">', $txt['poll_results_anyone'], '</label><br>
261
									<input type="radio" name="poll_hide" id="poll_results_voted" value="1"', $context['poll_options']['hide'] == 1 ? ' checked' : '', '> <label for="poll_results_voted">', $txt['poll_results_voted'], '</label><br>
262
									<input type="radio" name="poll_hide" id="poll_results_expire" value="2"', $context['poll_options']['hide'] == 2 ? ' checked' : '', empty($context['poll_options']['expire']) ? ' disabled' : '', '> <label for="poll_results_expire">', $txt['poll_results_after'], '</label>
263
								</dd>
264
							</dl>
265
						</fieldset>
266
					</div><!-- #edit_poll -->';
267
	}
268
269
	// Show the actual posting area...
270
	echo '
271
					', template_control_richedit($context['post_box_name'], 'smileyBox_message', 'bbcBox_message');
0 ignored issues
show
'smileyBox_message' of type string is incompatible with the type boolean|null expected by parameter $smileyContainer of template_control_richedit(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

271
					', template_control_richedit($context['post_box_name'], /** @scrutinizer ignore-type */ 'smileyBox_message', 'bbcBox_message');
Loading history...
'bbcBox_message' of type string is incompatible with the type boolean|null expected by parameter $bbcContainer of template_control_richedit(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

271
					', template_control_richedit($context['post_box_name'], 'smileyBox_message', /** @scrutinizer ignore-type */ 'bbcBox_message');
Loading history...
Are you sure the usage of template_control_richedi...age', 'bbcBox_message') is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
272
273
	// If we're editing and displaying edit details, show a box where they can say why
274
	if (isset($context['editing']) && $modSettings['show_modify'])
275
		echo '
276
					<dl>
277
						<dt class="clear">
278
							<span id="caption_edit_reason">', $txt['reason_for_edit'], ':</span>
279
						</dt>
280
						<dd>
281
							<input type="text" name="modify_reason"', isset($context['last_modified_reason']) ? ' value="' . $context['last_modified_reason'] . '"' : '', ' tabindex="', $context['tabindex']++, '" size="80" maxlength="80">
282
						</dd>
283
					</dl>';
284
285
	// If this message has been edited in the past - display when it was.
286
	if (isset($context['last_modified']))
287
		echo '
288
					<div class="padding smalltext">
289
						', $context['last_modified_text'], '
290
					</div>';
291
292
	// If the admin has enabled the hiding of the additional options - show a link and image for it.
293
	if (!empty($modSettings['additional_options_collapsable']))
294
		echo '
295
					<div id="post_additional_options_header">
296
						<strong><a href="#" id="postMoreExpandLink"> ', $context['can_post_attachment'] ? $txt['post_additionalopt_attach'] : $txt['post_additionalopt'], '</a></strong>
297
					</div>';
298
299
	echo '
300
					<div id="post_additional_options">';
301
302
	// Display the checkboxes for all the standard options - if they are available to the user!
303
	echo '
304
						<div id="post_settings" class="smalltext">
305
							<ul class="post_options">
306
								', $context['can_notify'] ? '<li><input type="hidden" name="notify" value="0"><label for="check_notify"><input type="checkbox" name="notify" id="check_notify"' . ($context['notify'] || !empty($options['auto_notify']) || $context['auto_notify'] ? ' checked' : '') . ' value="1"> ' . $txt['notify_replies'] . '</label></li>' : '', '
307
								', $context['can_lock'] ? '<li><input type="hidden" name="already_locked" value="' . $context['already_locked'] . '"><input type="hidden" name="lock" value="0"><label for="check_lock"><input type="checkbox" name="lock" id="check_lock"' . ($context['locked'] ? ' checked' : '') . ' value="1"> ' . $txt['lock_topic'] . '</label></li>' : '', '
308
								<li><label for="check_back"><input type="checkbox" name="goback" id="check_back"' . ($context['back_to_topic'] || !empty($options['return_to_post']) ? ' checked' : '') . ' value="1"> ' . $txt['back_to_topic'] . '</label></li>
309
								', $context['can_sticky'] ? '<li><input type="hidden" name="already_sticky" value="' . $context['already_sticky'] . '"><input type="hidden" name="sticky" value="0"><label for="check_sticky"><input type="checkbox" name="sticky" id="check_sticky"' . ($context['sticky'] ? ' checked' : '') . ' value="1"> ' . $txt['sticky_after_posting'] . '</label></li>' : '', '
310
								<li><label for="check_smileys"><input type="checkbox" name="ns" id="check_smileys"', $context['use_smileys'] ? '' : ' checked', ' value="NS"> ', $txt['dont_use_smileys'], '</label></li>', '
311
								', $context['can_move'] ? '<li><input type="hidden" name="move" value="0"><label for="check_move"><input type="checkbox" name="move" id="check_move" value="1"' . (!empty($context['move']) ? ' checked" ' : '') . '> ' . $txt['move_after_posting'] . '</label></li>' : '', '
312
								', $context['can_announce'] && $context['is_first_post'] ? '<li><label for="check_announce"><input type="checkbox" name="announce_topic" id="check_announce" value="1"' . (!empty($context['announce']) ? ' checked' : '') . '> ' . $txt['announce_topic'] . '</label></li>' : '', '
313
								', $context['show_approval'] ? '<li><label for="approve"><input type="checkbox" name="approve" id="approve" value="2"' . ($context['show_approval'] === 2 ? ' checked' : '') . '> ' . $txt['approve_this_post'] . '</label></li>' : '', '
314
							</ul>
315
						</div><!-- #post_settings -->';
316
317
	// If this post already has attachments on it - give information about them.
318
	if (!empty($context['current_attachments']))
319
	{
320
		echo '
321
						<dl id="postAttachment">
322
							<dt>
323
								', $txt['attachments'], ':
324
							</dt>
325
							<dd class="smalltext" style="width: 100%;">
326
								<input type="hidden" name="attach_del[]" value="0">
327
								', $txt['uncheck_unwatchd_attach'], ':
328
							</dd>';
329
330
		foreach ($context['current_attachments'] as $attachment)
331
			echo '
332
							<dd class="smalltext">
333
								<label for="attachment_', $attachment['attachID'], '"><input type="checkbox" id="attachment_', $attachment['attachID'], '" name="attach_del[]" value="', $attachment['attachID'], '"', empty($attachment['unchecked']) ? ' checked' : '', '> ', $attachment['name'], (empty($attachment['approved']) ? ' (' . $txt['awaiting_approval'] . ')' : ''),
334
								!empty($modSettings['attachmentPostLimit']) || !empty($modSettings['attachmentSizeLimit']) ? sprintf($txt['attach_kb'], comma_format(round(max($attachment['size'], 1024) / 1024), 0)) : '', '</label>
335
							</dd>';
336
337
		echo '
338
						</dl>';
339
340
		if (!empty($context['files_in_session_warning']))
341
			echo '
342
						<div class="smalltext"><em>', $context['files_in_session_warning'], '</em></div>';
343
	}
344
345
	// Is the user allowed to post any additional ones? If so give them the boxes to do it!
346
	if ($context['can_post_attachment'])
347
	{
348
		// Print dropzone UI.
349
		echo '
350
						<div class="files" id="attachment_previews">
351
							<div>
352
								<strong>', $txt['attachments'], ':</strong>
353
							</div>
354
							<div id="au-template">
355
								<div class="attach-preview">
356
									<img data-dz-thumbnail />
357
								</div>
358
								<div class="attachment_info">
359
									<div>
360
										<span class="name" data-dz-name></span>
361
										<span class="error" data-dz-errormessage></span>
362
										<span class="size" data-dz-size></span>
363
										<span class="message" data-dz-message></span>
364
									</div>
365
									<div class="attached_BBC">
366
										<input type="text" name="attachBBC" value="" readonly>
367
										<div class="attached_BBC_width_height">
368
											<div class="attached_BBC_width">
369
												<label for="attached_BBC_width">', $txt['attached_insert_width'], '</label>
370
												<input type="number" name="attached_BBC_width" min="0" value="" placeholder="auto">
371
											</div>
372
											<div class="attached_BBC_height">
373
												<label for="attached_BBC_height">', $txt['attached_insert_height'], '</label>
374
												<input type="number" name="attached_BBC_height" min="0" value="" placeholder="auto">
375
											</div>
376
										</div>
377
									</div><!-- .attached_BBC -->
378
									<div class="progress_bar" role="progressBar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
379
										<div class="bar"></div>
380
									</div>
381
									<div class="attach-ui">
382
										<a data-dz-remove class="button cancel">', $txt['modify_cancel'], '</a>
383
										<a class="button upload">', $txt['upload'], '</a>
384
									</div>
385
								</div><!-- .attachment_info -->
386
							</div><!-- #au-template -->
387
						</div><!-- #attachment_previews -->
388
						<div id ="max_files_progress" class="max_files_progress progress_bar">
389
							<div class="bar"></div>
390
						</div>
391
						<div id ="max_files_progress_text"></div>';
392
393
		echo '
394
						<dl id="postAttachment2">
395
							<dd class="fallback">
396
								<div id="attachment_upload" class="descbox">
397
									<div id="drop_zone_ui">
398
										<div>
399
											<strong>', $txt['attach_drop_zone'], '</strong>
400
										</div>
401
										<div class="righttext">
402
											<a class="button" id="attach_cancel_all">', $txt['attached_cancel_all'], '</a>
403
											<a class="button" id="attach_upload_all">', $txt['attached_upload_all'], '</a>
404
											<a class="button fileinput-button">', $txt['attach_add'], '</a>
405
										</div>
406
									</div>
407
									<div id="total_progress" class="progress_bar" role="progressBar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
408
										<div class="bar"></div>
409
									</div>
410
									<div class="fallback">
411
										<input type="file" multiple="multiple" name="attachment[]" id="attachment1" class="fallback"> (<a href="javascript:void(0);" onclick="cleanFileInput(\'attachment1\');">', $txt['clean_attach'], '</a>)';
412
413
		if (!empty($modSettings['attachmentSizeLimit']))
414
			echo '
415
										<input type="hidden" name="MAX_FILE_SIZE" value="' . $modSettings['attachmentSizeLimit'] * 1024 . '">';
416
417
		echo '
418
									</div><!-- .fallback -->
419
								</div><!-- #attachment_upload -->
420
							</dd>';
421
422
		// Add any template changes for an alternative upload system here.
423
		call_integration_hook('integrate_upload_template');
424
425
		echo '
426
							<dd class="smalltext">';
427
428
		// Show some useful information such as allowed extensions, maximum size and amount of attachments allowed.
429
		if (!empty($modSettings['attachmentCheckExtensions']))
430
			echo '
431
								', $txt['allowed_types'], ': ', $context['allowed_extensions'], '<br>';
432
433
		if (!empty($context['attachment_restrictions']))
434
			echo '
435
								', $txt['attach_restrictions'], ' ', implode(', ', $context['attachment_restrictions']), '<br>';
436
437
		if ($context['num_allowed_attachments'] <= count($context['current_attachments']))
438
			echo '
439
								', $txt['attach_limit_nag'], '<br>';
440
441
		if (!$context['can_post_attachment_unapproved'])
442
			echo '
443
								<span class="alert">', $txt['attachment_requires_approval'], '</span>', '<br>';
444
445
		echo '
446
							</dd>
447
						</dl>';
448
	}
449
450
	echo '
451
					</div><!-- #post_additional_options -->';
452
453
	// If the admin enabled the drafts feature, show a draft selection box
454
	if (!empty($modSettings['drafts_post_enabled']) && !empty($context['drafts']) && !empty($modSettings['drafts_show_saved_enabled']) && !empty($options['drafts_show_saved_enabled']))
455
	{
456
		echo '
457
					<div id="post_draft_options_header" class="title_bar">
458
						<h4 class="titlebg">
459
							<span id="postDraftExpand" class="toggle_up floatright" style="display: none;"></span> <strong><a href="#" id="postDraftExpandLink">', $txt['drafts_show'], '</a></strong>
460
						</h4>
461
					</div>
462
					<div id="post_draft_options">
463
						<dl class="settings">
464
							<dt><strong>', $txt['subject'], '</strong></dt>
465
							<dd><strong>', $txt['draft_saved_on'], '</strong></dd>';
466
467
		foreach ($context['drafts'] as $draft)
468
			echo '
469
							<dt>', $draft['link'], '</dt>
470
							<dd>', $draft['poster_time'], '</dd>';
471
		echo '
472
						</dl>
473
					</div>';
474
	}
475
476
	// Is visual verification enabled?
477
	if ($context['require_verification'])
478
		echo '
479
					<div class="post_verification">
480
						<span', !empty($context['post_error']['need_qr_verification']) ? ' class="error"' : '', '>
481
							<strong>', $txt['verification'], ':</strong>
482
						</span>
483
						', template_control_verification($context['visual_verification_id'], 'all'), '
484
					</div>';
485
486
	// Finally, the submit buttons.
487
	echo '
488
					<span id="post_confirm_buttons">
489
						', template_control_richedit_buttons($context['post_box_name']);
0 ignored issues
show
Are you sure the usage of template_control_richedi...ntext['post_box_name']) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
490
491
	// Option to delete an event if user is editing one.
492
	if ($context['make_event'] && !$context['event']['new'])
493
		echo '
494
						<input type="submit" name="deleteevent" value="', $txt['event_delete'], '" data-confirm="', $txt['event_delete_confirm'], '" class="button you_sure">';
495
496
	echo '
497
					</span>
498
				</div><!-- .roundframe -->
499
			</div><!-- #post_area -->
500
			<br class="clear">';
501
502
	// Assuming this isn't a new topic pass across the last message id.
503
	if (isset($context['topic_last_message']))
504
		echo '
505
			<input type="hidden" name="last_msg" value="', $context['topic_last_message'], '">';
506
507
	echo '
508
			<input type="hidden" name="additional_options" id="additional_options" value="', $context['show_additional_options'] ? '1' : '0', '">
509
			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
510
			<input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '">
511
		</form>';
512
513
	echo '
514
		<script>';
515
516
	$newPostsHTML = '
517
		<span id="new_replies"></span>
518
		<div class="windowbg">
519
			<div id="msg%PostID%">
520
			<h5 class="floatleft">
521
				<span>' . $txt['posted_by'] . '</span>
522
				%PosterName%
523
			</h5>
524
			&nbsp;-&nbsp;%PostTime%&nbsp;&#187; <span class="new_posts" id="image_new_%PostID%">' . $txt['new'] . '</span>
525
			<br class="clear">
526
			<div id="msg_%PostID%_ignored_prompt" class="smalltext" style="display: none;">' . $txt['ignoring_user'] . '<a href="#" id="msg_%PostID%_ignored_link" style="%IgnoredStyle%">' . $txt['show_ignore_user_post'] . '</a></div>
527
			<div class="list_posts smalltext" id="msg_%PostID%_body">%PostBody%</div>';
528
529
	if ($context['can_quote'])
530
		$newPostsHTML .= '
531
			<ul class="quickbuttons sf-js-enabled sf-arrows" id="msg_%PostID%_quote" style="touch-action: pan-y;">
532
				<li id="post_modify">
533
					<a href="#postmodify" onclick="return insertQuoteFast(%PostID%);" class="quote_button"><span class="main_icons quote"></span>' . $txt['quote'] . '</a>
534
				</li>
535
			</ul>';
536
537
	$newPostsHTML .= '
538
		</div>';
539
540
	// The functions used to preview a posts without loading a new page.
541
	echo '
542
			var oPreviewPost = new smc_preview_post({
543
				sPreviewSectionContainerID: "preview_section",
544
				sPreviewSubjectContainerID: "preview_subject",
545
				sPreviewBodyContainerID: "preview_body",
546
				sErrorsContainerID: "errors",
547
				sErrorsSeriousContainerID: "error_serious",
548
				sErrorsListContainerID: "error_list",
549
				sCaptionContainerID: "caption_%ID%",
550
				sNewImageContainerID: "image_new_%ID%",
551
				sPostBoxContainerID: ', JavaScriptEscape($context['post_box_name']), ',
552
				bMakePoll: ', $context['make_poll'] ? 'true' : 'false', ',
553
				sTxtPreviewTitle: ', JavaScriptEscape($txt['preview_title']), ',
554
				sTxtPreviewFetch: ', JavaScriptEscape($txt['preview_fetch']), ',
555
				sSessionVar: ', JavaScriptEscape($context['session_var']), ',
556
				newPostsTemplate:', JavaScriptEscape($newPostsHTML);
557
558
	if (!empty($context['current_board']))
559
		echo ',
560
				iCurrentBoard: ', $context['current_board'], '';
561
562
	echo '
563
			});';
564
565
	// Code for showing and hiding additional options.
566
	if (!empty($modSettings['additional_options_collapsable']))
567
		echo '
568
			var oSwapAdditionalOptions = new smc_Toggle({
569
				bToggleEnabled: true,
570
				bCurrentlyCollapsed: ', $context['show_additional_options'] ? 'false' : 'true', ',
571
				funcOnBeforeCollapse: function () {
572
					document.getElementById(\'additional_options\').value = \'0\';
573
				},
574
				funcOnBeforeExpand: function () {
575
					document.getElementById(\'additional_options\').value = \'1\';
576
				},
577
				aSwappableContainers: [
578
					\'post_additional_options\',
579
				],
580
				aSwapImages: [
581
					{
582
						sId: \'postMoreExpandLink\',
583
						altExpanded: \'-\',
584
						altCollapsed: \'+\'
585
					}
586
				],
587
				aSwapLinks: [
588
					{
589
						sId: \'postMoreExpandLink\',
590
						msgExpanded: ', JavaScriptEscape($context['can_post_attachment'] ? $txt['post_additionalopt_attach'] : $txt['post_additionalopt']), ',
591
						msgCollapsed: ', JavaScriptEscape($context['can_post_attachment'] ? $txt['post_additionalopt_attach'] : $txt['post_additionalopt']), '
592
					}
593
				]
594
			});';
595
596
	// Code for showing and hiding drafts
597
	if (!empty($context['drafts']))
598
		echo '
599
			var oSwapDraftOptions = new smc_Toggle({
600
				bToggleEnabled: true,
601
				bCurrentlyCollapsed: true,
602
				aSwappableContainers: [
603
					\'post_draft_options\',
604
				],
605
				aSwapImages: [
606
					{
607
						sId: \'postDraftExpand\',
608
						altExpanded: \'-\',
609
						altCollapsed: \'+\'
610
					}
611
				],
612
				aSwapLinks: [
613
					{
614
						sId: \'postDraftExpandLink\',
615
						msgExpanded: ', JavaScriptEscape($txt['draft_hide']), ',
616
						msgCollapsed: ', JavaScriptEscape($txt['drafts_show']), '
617
					}
618
				]
619
			});';
620
621
	echo '
622
			var oEditorID = "', $context['post_box_name'], '";
623
			var oEditorObject = oEditorHandle_', $context['post_box_name'], ';
624
		</script>';
625
626
	// If the user is replying to a topic show the previous posts.
627
	if (isset($context['previous_posts']) && count($context['previous_posts']) > 0)
628
	{
629
		echo '
630
		<div id="recent" class="flow_hidden main_section">
631
			<div class="cat_bar cat_bar_round">
632
				<h3 class="catbg">', $txt['topic_summary'], '</h3>
633
			</div>
634
			<span id="new_replies"></span>';
635
636
		$ignored_posts = array();
637
		foreach ($context['previous_posts'] as $post)
638
		{
639
			$ignoring = false;
640
			if (!empty($post['is_ignored']))
641
				$ignored_posts[] = $ignoring = $post['id'];
642
643
			echo '
644
			<div class="windowbg">
645
				<div id="msg', $post['id'], '">
646
					<div>
647
						<h5 class="floatleft">
648
							<span>', $txt['posted_by'], '</span> ', $post['poster'], '
649
						</h5>
650
						<span class="smalltext">&nbsp;-&nbsp;', $post['time'], '</span>
651
					</div>';
652
653
			if ($ignoring)
654
				echo '
655
					<div id="msg_', $post['id'], '_ignored_prompt" class="smalltext">
656
						', $txt['ignoring_user'], '
657
						<a href="#" id="msg_', $post['id'], '_ignored_link" style="display: none;">', $txt['show_ignore_user_post'], '</a>
658
					</div>';
659
660
			echo '
661
					<div class="list_posts smalltext" id="msg_', $post['id'], '_body" data-msgid="', $post['id'], '">', $post['message'], '</div>';
662
663
			if ($context['can_quote'])
664
				echo '
665
					<ul class="quickbuttons" id="msg_', $post['id'], '_quote">
666
						<li style="display:none;" id="quoteSelected_', $post['id'], '" data-msgid="', $post['id'], '"><a href="javascript:void(0)"><span class="main_icons quote_selected"></span>', $txt['quote_selected_action'], '</a></li>
667
						<li id="post_modify"><a href="#postmodify" onclick="return insertQuoteFast(', $post['id'], ');"><span class="main_icons quote"></span>', $txt['quote'], '</a></li>
668
					</ul>';
669
670
			echo '
671
				</div><!-- #msg[id] -->
672
			</div><!-- .windowbg -->';
673
		}
674
675
		echo '
676
		</div><!-- #recent -->
677
		<script>
678
			var aIgnoreToggles = new Array();';
679
680
		foreach ($ignored_posts as $post_id)
681
		{
682
			echo '
683
			aIgnoreToggles[', $post_id, '] = new smc_Toggle({
684
				bToggleEnabled: true,
685
				bCurrentlyCollapsed: true,
686
				aSwappableContainers: [
687
					\'msg_', $post_id, '_body\',
688
					\'msg_', $post_id, '_quote\',
689
				],
690
				aSwapLinks: [
691
					{
692
						sId: \'msg_', $post_id, '_ignored_link\',
693
						msgExpanded: \'\',
694
						msgCollapsed: ', JavaScriptEscape($txt['show_ignore_user_post']), '
695
					}
696
				]
697
			});';
698
		}
699
700
		echo '
701
			function insertQuoteFast(messageid)
702
			{
703
				var e = document.getElementById("', $context['post_box_name'], '");
704
				sceditor.instance(e).insertQuoteFast(messageid);
705
706
				return true;
707
			}
708
			function onReceiveOpener(text)
709
			{
710
				var e = document.getElementById("', $context['post_box_name'], '");
711
				sceditor.instance(e).insert(text);
712
			}
713
		</script>';
714
	}
715
}
716
717
/**
718
 * The template for the spellchecker.
719
 */
720
function template_spellcheck()
721
{
722
	global $context, $settings, $txt, $modSettings;
723
724
	// The style information that makes the spellchecker look... like the forum hopefully!
725
	echo '<!DOCTYPE html>
726
<html', $context['right_to_left'] ? ' dir="rtl"' : '', '>
727
	<head>
728
		<meta charset="', $context['character_set'], '">
729
		<title>', $txt['spell_check'], '</title>
730
		<link rel="stylesheet" href="', $settings['theme_url'], '/css/index', $context['theme_variant'], '.css', $context['browser_cache'], '">
731
		<style>
732
			body, td {
733
				font-size: small;
734
				margin: 0;
735
				background: #f0f0f0;
736
				color: #000;
737
				padding: 10px;
738
			}
739
			.highlight {
740
				color: red;
741
				font-weight: bold;
742
			}
743
			#spellview {
744
				border-style: outset;
745
				border: 1px solid black;
746
				padding: 5px;
747
				width: 95%;
748
				height: 314px;
749
				overflow: auto;
750
				background: #ffffff;
751
			}';
752
753
	// As you may expect - we need a lot of javascript for this... load it from the separate files.
754
	echo '
755
		</style>
756
		<script>
757
			var spell_formname = window.opener.spell_formname;
758
			var spell_fieldname = window.opener.spell_fieldname;
759
		</script>
760
		<script src="', $settings['default_theme_url'], '/scripts/spellcheck.js', $context['browser_cache'], '"></script>
761
		<script src="', $settings['default_theme_url'], '/scripts/script.js', $context['browser_cache'], '"></script>
762
		<script>
763
			', $context['spell_js'], '
764
		</script>
765
	</head>
766
	<body onload="nextWord(false);">
767
		<form action="#" method="post" accept-charset="', $context['character_set'], '" name="spellingForm" id="spellingForm" onsubmit="return false;">
768
			<div id="spellview">&nbsp;</div>
769
			<table width="100%">
770
				<tr class="windowbg">
771
					<td style="width: 50%; vertical-align: top">
772
						', $txt['spellcheck_change_to'], '<br>
773
						<input type="text" name="changeto" style="width: 98%;">
774
					</td>
775
					<td style="width: 50%">
776
						', $txt['spellcheck_suggest'], '<br>
777
						<select name="suggestions" style="width: 98%;" size="5" onclick="if (this.selectedIndex != -1) this.form.changeto.value = this.options[this.selectedIndex].text;" ondblclick="replaceWord();">
778
						</select>
779
					</td>
780
				</tr>
781
			</table>
782
			<div class="righttext" style="padding: 4px;">
783
				<input type="button" name="change" value="', $txt['spellcheck_change'], '" onclick="replaceWord();" class="button">
784
				<input type="button" name="changeall" value="', $txt['spellcheck_change_all'], '" onclick="replaceAll();" class="button">
785
				<input type="button" name="ignore" value="', $txt['spellcheck_ignore'], '" onclick="nextWord(false);" class="button">
786
				<input type="button" name="ignoreall" value="', $txt['spellcheck_ignore_all'], '" onclick="nextWord(true);" class="button">
787
			</div>
788
		</form>
789
	</body>
790
</html>';
791
}
792
793
/**
794
 * The template for the AJAX quote feature
795
 */
796
function template_quotefast()
797
{
798
	global $context, $settings, $txt, $modSettings;
799
800
	echo '<!DOCTYPE html>
801
<html', $context['right_to_left'] ? ' dir="rtl"' : '', '>
802
	<head>
803
		<meta charset="', $context['character_set'], '">
804
		<title>', $txt['retrieving_quote'], '</title>
805
		<script src="', $settings['default_theme_url'], '/scripts/script.js', $context['browser_cache'], '"></script>
806
	</head>
807
	<body>
808
		', $txt['retrieving_quote'], '
809
		<div id="temporary_posting_area" style="display: none;"></div>
810
		<script>';
811
812
	if ($context['close_window'])
813
		echo '
814
			window.close();';
815
	else
816
	{
817
		// Lucky for us, Internet Explorer has an "innerText" feature which basically converts entities <--> text. Use it if possible ;)
818
		echo '
819
			var quote = \'', $context['quote']['text'], '\';
820
			var stage = \'createElement\' in document ? document.createElement("DIV") : document.getElementById("temporary_posting_area");
821
822
			if (\'DOMParser\' in window && !(\'opera\' in window))
823
			{
824
				var xmldoc = new DOMParser().parseFromString("<temp>" + \'', $context['quote']['mozilla'], '\'.replace(/\n/g, "_SMF-BREAK_").replace(/\t/g, "_SMF-TAB_") + "</temp>", "text/xml");
825
				quote = xmldoc.childNodes[0].textContent.replace(/_SMF-BREAK_/g, "\n").replace(/_SMF-TAB_/g, "\t");
826
			}
827
			else if (\'innerText\' in stage)
828
			{
829
				setInnerHTML(stage, quote.replace(/\n/g, "_SMF-BREAK_").replace(/\t/g, "_SMF-TAB_").replace(/</g, "&lt;").replace(/>/g, "&gt;"));
830
				quote = stage.innerText.replace(/_SMF-BREAK_/g, "\n").replace(/_SMF-TAB_/g, "\t");
831
			}
832
833
			if (\'opera\' in window)
834
				quote = quote.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, \'"\').replace(/&amp;/g, "&");
835
836
			window.opener.onReceiveOpener(quote);
837
838
			window.focus();
839
			setTimeout("window.close();", 400);';
840
	}
841
	echo '
842
		</script>
843
	</body>
844
</html>';
845
}
846
847
/**
848
 * The form for sending out an announcement
849
 */
850
function template_announce()
851
{
852
	global $context, $txt, $scripturl;
853
854
	echo '
855
	<div id="announcement">
856
		<form action="', $scripturl, '?action=announce;sa=send" method="post" accept-charset="', $context['character_set'], '">
857
			<div class="cat_bar">
858
				<h3 class="catbg">', $txt['announce_title'], '</h3>
859
			</div>
860
			<div class="information">
861
				', $txt['announce_desc'], '
862
			</div>
863
			<div class="windowbg">
864
				<p>
865
					', $txt['announce_this_topic'], ' <a href="', $scripturl, '?topic=', $context['current_topic'], '.0">', $context['topic_subject'], '</a>
866
				</p>
867
				<ul>';
868
869
	foreach ($context['groups'] as $group)
870
		echo '
871
					<li>
872
						<label for="who_', $group['id'], '"><input type="checkbox" name="who[', $group['id'], ']" id="who_', $group['id'], '" value="', $group['id'], '" checked> ', $group['name'], '</label> <em>(', $group['member_count'], ')</em>
873
					</li>';
874
875
	echo '
876
					<li>
877
						<label for="checkall"><input type="checkbox" id="checkall" onclick="invertAll(this, this.form);" checked> <em>', $txt['check_all'], '</em></label>
878
					</li>
879
				</ul>
880
				<hr>
881
				<div id="confirm_buttons">
882
					<input type="submit" value="', $txt['post'], '" class="button">
883
					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
884
					<input type="hidden" name="topic" value="', $context['current_topic'], '">
885
					<input type="hidden" name="move" value="', $context['move'], '">
886
					<input type="hidden" name="goback" value="', $context['go_back'], '">
887
				</div>
888
				<br class="clear_right">
889
			</div><!-- .windowbg -->
890
		</form>
891
	</div><!-- #announcement -->
892
	<br>';
893
}
894
895
/**
896
 * The confirmation/progress page, displayed after the admin has clicked the button to send the announcement.
897
 */
898
function template_announcement_send()
899
{
900
	global $context, $txt, $scripturl;
901
902
	echo '
903
	<div id="announcement">
904
		<form action="', $scripturl, '?action=announce;sa=send" method="post" accept-charset="', $context['character_set'], '" name="autoSubmit" id="autoSubmit">
905
			<div class="windowbg">
906
				<p>
907
					', $txt['announce_sending'], ' <a href="', $scripturl, '?topic=', $context['current_topic'], '.0" target="_blank" rel="noopener">', $context['topic_subject'], '</a>
908
				</p>
909
				<div class="progress_bar">
910
					<span>', $context['percentage_done'], '% ', $txt['announce_done'], '</span>
911
					<div class="bar" style="width: ', $context['percentage_done'], '%;"></div>
912
				</div>
913
				<hr>
914
				<div id="confirm_buttons">
915
					<input type="submit" name="b" value="', $txt['announce_continue'], '" class="button">
916
					<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '">
917
					<input type="hidden" name="topic" value="', $context['current_topic'], '">
918
					<input type="hidden" name="move" value="', $context['move'], '">
919
					<input type="hidden" name="goback" value="', $context['go_back'], '">
920
					<input type="hidden" name="start" value="', $context['start'], '">
921
					<input type="hidden" name="membergroups" value="', $context['membergroups'], '">
922
				</div>
923
				<br class="clear_right">
924
			</div><!-- .windowbg -->
925
		</form>
926
	</div><!-- #announcement -->
927
	<br>
928
	<script>
929
		var countdown = 2;
930
		doAutoSubmit();
931
932
		function doAutoSubmit()
933
		{
934
			if (countdown == 0)
935
				document.forms.autoSubmit.submit();
936
			else if (countdown == -1)
937
				return;
938
939
			document.forms.autoSubmit.b.value = "', $txt['announce_continue'], ' (" + countdown + ")";
940
			countdown--;
941
942
			setTimeout("doAutoSubmit();", 1000);
943
		}
944
	</script>';
945
}
946
947
/**
948
 * Prints the input fields in the form's header (subject, message icon, guest name & email, etc.)
949
 *
950
 * Mod authors can use the 'integrate_post_end' hook to modify or add to these (see Post.php).
951
 *
952
 * Theme authors can customize the output in a couple different ways:
953
 * 1. Change specific values in the $context['posting_fields'] array.
954
 * 2. Add an 'html' element to the 'label' and/or 'input' elements of the field they want to
955
 *    change. This should contain the literal HTML string to be printed.
956
 *
957
 * See the documentation in Post.php for more info on the $context['posting_fields'] array.
958
 */
959
function template_post_header()
960
{
961
	global $context, $txt;
962
963
	// Sanity check: submitting the form won't work without at least a subject field
964
	if (empty($context['posting_fields']['subject']) || !is_array($context['posting_fields']['subject']))
965
	{
966
		$context['posting_fields']['subject'] = array(
967
			'label' => array('html' => '<label for="subject" id="caption_subject">' . $txt['subject'] . '</label>'),
968
			'input' => array('html' => '<input type="text" id="subject" name="subject" value="' . $context['subject'] . '" size="80" maxlength="80" required>')
969
		);
970
	}
971
972
	// THEME AUTHORS: Above this line is a great place to make customizations to the posting_fields array
973
974
	// Start printing the header
975
	echo '
976
					<dl id="post_header">';
977
978
	foreach ($context['posting_fields'] as $pfid => $pf)
979
	{
980
		// We need both a label and an input
981
		if (empty($pf['label']) || empty($pf['input']))
982
			continue;
983
984
		// The labels are pretty simple...
985
		echo '
986
						<dt class="clear pf_', $pfid, '">';
987
988
		// Any leading HTML before the label
989
		if (!empty($pf['label']['before']))
990
			echo '
991
							', $pf['label']['before'];
992
993
		if (!empty($pf['label']['html']))
994
			echo $pf['label']['html'];
995
		else
996
			echo '
997
							<label', ($pf['input']['type'] === 'radio_select' ? '' : ' for="' . (!empty($pf['input']['attributes']['id']) ? $pf['input']['attributes']['id'] : $pfid) . '"'), ' id="caption_', $pfid, '"', !empty($pf['label']['class']) ? ' class="' . $pf['label']['class'] . '"' : '', '>', $pf['label']['text'], '</label>';
998
999
		// Any trailing HTML after the label
1000
		if (!empty($pf['label']['after']))
1001
			echo '
1002
							', $pf['label']['after'];
1003
1004
		echo '
1005
						</dt>';
1006
1007
		// Here's where the fun begins...
1008
		echo '
1009
						<dd class="pf_', $pfid, '">';
1010
1011
		// Any leading HTML before the main input
1012
		if (!empty($pf['input']['before']))
1013
			echo '
1014
							', $pf['input']['before'];
1015
1016
		// If there is a literal HTML string already defined, just print it.
1017
		if (!empty($pf['input']['html']))
1018
		{
1019
			echo $pf['input']['html'];
1020
		}
1021
		// Simple text inputs and checkboxes
1022
		elseif (in_array($pf['input']['type'], array('text', 'password', 'color', 'date', 'datetime-local', 'email', 'month', 'number', 'range', 'tel', 'time', 'url', 'week', 'checkbox')))
1023
		{
1024
			echo '
1025
							<input type="', $pf['input']['type'], '"';
1026
1027
			if (empty($pf['input']['attributes']['id']))
1028
				echo ' id="', $pfid, '"';
1029
1030
			if (empty($pf['input']['attributes']['name']))
1031
				echo ' name="', $pfid, '"';
1032
1033
			if (!empty($pf['input']['attributes']) && is_array($pf['input']['attributes']))
1034
			{
1035
				foreach ($pf['input']['attributes'] as $attribute => $value)
1036
				{
1037
					if (is_bool($value))
1038
						echo $value ? ' ' . $attribute : '';
1039
					else
1040
						echo ' ', $attribute, '="', $value, '"';
1041
				}
1042
			}
1043
1044
			echo ' tabindex="', $context['tabindex']++, '">';
1045
		}
1046
		// textarea
1047
		elseif ($pf['input']['type'] === 'textarea')
1048
		{
1049
			echo '
1050
							<textarea';
1051
1052
			if (empty($pf['input']['attributes']['id']))
1053
				echo ' id="', $pfid, '"';
1054
1055
			if (empty($pf['input']['attributes']['name']))
1056
				echo ' name="', $pfid, '"';
1057
1058
			if (!empty($pf['input']['attributes']) && is_array($pf['input']['attributes']))
1059
			{
1060
				foreach ($pf['input']['attributes'] as $attribute => $value)
1061
				{
1062
					if ($attribute === 'value')
1063
						continue;
1064
					elseif (is_bool($value))
1065
						echo $value ? ' ' . $attribute : '';
1066
					else
1067
						echo ' ', $attribute, '="', $value, '"';
1068
				}
1069
			}
1070
1071
			echo ' tabindex="', $context['tabindex']++, '">', !empty($pf['input']['attributes']['value']) ? $pf['input']['attributes']['value'] : '', '</textarea>';
1072
		}
1073
		// Select menus are more complicated
1074
		elseif ($pf['input']['type'] === 'select' && is_array($pf['input']['options']))
1075
		{
1076
			// The select element itself
1077
			echo '
1078
							<select';
1079
1080
			if (empty($pf['input']['attributes']['id']))
1081
				echo ' id="', $pfid, '"';
1082
1083
			if (empty($pf['input']['attributes']['name']))
1084
				echo ' name="', $pfid, !empty($pf['input']['attributes']['multiple']) ? '[]' : '', '"';
1085
1086
			if (!empty($pf['input']['attributes']) && is_array($pf['input']['attributes']))
1087
			{
1088
				foreach ($pf['input']['attributes'] as $attribute => $value)
1089
				{
1090
					if (is_bool($value))
1091
						echo $value ? ' ' . $attribute : '';
1092
					else
1093
						echo ' ', $attribute, '="', $value, '"';
1094
				}
1095
			}
1096
1097
			echo ' tabindex="', $context['tabindex']++, '">';
1098
1099
			// The options
1100
			foreach ($pf['input']['options'] as $optlabel => $option)
1101
			{
1102
				// An option containing options is an optgroup
1103
				if (!empty($option['options']) && is_array($option['options']))
1104
				{
1105
					echo '
1106
								<optgroup';
1107
1108
					if (empty($option['label']))
1109
						echo ' label="', $optlabel, '"';
1110
1111
					if (!empty($option) && is_array($option))
1112
					{
1113
						foreach ($option as $attribute => $value)
1114
						{
1115
							if ($attribute === 'options')
1116
								continue;
1117
							elseif (is_bool($value))
1118
								echo $value ? ' ' . $attribute : '';
1119
							else
1120
								echo ' ', $attribute, '="', $value, '"';
1121
						}
1122
					}
1123
1124
					echo '>';
1125
1126
					foreach ($option['options'] as $grouped_optlabel => $grouped_option)
1127
					{
1128
						echo '
1129
									<option';
1130
1131
						foreach ($grouped_option as $attribute => $value)
1132
						{
1133
							if (is_bool($value))
1134
								echo $value ? ' ' . $attribute : '';
1135
							else
1136
								echo ' ', $attribute, '="', $value, '"';
1137
						}
1138
1139
						echo '>', $grouped_option['label'], '</option>';
1140
1141
					}
1142
1143
					echo '
1144
								</optgroup>';
1145
				}
1146
				// Simple option
1147
				else
1148
				{
1149
					echo '
1150
								<option';
1151
1152
					foreach ($option as $attribute => $value)
1153
					{
1154
						if (is_bool($value))
1155
							echo $value ? ' ' . $attribute : '';
1156
						else
1157
							echo ' ', $attribute, '="', $value, '"';
1158
					}
1159
1160
					echo '>', $optlabel, '</option>';
1161
				}
1162
			}
1163
1164
			// Close the select element
1165
			echo '
1166
							</select>';
1167
		}
1168
		// Radio_select makes a div with some radio buttons in it
1169
		elseif ($pf['input']['type'] === 'radio_select' && is_array($pf['input']['options']))
1170
		{
1171
			echo '
1172
							<div';
1173
1174
			if (!empty($pf['input']['attributes']) && is_array($pf['input']['attributes']))
1175
			{
1176
				foreach ($pf['input']['attributes'] as $attribute => $value)
1177
				{
1178
					if ($attribute === 'name')
1179
						continue;
1180
					elseif (is_bool($value))
1181
						echo $value ? ' ' . $attribute : '';
1182
					else
1183
						echo ' ', $attribute, '="', $value, '"';
1184
				}
1185
			}
1186
1187
			echo '>';
1188
1189
			foreach ($pf['input']['options'] as $optlabel => $option)
1190
			{
1191
				echo '
1192
							<label style="margin-right:2ch"><input type="radio" name="', !empty($pf['input']['attributes']['name']) ? $pf['input']['attributes']['name'] : $pfid, '"';
1193
1194
				foreach ($option as $attribute => $value)
1195
				{
1196
					if ($attribute === 'label')
1197
						continue;
1198
					elseif (is_bool($value))
1199
						echo $value ? ' ' . ($attribute === 'selected' ? 'checked' : $attribute) : '';
1200
					else
1201
						echo ' ', $attribute, '="', $value, '"';
1202
				}
1203
1204
				echo ' tabindex="', $context['tabindex']++, '"> ', isset($option['label']) ? $option['label'] : $optlabel, '</label>';
1205
			}
1206
1207
			echo '
1208
							</div>';
1209
		}
1210
1211
		// Any trailing HTML after the main input
1212
		if (!empty($pf['input']['after']))
1213
			echo '
1214
							', $pf['input']['after'];
1215
1216
		echo '
1217
						</dd>';
1218
	}
1219
1220
	echo '
1221
					</dl>';
1222
}
1223
1224
?>