conversation.php 54.6 KB
Newer Older
friendica's avatar
friendica committed
1
<?php /** @file */
2

3 4
require_once('include/items.php');

5

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
function item_extract_images($body) {

	$saved_image = array();
	$orig_body = $body;
	$new_body = '';

	$cnt = 0;
	$img_start = strpos($orig_body, '[img');
	$img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
	$img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
	while(($img_st_close !== false) && ($img_end !== false)) {

		$img_st_close++; // make it point to AFTER the closing bracket
		$img_end += $img_start;

		if(! strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) {
			// This is an embedded image

Zach Prezkuta's avatar
Zach Prezkuta committed
24
			$saved_image[$cnt] = substr($orig_body, $img_start + $img_st_close, $img_end - ($img_start + $img_st_close));
25
			$new_body = $new_body . substr($orig_body, 0, $img_start) . '[!#saved_image' . $cnt . '#!]';
Zach Prezkuta's avatar
Zach Prezkuta committed
26 27

			$cnt++;
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
		}
		else
			$new_body = $new_body . substr($orig_body, 0, $img_end + strlen('[/img]'));

		$orig_body = substr($orig_body, $img_end + strlen('[/img]'));

		if($orig_body === false) // in case the body ends on a closing image tag
			$orig_body = '';

		$img_start = strpos($orig_body, '[img');
		$img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
		$img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
	}

	$new_body = $new_body . $orig_body;

	return array('body' => $new_body, 'images' => $saved_image);
45 46
}

47 48 49

function item_redir_and_replace_images($body, $images, $cid) {

Zach Prezkuta's avatar
Zach Prezkuta committed
50 51
	$origbody = $body;
	$newbody = '';
52

redmatrix's avatar
redmatrix committed
53
	$observer = App::get_observer();
54 55 56
	$obhash = (($observer) ? $observer['xchan_hash'] : '');
	$obaddr = (($observer) ? $observer['xchan_addr'] : '');

57 58
	for($i = 0; $i < count($images); $i++) {
		$search = '/\[url\=(.*?)\]\[!#saved_image' . $i . '#!\]\[\/url\]' . '/is';
59
		$replace = '[url=' . magiclink_url($obhash,$obaddr,'$1') . '][!#saved_image' . $i . '#!][/url]' ;
60

Zach Prezkuta's avatar
Zach Prezkuta committed
61 62 63 64 65 66
		$img_end = strpos($origbody, '[!#saved_image' . $i . '#!][/url]') + strlen('[!#saved_image' . $i . '#!][/url]');
		$process_part = substr($origbody, 0, $img_end);
		$origbody = substr($origbody, $img_end);

		$process_part = preg_replace($search, $replace, $process_part);
		$newbody = $newbody . $process_part;
67
	}
Zach Prezkuta's avatar
Zach Prezkuta committed
68
	$newbody = $newbody . $origbody;
69 70 71 72 73 74

	$cnt = 0;
	foreach($images as $image) {
		// We're depending on the property of 'foreach' (specified on the PHP website) that
		// it loops over the array starting from the first element and going sequentially
		// to the last element
Zach Prezkuta's avatar
Zach Prezkuta committed
75
		$newbody = str_replace('[!#saved_image' . $cnt . '#!]', '[img]' . $image . '[/img]', $newbody);
76 77 78 79
		$cnt++;
	}

	return $newbody;
80
}
81 82 83



84 85 86
/**
 * Render actions localized
 */
87

