Passed
Push — master ( d9e5dd...36764d )
by Spuds
01:07 queued 26s
created

Ila_Integrate::validate_options()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 1
nop 0
dl 0
loc 14
ccs 0
cts 9
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @name      ElkArte Forum
5
 * @copyright ElkArte Forum contributors
6
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
7
 *
8
 * @version 1.1.9
9
 *
10
 */
11
12
/**
13
 * Class Ila_Integrate
14
 */
15
class Ila_Integrate
16
{
17
	/** @var string holds the rendered html from the bbc [attach] tag */
18
	public static $typeTag = '';
19
20
	/**
21
	 * Register ILA hooks to the system
22
	 *
23
	 * @return array
24
	 */
25
	public static function register()
26
	{
27
		global $modSettings;
28
29
		if (empty($modSettings['attachment_inline_enabled']))
30
		{
31
			return array();
32
		}
33
34
		// $hook, $function, $file
35
		return array(
36
			array('integrate_additional_bbc', 'Ila_Integrate::integrate_additional_bbc'),
37
			array('integrate_before_prepare_display_context', 'Ila_Integrate::integrate_before_prepare_display_context'),
38
			array('integrate_post_bbc_parser', 'Ila_Integrate::integrate_post_parser')
39
		);
40
	}
41
42
	/**
43
	 * Register ACP config hooks for setting values
44
	 *
45
	 * @return array
46
	 */
47
	public static function settingsRegister()
48
	{
49
		// $hook, $function, $file
50
		return array(
51
			array('integrate_modify_attachment_settings', 'Ila_Integrate::integrate_modify_attachment_settings'),
52
		);
53
	}
54
55
	/**
56
	 * After parse is done, we need to sub in the message id for proper lightbox navigation
57
	 *
58
	 * @param string $message
59
	 */
60
	public static function integrate_post_parser(&$message)
61
	{
62
		global $context;
63
64
		$lighbox_message = 'data-lightboxmessage="' . (!empty($context['id_msg']) ? $context['id_msg'] : '0') . '"';
65
		$message = str_replace('data-lightboxmessage="0"', $lighbox_message, $message);
66
	}
67
68
	/**
69
	 * - Adds in new BBC code tags for use with inline images
70
	 *
71
	 * @param array $additional_bbc
72
	 */
73
	public static function integrate_additional_bbc(&$additional_bbc)
74
	{
75
		global $scripturl, $modSettings, $txt;
76
77
		// Generally we don't want to render inside of these tags ...
78
		$disallow = array(
79
			'quote' => 1,
80
			'code' => 1,
81
			'nobbc' => 1,
82
			'html' => 1,
83
			'php' => 1,
84
		);
85
86
		// Why enable it to disable the tags, oh well
87
		$disabledBBC = empty($modSettings['disabledBBC']) ? array() : explode(',', $modSettings['disabledBBC']);
88
		$disabled = in_array('attach', $disabledBBC);
89
		$disabledUrl = in_array('attachurl', $disabledBBC);
90
91
		// Want to see them in quotes eh?
92
		if (!empty($modSettings['attachment_inline_quotes']))
93
		{
94
			unset($disallow['quote']);
95
		}
96
97
		// Add ILA codes
98
		$additional_bbc = array_merge($additional_bbc, array(
99
			// Just a simple attach [attach][/attach]
100
			array(
101
				\BBC\Codes::ATTR_TAG => 'attach',
102
				\BBC\Codes::ATTR_TYPE => \BBC\Codes::TYPE_UNPARSED_CONTENT,
103
				\BBC\Codes::ATTR_DISABLED => $disabled,
104
				\BBC\Codes::ATTR_RESET => '',
105
				\BBC\Codes::ATTR_CONTENT => &self::$typeTag,
106
				\BBC\Codes::ATTR_VALIDATE => $disabled ? null : self::buildTag(),
107
				\BBC\Codes::ATTR_DISALLOW_PARENTS => $disallow,
108
				\BBC\Codes::ATTR_DISABLED_CONTENT => '<a href="' . $scripturl . '?action=dlattach;attach=$1">(' . $txt['link'] . '-$1)</a> ',
109
				\BBC\Codes::ATTR_BLOCK_LEVEL => false,
110
				\BBC\Codes::ATTR_AUTOLINK => false,
111
				\BBC\Codes::ATTR_LENGTH => 6,
112
			),
113
			// Attach, with perhaps a type [attach type=xyz][/attach]
114
			array(
115
				\BBC\Codes::ATTR_TAG => 'attach',
116
				\BBC\Codes::ATTR_TYPE => \BBC\Codes::TYPE_UNPARSED_CONTENT,
117
				\BBC\Codes::ATTR_PARAM => array(
118
					'type' => array(
119
						\BBC\Codes::PARAM_ATTR_OPTIONAL => true,
120
						\BBC\Codes::PARAM_ATTR_VALUE => ';$1',
121
						\BBC\Codes::PARAM_ATTR_MATCH => '(thumb|image)',
122
					),
123
				),
124
				\BBC\Codes::ATTR_DISABLED => $disabled,
125
				\BBC\Codes::ATTR_RESET => '~~{type}',
126
				\BBC\Codes::ATTR_CONTENT => &self::$typeTag,
127
				\BBC\Codes::ATTR_VALIDATE => $disabled ? null : self::buildTag(),
128
				\BBC\Codes::ATTR_DISALLOW_PARENTS => $disallow,
129
				\BBC\Codes::ATTR_DISABLED_CONTENT => '<a href="' . $scripturl . '?action=dlattach;attach=$1">(' . $txt['link'] . '-$1)</a> ',
130
				\BBC\Codes::ATTR_BLOCK_LEVEL => false,
131
				\BBC\Codes::ATTR_AUTOLINK => false,
132
				\BBC\Codes::ATTR_LENGTH => 6,
133
			),
134
			// Require a width with optional height/align, allows either use of full image and/or ;thumb
135
			// [attach width=300 align=??][/attach]
136
			array(
137
				\BBC\Codes::ATTR_TAG => 'attach',
138
				\BBC\Codes::ATTR_TYPE => \BBC\Codes::TYPE_UNPARSED_CONTENT,
139
				\BBC\Codes::ATTR_PARAM => array(
140
					'width' => array(
141
						\BBC\Codes::PARAM_ATTR_VALUE => 'width:100%;max-width:$1px;',
142
						\BBC\Codes::PARAM_ATTR_MATCH => '(\d+)',
143
					),
144
					'height' => array(
145
						\BBC\Codes::PARAM_ATTR_OPTIONAL => true,
146
						\BBC\Codes::PARAM_ATTR_VALUE => 'max-height:$1px;',
147
						\BBC\Codes::PARAM_ATTR_MATCH => '(\d+)',
148
					),
149
					'align' => array(
150
						\BBC\Codes::PARAM_ATTR_OPTIONAL => true,
151
						\BBC\Codes::PARAM_ATTR_VALUE => 'float$1',
152
						\BBC\Codes::PARAM_ATTR_MATCH => '(right|left|center)',
153
					),
154
				),
155
				\BBC\Codes::ATTR_DISABLED => $disabled,
156
				\BBC\Codes::ATTR_RESET => '{width}{height}~{align}',
157
				\BBC\Codes::ATTR_CONTENT => &self::$typeTag,
158
				\BBC\Codes::ATTR_VALIDATE => $disabled ? null : self::buildTag(),
159
				\BBC\Codes::ATTR_DISALLOW_PARENTS => $disallow,
160
				\BBC\Codes::ATTR_DISABLED_CONTENT => '<a href="' . $scripturl . '?action=dlattach;attach=$1">(' . $txt['link'] . '-$1)</a> ',
161
				\BBC\Codes::ATTR_BLOCK_LEVEL => false,
162
				\BBC\Codes::ATTR_AUTOLINK => false,
163
				\BBC\Codes::ATTR_LENGTH => 6,
164
			),
165
			// Require a height with option width/align [attach height=300 align=??][/attach]
166
			array(
167
				\BBC\Codes::ATTR_TAG => 'attach',
168
				\BBC\Codes::ATTR_TYPE => \BBC\Codes::TYPE_UNPARSED_CONTENT,
169
				\BBC\Codes::ATTR_PARAM => array(
170
					'height' => array(
171
						\BBC\Codes::PARAM_ATTR_VALUE => 'max-height:$1px;',
172
						\BBC\Codes::PARAM_ATTR_MATCH => '(\d+)',
173
					),
174
					'width' => array(
175
						\BBC\Codes::PARAM_ATTR_OPTIONAL => true,
176
						\BBC\Codes::PARAM_ATTR_VALUE => 'width:100%;max-width:$1px;',
177
						\BBC\Codes::PARAM_ATTR_MATCH => '(\d+)',
178
					),
179
					'align' => array(
180
						\BBC\Codes::PARAM_ATTR_OPTIONAL => true,
181
						\BBC\Codes::PARAM_ATTR_VALUE => 'float$1',
182
						\BBC\Codes::PARAM_ATTR_MATCH => '(right|left|center)',
183
					),
184
				),
185
				\BBC\Codes::ATTR_DISABLED => $disabled,
186
				\BBC\Codes::ATTR_RESET => '{width}{height}~{align}',
187
				\BBC\Codes::ATTR_CONTENT => &self::$typeTag,
188
				\BBC\Codes::ATTR_VALIDATE => $disabled ? null : self::buildTag(),
189
				\BBC\Codes::ATTR_DISALLOW_PARENTS => $disallow,
190
				\BBC\Codes::ATTR_DISABLED_CONTENT => '<a href="' . $scripturl . '?action=dlattach;attach=$1">(' . $txt['link'] . '-$1)</a> ',
191
				\BBC\Codes::ATTR_BLOCK_LEVEL => false,
192
				\BBC\Codes::ATTR_AUTOLINK => false,
193
				\BBC\Codes::ATTR_LENGTH => 6,
194
			),
195
			// Align with an optional a type? [attach align=right type=thumb][/attach]
196
			array(
197
				\BBC\Codes::ATTR_TAG => 'attach',
198
				\BBC\Codes::ATTR_TYPE => \BBC\Codes::TYPE_UNPARSED_CONTENT,
199
				\BBC\Codes::ATTR_PARAM => array(
200
					'align' => array(
201
						\BBC\Codes::PARAM_ATTR_VALUE => 'float$1',
202
						\BBC\Codes::PARAM_ATTR_MATCH => '(right|left|center)',
203
					),
204
					'type' => array(
205
						\BBC\Codes::PARAM_ATTR_OPTIONAL => true,
206
						\BBC\Codes::PARAM_ATTR_VALUE => ';$1',
207
						\BBC\Codes::PARAM_ATTR_MATCH => '(thumb|image)',
208
					),
209
				),
210
				\BBC\Codes::ATTR_DISABLED => $disabled,
211
				\BBC\Codes::ATTR_RESET => '~{align}~{type}',
212
				\BBC\Codes::ATTR_CONTENT => &self::$typeTag,
213
				\BBC\Codes::ATTR_VALIDATE => $disabled ? null : self::buildTag(),
214
				\BBC\Codes::ATTR_DISALLOW_PARENTS => $disallow,
215
				\BBC\Codes::ATTR_DISABLED_CONTENT => '<a href="' . $scripturl . '?action=dlattach;attach$1">(' . $txt['link'] . '-$1)</a> ',
216
				\BBC\Codes::ATTR_BLOCK_LEVEL => false,
217
				\BBC\Codes::ATTR_AUTOLINK => false,
218
				\BBC\Codes::ATTR_LENGTH => 6,
219
			),
220
			// [attachurl=xx] -- no image but a link with some details
221
			array(
222
				\BBC\Codes::ATTR_TAG => 'attachurl',
223
				\BBC\Codes::ATTR_TYPE => \BBC\Codes::TYPE_UNPARSED_CONTENT,
224
				\BBC\Codes::ATTR_DISABLED => $disabledUrl,
225
				\BBC\Codes::ATTR_CONTENT => '$1',
226
				\BBC\Codes::ATTR_VALIDATE => $disabledUrl ? null : self::validate_url(),
227
				\BBC\Codes::ATTR_DISALLOW_PARENTS => $disallow,
228
				\BBC\Codes::ATTR_DISABLED_CONTENT => '<a href="' . $scripturl . '?action=dlattach;attach=$1">(' . $txt['link'] . '-$1)</a> ',
229
				\BBC\Codes::ATTR_BLOCK_LEVEL => false,
230
				\BBC\Codes::ATTR_AUTOLINK => false,
231
				\BBC\Codes::ATTR_LENGTH => 9,
232
			),
233
		));
234
	}
235
236
	/**
237
	 * This provides for the control of returned tags.  The tag will be different based on
238
	 * - Preview, Approval Y/N, Image Y/N, File mime type and width, height, align, type attributes
239
	 *
240
	 * - Determines if the ILA is an image or not
241
	 * - Sets the lightbox attributes if an image is identified
242
	 * - Sets a pending approval image if the attachment is not approved and not a preview
243
	 * - Keeps track of attachment usage to prevent displaying below the post
244
	 * - Sets self::$typeTag which is a reference to the tag content attribute
245
	 *
246
	 * @return callable
247
	 */
248
	public static function buildTag()
249
	{
250
		global $modSettings, $scripturl;
251
252
		return static function ($tag, &$data, $disabled) use ($modSettings, $scripturl) {
253
			$num = $data;
254
			$attachment = [];
255
			$preview = self::isPreview($num);
256
257
			// Was this tag dynamically disabled from the parser, aka print page or other addon?
258
			if (in_array('attach', $disabled, true))
259
			{
260
				self::$typeTag = $tag[\BBC\Codes::ATTR_DISABLED_CONTENT];
261
				return;
262
			}
263
264
			// Not a preview, then determine the actual type of attachment we are dealing with
265
			if (!$preview)
266
			{
267
				require_once(SUBSDIR . '/Attachments.subs.php');
268
				$attachment = isAttachmentImage($num);
269
			}
270
271
			// Grab the tags content value, at this point it will have completed parameter exchange
272
			$parameters = isset($tag[\BBC\Codes::ATTR_CONTENT]) ? $tag[\BBC\Codes::ATTR_CONTENT] : '~~~';
273
			$parameters = explode('~', $parameters);
274
			$style = isset($parameters[0]) ? $parameters[0] : '';
275
			$class = isset($parameters[1]) ? $parameters[1] : '';
276
			$type = isset($parameters[2]) ? $parameters[2] : (empty($style) ? ';thumb' : '');
277
278
			// Not approved gets a bland not found image
279
			if (empty($attachment['is_approved']) && !$preview)
280
			{
281
				self::$typeTag = '
282
					<img src="' . $scripturl . '?action=dlattach;id=ila" alt="X" class="bbc_img' . $class . '" loading="lazy" />';
283
			}
284
			// An image will get the light box treatment
285
			elseif (!empty($attachment['is_image']) || $preview)
286
			{
287
				$type = !empty($modSettings['attachmentThumbnails']) ? $type : '';
288
				$alt = Util::htmlspecialchars(isset($attachment['filename']) ? $attachment['filename'] : 'X');
289
				self::$typeTag = '
290
					<a id="link_$1" data-lightboximage="$1" data-lightboxmessage="0" href="' . $scripturl . '?action=dlattach;attach=$1;image">
291
						<img src="' . $scripturl . '?action=dlattach;attach=$1' . $type . '" style="' . $style . '" alt="' . $alt . '" class="bbc_img ' . $class . '" loading="lazy" />
292
					</a>';
293
			}
294
			// Not an image, determine a mime thumbnail or use a default thumbnail
295
			else
296
			{
297
				$thumbUrl = returnMimeThumb((isset($attachment['fileext']) ? $attachment['fileext'] : ''), true);
298
				if ($attachment === false)
299
				{
300
					self::$typeTag = '
301
					<img src="' . $thumbUrl . '" alt="X" class="bbc_img' . $class . '" loading="lazy"/>';
302
				}
303
				else
304
				{
305
					self::$typeTag = '
306
					<a href="' . $scripturl . '?action=dlattach;attach=$num">
307
						<img src="' . $thumbUrl . '" alt="' . $attachment['filename'] . '" class="bbc_img ' . $class . '" loading="lazy" />
308
					</a>';
309
				}
310
			}
311
312
			// The above indentation needs to be removed, otherwise it will appear in the final markup
313
			self::$typeTag = preg_replace('~[\n\t]~', '', self::$typeTag);
314
315
			self::trackIlaUsage($num);
316
		};
317
	}
318
319
	/**
320
	 * This is prevents a little repetition and provides a some control for url tags
321
	 *
322
	 * - Determines if the ILA is an image or not
323
	 * - Keeps track of attachment usage to prevent displaying below the post
324
	 *
325
	 * @return callable
326
	 */
327
	public static function validate_url()
328
	{
329
		global $txt, $scripturl;
330
331
		return static function ($tag, &$data) use ($txt, $scripturl) {
332
			$num = $data;
333
			$attachment = false;
334
335
			// Not a preview, then sanitize the attach id and determine the details
336
			$preview = self::isPreview($num);
337
			if (!$preview)
338
			{
339
				require_once(SUBSDIR . '/Attachments.subs.php');
340
				$attachment = isAttachmentImage($num);
341
			}
342
343
			// Not approved gets a bland message
344
			if (empty($attachment['is_approved']) && !$preview)
345
			{
346
				$data = '
347
				<a href="#">
348
					<i class="icon icon-small i-paperclip"></i>&nbsp;' . $txt['awaiting_approval'] . '
349
				</a>&nbsp;';
350
			}
351
			// If we got the details ...
352
			elseif ($attachment)
353
			{
354
				$data = '
355
				<a href="' . $scripturl . '?action=dlattach;attach=$num">
356
					<i class="icon icon-small i-paperclip"></i>&nbsp;' . $attachment['filename'] . '
357
				</a>&nbsp;(' . $attachment['size'] . ($attachment['is_image'] ? ' ' . $attachment['width'] . 'x' . $attachment['height'] : '') . ')';
358
			}
359
			else
360
			{
361
				$data = '
362
				<a href="' . $scripturl . '?action=dlattach;attach=$num">
363
					<i class="icon icon-small i-paperclip"></i>&nbsp;' . $num . '
364
				</a>';
365
			}
366
367
			$data = preg_replace('~[\n\t]~', '', $data);
368
369
			self::trackIlaUsage($num);
370
		};
371
	}
372
373
	/**
374
	 * Checks if this is a request for a yet posted attachment preview
375
	 * Will int the attachment number if not a preview
376
	 *
377
	 * @param string $data if ila will be (int)'ed otherwise left alone
378
	 * @return bool
379
	 */
380
	public static function isPreview(&$data)
381
	{
382
		global $user_info;
383
384
		if (strpos($data, 'post_tmp_' . $user_info['id'] . '_') === false)
385
		{
386
			$data = (int) $data;
387
			return false;
388
		}
389
390
		return true;
391
	}
392
393
	/**
394
	 * Keeps track of attachment usage to prevent displaying below the post
395
	 *
396
	 * @param int $data
397
	 */
398
	public static function trackIlaUsage($data)
399
	{
400
		global $context;
401
402
		$context['ila_dont_show_attach_below'][] = $data;
403
		$context['ila_dont_show_attach_below'] = array_unique($context['ila_dont_show_attach_below']);
404
	}
405
406
	/**
407
	 * Settings hook for the admin panel
408
	 *
409
	 * What it does:
410
	 *
411
	 * - Defines our settings array and uses our settings class to manage the data
412
	 *
413
	 * @param array $config_vars
414
	 */
415
	public static function integrate_modify_attachment_settings(&$config_vars)
416
	{
417
		$config_vars[] = ['title', 'attachment_inline_title'];
418
		$config_vars[] = ['check', 'attachment_inline_enabled'];
419
		$config_vars[] = ['check', 'attachment_inline_quotes'];
420
	}
421
422
	/**
423
	 * Display controller hook, called from prepareDisplayContext_callback integrate_before_prepare_display_context
424
	 *
425
	 * What it does:
426
	 *
427
	 * - Drops attachments from the message if they were rendered inline
428
	 *
429
	 * @param array $message
430
	 */
431
	public static function integrate_before_prepare_display_context(&$message)
432
	{
433
		global $context, $attachments;
434
435
		$context['ila'] = array();
436
437
		if (empty($context['ila_dont_show_attach_below']) || empty($attachments[$message['id_msg']]))
438
		{
439
			return;
440
		}
441
442
		// If the attachment has been used inline, drop it so its not shown below the message as well
443
		foreach ($attachments[$message['id_msg']] as $id => $attachcheck)
444
		{
445
			if ($attachcheck['approved'] && in_array($attachcheck['id_attach'], $context['ila_dont_show_attach_below']))
446
			{
447
				unset($attachments[$message['id_msg']][$id]);
448
				$context['ila'][] = $attachcheck;
449
			}
450
		}
451
	}
452
}
453