friendica's avatar
friendica committed
88
function localize_item(&$item){
89

90
	if (activity_match($item['verb'],ACTIVITY_LIKE) || activity_match($item['verb'],ACTIVITY_DISLIKE)){
91
	
92
		if(! $item['obj'])
93
			return;
friendica's avatar
friendica committed
94

95
		if(intval($item['item_thread_top']))
friendica's avatar
friendica committed
96 97
			return;	

98
		$obj = json_decode($item['obj'],true);
99 100
		if((! $obj) && ($item['obj'])) {
			logger('localize_item: failed to decode object: ' . print_r($item['obj'],true));
101
		}
102
		
friendica's avatar
friendica committed
103 104
		if($obj['author'] && $obj['author']['link'])
			$author_link = get_rel_link($obj['author']['link'],'alternate');
105 106 107
		else
			$author_link = '';

friendica's avatar
friendica committed
108
		$author_name = (($obj['author'] && $obj['author']['name']) ? $obj['author']['name'] : '');
109

friendica's avatar
friendica committed
110
		$item_url = get_rel_link($obj['link'],'alternate');
111

112 113
		$Bphoto = '';

114
		switch($obj['type']) {
115 116 117 118 119 120 121 122 123 124 125 126 127 128
			case ACTIVITY_OBJ_PHOTO:
				$post_type = t('photo');
				break;
			case ACTIVITY_OBJ_EVENT:
				$post_type = t('event');
				break;
			case ACTIVITY_OBJ_PERSON:
				$post_type = t('channel');
				$author_name = $obj['title'];
				if($obj['link']) {
					$author_link  = get_rel_link($obj['link'],'alternate');
					$Bphoto = get_rel_link($obj['link'],'photo');
				}
				break;
129 130
			case ACTIVITY_OBJ_THING:
				$post_type = $obj['title'];
131 132 133 134 135 136
				if($obj['owner']) {
					if(array_key_exists('name',$obj['owner']))
						$obj['owner']['name'];
					if(array_key_exists('link',$obj['owner']))
						$author_link = get_rel_link($obj['owner']['link'],'alternate');
				}
137 138 139 140 141
				if($obj['link']) {
					$Bphoto = get_rel_link($obj['link'],'photo');
				}
				break;

142 143 144
			case ACTIVITY_OBJ_NOTE:
			default:
				$post_type = t('status');
145
				if($obj['id'] != $obj['parent'])
146 147 148 149
					$post_type = t('comment');
				break;
		}

150
		// If we couldn't parse something useful, don't bother translating.
friendica's avatar
friendica committed
151
		// We need something better than zid here, probably magic_link(), but it needs writing
152 153

		if($author_link && $author_name && $item_url) {
154 155
			$author	 = '[zrl=' . chanlink_url($item['author']['xchan_url']) . ']' . $item['author']['xchan_name'] . '[/zrl]';
			$objauthor =  '[zrl=' . chanlink_url($author_link) . ']' . $author_name . '[/zrl]';
156
		
157
			$plink = '[zrl=' . zid($item_url) . ']' . $post_type . '[/zrl]';
158 159 160 161 162 163 164

			if(activity_match($item['verb'],ACTIVITY_LIKE)) {
				$bodyverb = t('%1$s likes %2$s\'s %3$s');
			}
			elseif(activity_match($item['verb'],ACTIVITY_DISLIKE)) {
				$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
			}
friendica's avatar
friendica committed
165
			$item['body'] = $item['localize'] = sprintf($bodyverb, $author, $objauthor, $plink);
166 167
			if($Bphoto != "") 
				$item['body'] .= "\n\n\n" . '[zrl=' . chanlink_url($author_link) . '][zmg=80x80]' . $Bphoto . '[/zmg][/zrl]';
168

169
		}
170 171 172
		else {
			logger('localize_item like failed: link ' . $author_link . ' name ' . $author_name . ' url ' . $item_url);
		}
173

174
	}
175

176
	if (activity_match($item['verb'],ACTIVITY_FRIEND)) {
177

178 179
		if ($item['obj_type'] == "" || $item['obj_type'] !== ACTIVITY_OBJ_PERSON) 
			return;
180

friendica's avatar
friendica committed
181 182
		$Aname = $item['author']['xchan_name'];
		$Alink = $item['author']['xchan_url'];
183 184


185
		$obj= json_decode($item['obj'],true);
friendica's avatar
friendica committed
186 187
		
		$Blink = $Bphoto = '';
188

friendica's avatar
friendica committed
189 190 191
		if($obj['link']) {
			$Blink  = get_rel_link($obj['link'],'alternate');
			$Bphoto = get_rel_link($obj['link'],'photo');
192
		}
friendica's avatar
friendica committed
193 194
		$Bname = $obj['title'];

195

196 197 198
		$A = '[zrl=' . chanlink_url($Alink) . ']' . $Aname . '[/zrl]';
		$B = '[zrl=' . chanlink_url($Blink) . ']' . $Bname . '[/zrl]';
		if ($Bphoto!="") $Bphoto = '[zrl=' . chanlink_url($Blink) . '][zmg=80x80]' . $Bphoto . '[/zmg][/zrl]';
199

200
		$item['body'] = $item['localize'] = sprintf( t('%1$s is now connected with %2$s'), $A, $B);
friendica's avatar
friendica committed
201
		$item['body'] .= "\n\n\n" . $Bphoto;
202
	}
friendica's avatar
friendica committed
203

204
	if (stristr($item['verb'], ACTIVITY_POKE)) {
friendica's avatar
friendica committed
205

206
		/** @FIXME for obscured private posts, until then leave untranslated */
friendica's avatar
friendica committed
207 208
		return;

friendica's avatar
friendica committed
209 210 211
		$verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
		if(! $verb)
			return;
212

213
		if ($item['obj_type']=="" || $item['obj_type']!== ACTIVITY_OBJ_PERSON) return;
friendica's avatar
friendica committed
214

friendica's avatar
friendica committed
215 216
		$Aname = $item['author']['xchan_name'];
		$Alink = $item['author']['xchan_url'];
217

218
		$obj= json_decode($item['obj'],true);
219

friendica's avatar
friendica committed
220
		$Blink = $Bphoto = '';
221

friendica's avatar
friendica committed
222 223 224
		if($obj['link']) {
			$Blink  = get_rel_link($obj['link'],'alternate');
			$Bphoto = get_rel_link($obj['link'],'photo');
friendica's avatar
friendica committed
225
		}
friendica's avatar
friendica committed
226
		$Bname = $obj['title'];
227

228 229 230
		$A = '[zrl=' . chanlink_url($Alink) . ']' . $Aname . '[/zrl]';
		$B = '[zrl=' . chanlink_url($Blink) . ']' . $Bname . '[/zrl]';
		if ($Bphoto!="") $Bphoto = '[zrl=' . chanlink_url($Blink) . '][zmg=80x80]' . $Bphoto . '[/zmg][/zrl]';
friendica's avatar
friendica committed
231 232 233 234 235 236 237 238 239 240 241 242

		// we can't have a translation string with three positions but no distinguishable text
		// So here is the translate string.

		$txt = t('%1$s poked %2$s');

		// now translate the verb

		$txt = str_replace( t('poked'), t($verb), $txt);

		// then do the sprintf on the translation string

friendica's avatar
friendica committed
243 244
		$item['body'] = $item['localize'] = sprintf($txt, $A, $B);
		$item['body'] .= "\n\n\n" . $Bphoto;
friendica's avatar
friendica committed
245
	}
246 247 248 249 250
	if (stristr($item['verb'],ACTIVITY_MOOD)) {
		$verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
		if(! $verb)
			return;

friendica's avatar
friendica committed
251 252 253
		$Aname = $item['author']['xchan_name'];
		$Alink = $item['author']['xchan_url'];

254
		$A = '[zrl=' . chanlink_url($Alink) . ']' . $Aname . '[/zrl]';
255
		
256
		$txt = t('%1$s is %2$s','mood');
257 258 259

		$item['body'] = sprintf($txt, $A, t($verb));
	}
260 261


Mario's avatar
Mario committed
262

friendica's avatar
friendica committed
263 264 265
/*
// FIXME store parent item as object or target
// (and update to json storage)
266

267
 	if (activity_match($item['verb'],ACTIVITY_TAG)) {
268 269
		$r = q("SELECT * from item,contact WHERE 
		item.contact-id=contact.id AND item.mid='%s';",
270
		 dbesc($item['parent_mid']));
271 272 273
		if(count($r)==0) return;
		$obj=$r[0];
		
274 275
		$author	 = '[zrl=' . zid($item['author-link']) . ']' . $item['author-name'] . '[/zrl]';
		$objauthor =  '[zrl=' . zid($obj['author-link']) . ']' . $obj['author-name'] . '[/zrl]';
276 277 278
		
		switch($obj['verb']){
			case ACTIVITY_POST:
279
				switch ($obj['obj_type']){
280 281 282 283 284 285 286 287
					case ACTIVITY_OBJ_EVENT:
						$post_type = t('event');
						break;
					default:
						$post_type = t('status');
				}
				break;
			default:
288
				if($obj['resource_id']){
289
					$post_type = t('photo');
290
					$m=array(); preg_match("/\[[zu]rl=([^]]*)\]/", $obj['body'], $m);
291 292 293 294 295
					$rr['plink'] = $m[1];
				} else {
					$post_type = t('status');
				}
		}
296
		$plink = '[zrl=' . $obj['plink'] . ']' . $post_type . '[/zrl]';
297

298
		$parsedobj = parse_xml_string($xmlhead.$item['obj']);
299

300
		$tag = sprintf('#[zrl=%s]%s[/zrl]', $parsedobj->id, $parsedobj->content);
301
		$item['body'] = sprintf( t('%1$s tagged %2$s\'s %3$s with %4$s'), $author, $objauthor, $plink, $tag );
302

303
	}
friendica's avatar
friendica committed
304

305
	if (activity_match($item['verb'],ACTIVITY_FAVORITE)){
friendica's avatar
friendica committed
306

307
		if ($item['obj_type']== "")
friendica's avatar
friendica committed
308 309
			return;

friendica's avatar
friendica committed
310 311
		$Aname = $item['author']['xchan_name'];
		$Alink = $item['author']['xchan_url'];
312

friendica's avatar
friendica committed
313
		$xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
314

315
		$obj = parse_xml_string($xmlhead.$item['obj']);
friendica's avatar
friendica committed
316
		if(strlen($obj->id)) {
317
			$r = q("select * from item where mid = '%s' and uid = %d limit 1",
friendica's avatar
friendica committed
318 319 320 321 322 323 324
					dbesc($obj->id),
					intval($item['uid'])
			);
			if(count($r) && $r[0]['plink']) {
				$target = $r[0];
				$Bname = $target['author-name'];
				$Blink = $target['author-link'];
325 326 327
				$A = '[zrl=' . zid($Alink) . ']' . $Aname . '[/zrl]';
				$B = '[zrl=' . zid($Blink) . ']' . $Bname . '[/zrl]';
				$P = '[zrl=' . $target['plink'] . ']' . t('post/item') . '[/zrl]';
friendica's avatar
friendica committed
328 329 330 331 332
				$item['body'] = sprintf( t('%1$s marked %2$s\'s %3$s as favorite'), $A, $B, $P)."\n";

			}
		}
	}
friendica's avatar
friendica committed
333 334
*/

335
/*
friendica's avatar
friendica committed
336
	$matches = null;
337 338
	if(strpos($item['body'],'[zrl') !== false) {
		if(preg_match_all('/@\[zrl=(.*?)\]/is',$item['body'],$matches,PREG_SET_ORDER)) {
339 340
			foreach($matches as $mtch) {
				if(! strpos($mtch[1],'zid='))
341
					$item['body'] = str_replace($mtch[0],'@[zrl=' . zid($mtch[1]). ']',$item['body']);
342
			}
friendica's avatar
friendica committed
343 344
		}
	}
345

346
	if(strpos($item['body'],'[zmg') !== false) {
347
		// add zid's to public images
348
		if(preg_match_all('/\[zrl=(.*?)\/photos\/(.*?)\/image\/(.*?)\]\[zmg(.*?)\]h(.*?)\[\/zmg\]\[\/zrl\]/is',$item['body'],$matches,PREG_SET_ORDER)) {
349
			foreach($matches as $mtch) {
350
				$item['body'] = str_replace($mtch[0],'[zrl=' . zid( $mtch[1] . '/photos/' . $mtch[2] . '/image/' . $mtch[3]) . '][zmg' . $mtch[4] . ']h' . $mtch[5]  . '[/zmg][/zrl]',$item['body']);
351
			}
352 353
		}
	}
354
*/
355 356 357 358 359

	// if item body was obscured and we changed it, re-obscure it
	// FIXME - we need a better filter than just the string 'data'; try and
	// match the fact that it's json encoded

friendica's avatar
friendica committed
360
	if(intval($item['item_obscured'])
361
		&& strlen($item['body']) && (! strpos($item['body'],'data'))) {
Zot's avatar
Zot committed
362
		$item['body']  = z_obscure($item['body']);
363 364
	}

365 366
}

367
/**
368 369 370 371 372
 * @brief Count the total of comments on this item and its desendants.
 *
 * @param array $item an assoziative item-array which provides:
 *  * \e array \b children
 * @return number
373
 */
Zot's avatar
Zot committed
374

375
function count_descendants($item) {
376

377 378
	$total = count($item['children']);

Zot's avatar
Zot committed
379 380 381
	if($total > 0) {
		foreach($item['children'] as $child) {
			if(! visible_activity($child))
382 383 384 385 386
				$total --;

			$total += count_descendants($child);
		}
	}
387 388 389 390

	return $total;
}

391 392 393 394
/**
 * @brief Check if the activity of the item is visible.
 *
 * likes (etc.) can apply to other things besides posts. Check if they are post
redmatrix's avatar
redmatrix committed
395 396 397
 * children, in which case we handle them specially. Activities which are unrecognised
 * as having special meaning and hidden will be treated as posts or comments and visible
 * in the stream.  
398 399 400 401
 *
 * @param array $item
 * @return boolean
 */
402
function visible_activity($item) {
403
	$hidden_activities = [ ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_AGREE, ACTIVITY_DISAGREE, ACTIVITY_ABSTAIN, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE ];
404

405 406
	if(intval($item['item_notshown']))
		return false;
redmatrix's avatar
redmatrix committed
407

Zot's avatar
Zot committed
408 409
	foreach($hidden_activities as $act) {
		if((activity_match($item['verb'], $act)) && ($item['mid'] != $item['parent_mid'])) {
410 411 412
			return false;
		}
	}
413

414 415
	if(is_edit_activity($item))
		return false;
Zot's avatar
Zot committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431

	return true;
}

/**
 * @brief Check if a given activity is an edit activity
 * 
 *
 * @param array $item
 * @return boolean
 */

function is_edit_activity($item) {

	$post_types = [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT, basename(ACTIVITY_OBJ_NOTE), basename(ACTIVITY_OBJ_COMMENT)]; 

redmatrix's avatar
redmatrix committed
432 433 434 435 436
	// In order to share edits with networks which have no concept of editing, we'll create 
	// separate activities to indicate the edit. Our network will not require them, since our
	// edits are automatically applied and the activity indicated.  

	if(($item['verb'] === ACTIVITY_UPDATE) && (in_array($item['obj_type'],$post_types)))
Zot's avatar
Zot committed
437
		return true;
redmatrix's avatar
redmatrix committed
438

Zot's avatar
Zot committed
439
	return false;
440 441
}

442
/**
443 444
 * @brief "Render" a conversation or list of items for HTML display.
 *
445
 * There are two major forms of display:
446 447 448
 *  - Sequential or unthreaded ("New Item View" or search results)
 *  - conversation view
 *
449
 * The $mode parameter decides between the various renderings and also
450
 * figures out how to determine page owner and other contextual items
451 452
 * that are based on unique features of the calling module.
 *
453 454 455 456 457 458 459
 * @param App &$a
 * @param array $items
 * @param string $mode
 * @param boolean $update
 * @param string $page_mode default traditional
 * @param string $prepared_item
 * @return string
460
 */
461
function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $prepared_item = '') {
462

463
	$content_html = '';
464
	$o = '';
465

466 467
	require_once('bbcode.php');

friendica's avatar
friendica committed
468
	$ssl_state = ((local_channel()) ? true : false);
469

470
	if (local_channel())
friendica's avatar
friendica committed
471
		load_pconfig(local_channel(),'');
472

473 474
	$profile_owner   = 0;
	$page_writeable  = false;
475
	$live_update_div = '';
Friendika's avatar
Friendika committed
476

477
	$preview = (($page_mode === 'preview') ? true : false);
friendica's avatar
friendica committed
478 479
	$previewing = (($preview) ? ' preview ' : '');

480
	if ($mode === 'network') {
481

friendica's avatar
friendica committed
482
		$profile_owner = local_channel();
483
		$page_writeable = true;
484

485
		if (!$update) {
486 487 488 489 490 491
			// The special div is needed for liveUpdate to kick in for this page.
			// We only launch liveUpdate if you aren't filtering in some incompatible
			// way and also you aren't writing a comment (discovered in javascript).

			$live_update_div = '<div id="live-network"></div>' . "\r\n"
				. "<script> var profile_uid = " . $_SESSION['uid']
redmatrix's avatar
redmatrix committed
492
				. "; var netargs = '" . substr(App::$cmd,8)
493 494 495 496 497 498 499 500 501 502 503 504 505 506
				. '?f='
				. ((x($_GET,'cid'))    ? '&cid='    . $_GET['cid']    : '')
				. ((x($_GET,'search')) ? '&search=' . $_GET['search'] : '')
				. ((x($_GET,'star'))   ? '&star='   . $_GET['star']   : '')
				. ((x($_GET,'order'))  ? '&order='  . $_GET['order']  : '')
				. ((x($_GET,'bmark'))  ? '&bmark='  . $_GET['bmark']  : '')
				. ((x($_GET,'liked'))  ? '&liked='  . $_GET['liked']  : '')
				. ((x($_GET,'conv'))   ? '&conv='   . $_GET['conv']   : '')
				. ((x($_GET,'spam'))   ? '&spam='   . $_GET['spam']   : '')
				. ((x($_GET,'nets'))   ? '&nets='   . $_GET['nets']   : '')
				. ((x($_GET,'cmin'))   ? '&cmin='   . $_GET['cmin']   : '')
				. ((x($_GET,'cmax'))   ? '&cmax='   . $_GET['cmax']   : '')
				. ((x($_GET,'file'))   ? '&file='   . $_GET['file']   : '')
				. ((x($_GET,'uri'))    ? '&uri='    . $_GET['uri']   : '')
redmatrix's avatar
redmatrix committed
507
				. "'; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
508
		}
Friendika's avatar
Friendika committed
509 510
	}

511
	elseif ($mode === 'channel') {
redmatrix's avatar
redmatrix committed
512
		$profile_owner = App::$profile['profile_uid'];
friendica's avatar
friendica committed
513
		$page_writeable = ($profile_owner == local_channel());
Friendika's avatar
Friendika committed
514

515
		if (!$update) {
516
			$tab = notags(trim($_GET['tab']));
517
			if ($tab === 'posts') {
518 519
				// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
				// because browser prefetching might change it on us. We have to deliver it with the page.
520

521
				$live_update_div = '<div id="live-channel"></div>' . "\r\n"
redmatrix's avatar
redmatrix committed
522 523
					. "<script> var profile_uid = " . App::$profile['profile_uid']
					. "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
524 525
			}
		}
Friendika's avatar
Friendika committed
526 527
	}

528
	elseif ($mode === 'display') {
friendica's avatar
friendica committed
529
		$profile_owner = local_channel();
530
		$page_writeable = false;
531
		$live_update_div = '<div id="live-display"></div>' . "\r\n";
532 533
	}

534
	elseif ($mode === 'page') {
redmatrix's avatar
redmatrix committed
535
		$profile_owner = App::$profile['uid'];
friendica's avatar
friendica committed
536
		$page_writeable = ($profile_owner == local_channel());
537 538 539
		$live_update_div = '<div id="live-page"></div>' . "\r\n";
	}

540
	elseif ($mode === 'search') {
541 542
		$live_update_div = '<div id="live-search"></div>' . "\r\n";
	}
543

544
	elseif ($mode === 'photos') {
redmatrix's avatar
redmatrix committed
545
		$profile_onwer = App::$profile['profile_uid'];
friendica's avatar
friendica committed
546
		$page_writeable = ($profile_owner == local_channel());
547 548
		$live_update_div = '<div id="live-photos"></div>' . "\r\n";
		// for photos we've already formatted the top-level item (the photo)
redmatrix's avatar
redmatrix committed
549
		$content_html = App::$data['photo_html'];
550
	}
friendica's avatar
friendica committed
551

friendica's avatar
friendica committed
552
	$page_dropping = ((local_channel() && local_channel() == $profile_owner) ? true : false);
553

554
	if (! feature_enabled($profile_owner,'multi_delete'))
555 556 557
		$page_dropping = false;


redmatrix's avatar
redmatrix committed
558 559
	$channel = App::get_channel();
	$observer = App::get_observer();
friendica's avatar
friendica committed
560

561 562 563
	if($update)
		$return_url = $_SESSION['return_url'];
	else
redmatrix's avatar
redmatrix committed
564
		$return_url = $_SESSION['return_url'] = App::$query_string;
Friendika's avatar
Friendika committed
565

friendica's avatar
friendica committed
566
	load_contact_links(local_channel());
567

friendica's avatar
friendica committed
568 569 570 571
	$cb = array('items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview);
	call_hooks('conversation_start',$cb);

	$items = $cb['items'];
572

friendica's avatar
friendica committed
573 574 575 576 577 578
	$conv_responses = array(
		'like' => array('title' => t('Likes','title')),'dislike' => array('title' => t('Dislikes','title')),
		'agree' => array('title' => t('Agree','title')),'disagree' => array('title' => t('Disagree','title')), 'abstain' => array('title' => t('Abstain','title')), 
		'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title'))
	);

579

580
	// array with html for each thread (parent+comments)
Fabio Comuni's avatar
Fabio Comuni committed
581 582
	$threads = array();
	$threadsid = -1;
583 584

	$page_template = get_markup_template("conversation.tpl");
585

586
	if($items) {
587

588
		if($mode === 'network-new' || $mode === 'search' || $mode === 'community') {
589

590
			// "New Item View" on network page or search page results
591
			// - just loop through the items and format them minimally for display
592

593

594 595
			//$tpl = get_markup_template('search_item.tpl');
			$tpl = 'search_item.tpl';
596

Friendika's avatar
Friendika committed
597
			foreach($items as $item) {
598

599 600 601 602 603 604 605
				$x = [ 'mode' => $mode, 'item' => $item ];
				call_hooks('stream_item',$x);
				
				if($x['item']['blocked'])
					continue;

				$item = $x['item'];
606

Fabio Comuni's avatar
Fabio Comuni committed
607
				$threadsid++;
608 609 610 611 612 613

				$comment     = '';
				$owner_url   = '';
				$owner_photo = '';
				$owner_name  = '';
				$sparkle     = '';
614

615
				if($mode === 'search' || $mode === 'community') {
616 617 618 619 620 621
					if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) 
						&& ($item['id'] != $item['parent']))
						continue;
					$nickname = $item['nickname'];
				}
				else
redmatrix's avatar
redmatrix committed
622
					$nickname = App::$user['nickname'];
623

624
				$profile_name   = ((strlen($item['author-name']))   ? $item['author-name']   : $item['name']);
friendica's avatar
friendica committed
625 626
				if($item['author-link'] && (! $item['author-name']))
					$profile_name = $item['author-link'];
627 628 629

				$sp = false;
				$profile_link = best_link_url($item,$sp);
friendica's avatar
friendica committed
630 631 632
				if($sp)
					$sparkle = ' sparkle';
				else
friendica's avatar
friendica committed
633
					$profile_link = zid($profile_link);
634

635 636
				$normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);

friendica's avatar
friendica committed
637 638 639 640
				$profile_name = $item['author']['xchan_name'];
				$profile_link = $item['author']['xchan_url'];
				$profile_avatar = $item['author']['xchan_photo_m'];

641
				$location = format_location($item);
Friendika's avatar
Friendika committed
642

643
				localize_item($item);
644
				if($mode === 'network-new')
645
					$dropping = true;
646
				else
647 648 649
					$dropping = false;

				$drop = array(
650
					'pagedropping' => $page_dropping,
651 652 653 654
					'dropping' => $dropping,
					'select' => t('Select'), 
					'delete' => t('Delete'),
				);
Friendika's avatar
Friendika committed
655

656
				$star = false;
Treer's avatar
Treer committed
657
				$isstarred = "unstarred fa-star-o";
658

659 660 661 662 663
				$lock = (($item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
					? t('Private Message')
					: false
				);

664 665
				$likebuttons = false;
				$shareable = false;
Friendika's avatar
Friendika committed
666

friendica's avatar
friendica committed
667 668
				$verified = (intval($item['item_verified']) ? t('Message signature validated') : '');
				$forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : '');
friendica's avatar
friendica committed
669

friendica's avatar
friendica committed
670 671
				$unverified = '';

672
//				$tags=array();
673
//				$terms = get_terms_oftype($item['term'],array(TERM_HASHTAG,TERM_MENTION,TERM_UNKNOWN,TERM_COMMUNITYTAG));
674 675 676
//				if(count($terms))
//					foreach($terms as $tag)
//						$tags[] = format_term_for_display($tag);
friendica's avatar
friendica committed
677

Friendika's avatar
Friendika committed
678
				$body = prepare_body($item,true);
679

680 681
				$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);

682 683
				$tmp_item = array(
					'template' => $tpl,
684
					'toplevel' => 'toplevel_item',
685
					'mode' => $mode,
686
					'id' => (($preview) ? 'P0' : $item['item_id']),
friendica's avatar
friendica committed
687
					'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, $profile_url),
688
					'profile_url' => $profile_link,
689 690
					'thread_action_menu' => thread_action_menu($item,$mode),
					'thread_author_menu' => thread_author_menu($item,$mode),
691
					'name' => $profile_name,
692 693 694
					'sparkle' => $sparkle,
					'lock' => $lock,
					'thumb' => $profile_avatar,
695
					'title' => $item['title'],
696
					'body' => $body['html'],
697
					'event' => $body['event'],
698
					'photo' => $body['photo'],
699 700 701 702 703
					'tags' => $body['tags'],
					'categories' => $body['categories'],
					'mentions' => $body['mentions'],
					'attachments' => $body['attachments'],
					'folders' => $body['folders'],
friendica's avatar
friendica committed
704 705
					'verified' => $verified,
					'unverified' => $unverified,
friendica's avatar
friendica committed
706
					'forged' => $forged,
707
					'txt_cats' => t('Categories:'),
708
					'txt_folders' => t('Filed under:'),
Zot's avatar
Zot committed
709 710
					'has_cats' => ((count($body['categories'])) ? 'true' : ''),
					'has_folders' => ((count($body['folders'])) ? 'true' : ''),
711
					'text' => strip_tags($body['html']),
712 713
					'ago' => relative_date($item['created']),
					'app' => $item['app'],
714
					'str_app' => sprintf( t('from %s'), $item['app']),
715 716
					'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
					'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
717
					'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
Zot's avatar
Zot committed
718
					'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
719
					'location' => $location,
720
					'indent' => '',
721
					'owner_name' => $owner_name,
722 723
					'owner_url' => $owner_url,
					'owner_photo' => $owner_photo,
724
					'plink' => get_plink($item,false),
725 726 727 728 729 730 731 732
					'edpost' => false,
					'isstarred' => $isstarred,
					'star' => $star,
					'drop' => $drop,
					'vote' => $likebuttons,
					'like' => '',
					'dislike' => '',
					'comment' => '',
733
					'conv' => (($preview) ? '' : array('href'=> z_root() . '/display/' . gen_link_id($item['mid']), 'title'=> t('View in context'))),
734 735
					'previewing' => $previewing,
					'wait' => t('Please wait'),
friendica's avatar
friendica committed
736
					'thread_level' => 1,
737
					'has_tags' => $has_tags,
738
				);
739

740 741 742
				$arr = array('item' => $item, 'output' => $tmp_item);
				call_hooks('display_item', $arr);

743 744
//				$threads[$threadsid]['id'] = $item['item_id'];
				$threads[] = $arr['output'];
745 746
			}
		}
747
		else {
748

749
			// Normal View
750
//			logger('conv: items: ' . print_r($items,true));
751

752
			$conv = new Zotlabs\Lib\ThreadStream($mode, $preview, $prepared_item);
753

754 755 756 757 758
			// In the display mode we don't have a profile owner. 

			if($mode === 'display' && $items)
				$conv->set_profile_owner($items[0]['uid']);

759 760 761
			// get all the topmost parents
			// this shouldn't be needed, as we should have only them in our array
			// But for now, this array respects the old style, just in case
762

763 764
			$threads = array();
			foreach($items as $item) {
765

friendica's avatar
friendica committed
766 767
				// Check for any blocked authors

768

769 770 771 772 773
				$x = [ 'mode' => $mode, 'item' => $item ];
				call_hooks('stream_item',$x);
				
				if($x['item']['blocked'])
					continue;
friendica's avatar
friendica committed
774

775
				$item = $x['item'];
friendica's avatar
friendica committed
776

friendica's avatar
friendica committed
777
				builtin_activity_puller($item, $conv_responses);
778

779 780 781
				if(! visible_activity($item)) {
					continue;
				}
782

redmatrix's avatar
redmatrix committed
783

784
				$item['pagedrop'] = $page_dropping;
785

786
				if($item['id'] == $item['parent']) {
friendica's avatar
friendica committed
787

788
					$item_object = new Zotlabs\Lib\ThreadItem($item);
789
					$conv->add_thread($item_object);
friendica's avatar
friendica committed
790
					if($page_mode === 'list') {
791
						$item_object->set_template('conv_list.tpl');
friendica's avatar
friendica committed
792 793
						$item_object->set_display_mode('list');
					}
794 795
				}
			}
friendica's avatar
friendica committed
796

797
			$threads = $conv->get_template_data($conv_responses);
798 799 800 801 802 803
			if(!$threads) {
				logger('[ERROR] conversation : Failed to get template data.', LOGGER_DEBUG);
				$threads = array();
			}
		}
	}
804 805 806 807 808 809 810 811 812 813 814 815

	if($page_mode === 'traditional' || $page_mode === 'preview') {
		$page_template = get_markup_template("threaded_conversation.tpl");
	}
	elseif($update) {
		$page_template = get_markup_template("convobj.tpl");
	}
	else {
		$page_template = get_markup_template("conv_frame.tpl");
		$threads = null;
	}

816 817
//	if($page_mode === 'preview')
//		logger('preview: ' . print_r($threads,true));
818

819
//  Do not un-comment if smarty3 is in use
820
//	logger('page_template: ' . $page_template);
821 822 823 824

//	logger('nouveau: ' . print_r($threads,true));


825
	$o .= replace_macros($page_template, array(
redmatrix's avatar
redmatrix committed
826
		'$baseurl' => z_root(),
827
		'$photo_item' => $content_html,
828 829 830
		'$live_update' => $live_update_div,
		'$remove' => t('remove'),
		'$mode' => $mode,
redmatrix's avatar
redmatrix committed
831
		'$user' => App::$user,
832
		'$threads' => $threads,
833
		'$wait' => t('Loading...'),
834 835
		'$dropping' => ($page_dropping?t('Delete Selected Items'):False),
	));
836

837
	return $o;
838
}
839 840


841
function best_link_url($item) {
842 843 844 845 846 847

	$best_url = '';
	$sparkle  = false;

	$clean_url = normalise_link($item['author-link']);

friendica's avatar
friendica committed
848
	if((local_channel()) && (local_channel() == $item['uid'])) {
redmatrix's avatar
redmatrix committed
849 850 851
		if(isset(App::$contacts) && x(App::$contacts,$clean_url)) {
			if(App::$contacts[$clean_url]['network'] === NETWORK_DFRN) {
				$best_url = z_root() . '/redir/' . App::$contacts[$clean_url]['id'];
852
				$sparkle = true;
853
			}
854
			else
redmatrix's avatar
redmatrix committed
855
				$best_url = App::$contacts[$clean_url]['url'];
856 857
		}
	}
858 859 860 861 862 863 864 865 866 867
	if(! $best_url) {
		if(strlen($item['author-link']))
			$best_url = $item['author-link'];
		else
			$best_url = $item['url'];
	}

	return $best_url;
}

868

869

870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
function thread_action_menu($item,$mode = '') {

	$menu = [];
	
	if((local_channel()) && local_channel() == $item['uid']) {
		$menu[] = [ 
			'menu' => 'view_source',
			'title' => t('View Source'),
			'icon' => 'eye',
			'action' => 'viewsrc(' . $item['id'] . '); return false;',
			'href' => '#'
		];

		if(! in_array($mode, [ 'network-new', 'search', 'community'])) {
			if($item['parent'] == $item['id'] && (get_observer_hash() != $item['author_xchan'])) {
				$menu[] = [ 
					'menu' => 'follow_thread',
					'title' => t('Follow Thread'),
					'icon' => 'plus',
					'action' => 'dosubthread(' . $item['id'] . '); return false;',
					'href' => '#'
				];
			}

			$menu[] = [ 
				'menu' => 'unfollow_thread',
				'title' => t('Unfollow Thread'),
				'icon' => 'minus',
				'action' => 'dounsubthread(' . $item['id'] . '); return false;',
				'href' => '#'
			];
		}

	}




	$args = [ 'item' => $item, 'mode' => $mode, 'menu' => $menu ];
	call_hooks('thread_action_menu', $args);

	return $args['menu'];

}

function thread_author_menu($item, $mode = '') {

	$menu = [];

	$local_channel = local_channel();

	if($local_channel) {
		if(! count(App::$contacts))
			load_contact_links($local_channel);
		$channel = App::get_channel();
		$channel_hash = (($channel) ? $channel['channel_hash'] : '');
	}

	$profile_link = chanlink_hash($item['author_xchan']);
Zot's avatar
Zot committed
929

930
	if($item['uid'] > 0)
Zot's avatar
Zot committed
931
		$pm_url = z_root() . '/mail/new/?f=&hash=' . urlencode($item['author_xchan']);
932 933 934 935 936

	if(App::$contacts && array_key_exists($item['author_xchan'],App::$contacts))
		$contact = App::$contacts[$item['author_xchan']];
	else
		if($local_channel && $item['author']['xchan_addr'])
Zot's avatar
Zot committed
937
			$follow_url = z_root() . '/follow/?f=&url=' . urlencode($item['author']['xchan_addr']);
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

	if($contact) {
		$poke_link = z_root() . '/poke/?f=&c=' . $contact['abook_id'];
		if (! intval($contact['abook_self']))  
			$contact_url = z_root() . '/connedit/' . $contact['abook_id'];
		$posts_link = z_root() . '/network/?cid=' . $contact['abook_id'];

		$clean_url = normalise_link($item['author-link']);
	}

	$rating_enabled = get_config('system','rating_enabled');

	$ratings_url = (($rating_enabled) ? z_root() . '/ratings/' . urlencode($item['author_xchan']) : '');

	if($profile_link) {
		$menu[] = [ 
			'menu' => 'view_profile',
			'title' => t('View Profile'),
			'icon' => 'fw',
			'action' => '',
			'href' => $profile_link
		];
	}

	if($posts_link) {
		$menu[] = [ 
			'menu' => 'view_posts',
			'title' => t('Activity/Posts'),
			'icon' => 'fw',
			'action' => '',
			'href' => $posts_link
		];
	}

	if($follow_url) {
		$menu[] = [ 
			'menu' => 'follow',
			'title' => t('Connect'),
			'icon' => 'fw',
			'action' => '',
			'href' => $follow_url
		];
	}

	if($contact_url) {
		$menu[] = [ 
			'menu' => 'connedit',
			'title' => t('Edit Connection'),
			'icon' => 'fw',
			'action' => '',
			'href' => $contact_url
		];
	}

	if($pm_url) {
		$menu[] = [ 
			'menu' => 'prv_message',
			'title' => t('Message'),
			'icon' => 'fw',
			'action' => '',
			'href' => $pm_url
		];
	}

	if($ratings_url) {
		$menu[] = [ 
			'menu' => 'ratings',
			'title' => t('Ratings'),
			'icon' => 'fw',
			'action' => '',
			'href' => $ratings_url
		];
	}

	if($poke_link) {
		$menu[] = [ 
			'menu' => 'poke',
			'title' => t('Poke'),
			'icon' => 'fw',
			'action' => '',
			'href' => $poke_link
		];
	}

	$args = [ 'item' => $item, 'mode' => $mode, 'menu' => $menu ];
	call_hooks('thread_author_menu', $args);

	return $args['menu'];

}





1033
/**
friendica's avatar
friendica committed
1034
 * @brief Checks item to see if it is one of the builtin activities (like/dislike, event attendance, consensus items, etc.)
1035
 *
friendica's avatar
friendica committed
1036
 * Increments the count of each matching activity and adds a link to the author as needed.
1037 1038
 *
 * @param array $item
friendica's avatar
friendica committed
1039
 * @param array &$conv_responses (already created with builtin activity structure)
1040
 */
friendica's avatar
friendica committed
1041
function builtin_activity_puller($item, &$conv_responses) {
1042

1043
	// if this item is a post or comment there's nothing for us to do here, just return.
1044

1045 1046
	if(activity_match($item['verb'],ACTIVITY_POST))
		return;
1047

friendica's avatar
friendica committed
1048
	foreach($conv_responses as $mode => $v) {
1049

friendica's avatar
friendica committed
1050
		$url = '';
friendica's avatar
friendica committed
1051

friendica's avatar
friendica committed
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
		switch($mode) {
			case 'like':
				$verb = ACTIVITY_LIKE;
				break;
			case 'dislike':
				$verb = ACTIVITY_DISLIKE;
				break;
			case 'agree':
				$verb = ACTIVITY_AGREE;
				break;
			case 'disagree':
				$verb = ACTIVITY_DISAGREE;
				break;
			case 'abstain':
				$verb = ACTIVITY_ABSTAIN;
				break;
			case 'attendyes':
				$verb = ACTIVITY_ATTEND;
				break;
			case 'attendno':
				$verb = ACTIVITY_ATTENDNO;
				break;
			case 'attendmaybe':
				$verb = ACTIVITY_ATTENDMAYBE;
				break;
			default:
				return;
				break;
		}
friendica's avatar
friendica committed
1081

friendica's avatar
friendica committed
1082 1083
		if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) {
			$name = (($item['author']['xchan_name']) ? $item['author']['xchan_name'] : t('Unknown'));
1084 1085
			$url = (($item['author_xchan'] && $item['author']['xchan_photo_s']) 
				? '<a href="' . chanlink_hash($item['author_xchan']) . '">' . '<img class="dropdown-menu-img-xs" src="' . zid($item['author']['xchan_photo_s'])  . '" alt="' . urlencode($name) . '" />' . $name . '</a>' 
friendica's avatar
friendica committed
1086 1087
				: '<a href="#" class="disabled">' . $name . '</a>'
			);
friendica's avatar
friendica committed
1088

friendica's avatar
friendica committed
1089 1090
			if(! $item['thr_parent'])
				$item['thr_parent'] = $item['parent_mid'];
1091

friendica's avatar
friendica committed
1092 1093 1094
			if(! ((isset($conv_responses[$mode][$item['thr_parent'] . '-l'])) 
				&& (is_array($conv_responses[$mode][$item['thr_parent'] . '-l']))))
				$conv_responses[$mode][$item['thr_parent'] . '-l'] = array();
friendica's avatar
friendica committed
1095

friendica's avatar
friendica committed
1096 1097 1098
			// only list each unique author once
			if(in_array($url,$conv_responses[$mode][$item['thr_parent'] . '-l']))
				continue;
friendica's avatar
friendica committed
1099

friendica's avatar
friendica committed
1100 1101 1102 1103 1104 1105
			if(! isset($conv_responses[$mode][$item['thr_parent']]))
				$conv_responses[$mode][$item['thr_parent']] = 1;
			else
				$conv_responses[$mode][$item['thr_parent']] ++;

			$conv_responses[$mode][$item['thr_parent'] . '-l'][] = $url;
1106 1107 1108
			if(get_observer_hash() && get_observer_hash() === $item['author_xchan']) {
				$conv_responses[$mode][$item['thr_parent'] . '-m'] = true;
			}
1109 1110

			// there can only be one activity verb per item so if we found anything, we can stop looking
1111
			return;
friendica's avatar
friendica committed
1112
		}
1113
	}
1114
}
1115 1116


1117 1118 1119 1120 1121
/**
 * @brief Format the like/dislike text for a profile item.
 *
 * @param int $cnt number of people who like/dislike the item
 * @param array $arr array of pre-linked names of likers/dislikers
1122
 * @param string $type one of 'like, 'dislike'
1123 1124 1125 1126
 * @param int $id item id
 * @return string formatted text
 */
function format_like($cnt, $arr, $type, $id) {
1127
	$o = '';
1128
	if ($cnt == 1) {
1129
		$o .= (($type === 'like') ? sprintf( t('%s likes this.'), $arr[0]) : sprintf( t('%s doesn\'t like this.'), $arr[0])) . EOL ;
1130
	} else {
1131
		$spanatts = 'class="fakelink" onclick="openClose(\'' . $type . 'list-' . $id . '\');"';
1132
		$o .= (($type === 'like') ?
1133
					sprintf( tt('<span  %1$s>%2$d people</span> like this.','<span  %1$s>%2$d people</span> like this.',$cnt), $spanatts, $cnt)
1134
					 :
1135
					sprintf( tt('<span  %1$s>%2$d people</span> don\'t like this.','<span  %1$s>%2$d people</span> don\'t like this.',$cnt), $spanatts, $cnt) );
1136
		$o .= EOL;
1137 1138 1139 1140 1141 1142 1143
		$total = count($arr);
		if($total >= MAX_LIKERS)
			$arr = array_slice($arr, 0, MAX_LIKERS - 1);
		if($total < MAX_LIKERS)
			$arr[count($arr)-1] = t('and') . ' ' . $arr[count($arr)-1];
		$str = implode(', ', $arr);
		if($total >= MAX_LIKERS)
1144
			$str .= sprintf( tt(', and %d other people',', and %d other people',$total - MAX_LIKERS), $total - MAX_LIKERS );
1145 1146 1147
		$str = (($type === 'like') ? sprintf( t('%s like this.'), $str) : sprintf( t('%s don\'t like this.'), $str));
		$o .= "\t" . '<div id="' . $type . 'list-' . $id . '" style="display: none;" >' . $str . '</div>';
	}
1148

1149
	return $o;
1150
}
1151

redmatrix's avatar
redmatrix committed
1152 1153 1154 1155 1156
/**
 * This is our general purpose content editor. 
 * It was once nicknamed "jot" and you may see references to "jot" littered throughout the code.
 * They are referring to the content editor or components thereof. 
 */
1157

1158
function status_editor($a, $x, $popup = false) {
1159 1160

	$o = '';
1161

1162 1163 1164 1165
	$c = channelx_by_n($x['profile_uid']);
	if($c && $c['channel_moved'])
		return $o;

1166
	$plaintext = true;
1167

friendica's avatar
friendica committed
1168
//	if(feature_enabled(local_channel(),'richtext'))
1169
//		$plaintext = false;
1170

1171 1172 1173
	$feature_voting = feature_enabled($x['profile_uid'], 'consensus_tools');
	if(x($x, 'hide_voting'))
		$feature_voting = false;
1174 1175 1176 1177
	
	$feature_nocomment = feature_enabled($x['profile_uid'], 'disable_comments');
	if(x($x, 'disable_comments'))
		$feature_nocomment = false;
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191

	$feature_expire = ((feature_enabled($x['profile_uid'], 'content_expire') && (! $webpage)) ? true : false);
	if(x($x, 'hide_expire'))
		$feature_expire = false;

	$feature_future = ((feature_enabled($x['profile_uid'], 'delayed_posting') && (! $webpage)) ? true : false);
	if(x($x, 'hide_future'))
		$feature_future = false;

	$geotag = (($x['allow_location']) ? replace_macros(get_markup_template('jot_geotag.tpl'), array()) : '');
	$setloc = t('Set your location');
	$clearloc = ((get_pconfig($x['profile_uid'], 'system', 'use_browser_location')) ? t('Clear browser location') : '');
	if(x($x, 'hide_location'))
		$geotag = $setloc = $clearloc = '';
friendica's avatar
friendica committed
1192

1193 1194 1195 1196 1197 1198
	$mimetype = ((x($x,'mimetype')) ? $x['mimetype'] : 'text/bbcode');

	$mimeselect = ((x($x,'mimeselect')) ? $x['mimeselect'] : false);
	if($mimeselect)
		$mimeselect = mimetype_select($x['profile_uid'], $mimetype);
	else
1199
		$mimeselect = '<input type="hidden" name="mimetype" value="' . $mimetype . '" />';
1200 1201

	$weblink = (($mimetype === 'text/bbcode') ? t('Insert web link') : false);
1202
	if