Decouple conversation creation from rendering
- This allows to separately obtain a list of threads for rendering without having to deal with an already-formed HTML output
This commit is contained in:
		
					parent
					
						
							
								31fbe70ec7
							
						
					
				
			
			
				commit
				
					
						706444bdb2
					
				
			
		
					 14 changed files with 294 additions and 269 deletions
				
			
		|  | @ -104,7 +104,7 @@ function item_edit(int $uid, array $request, bool $preview, string $return_path) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	$post['edit'] = $post; | 	$post['edit'] = $post; | ||||||
| 	$post['file'] = Post\Category::getTextByURIId($post['uri-id'], $post['uid']);	 | 	$post['file'] = Post\Category::getTextByURIId($post['uri-id'], $post['uid']); | ||||||
| 
 | 
 | ||||||
| 	Post\Media::deleteByURIId($post['uri-id'], [Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::IMAGE, Post\Media::HTML]); | 	Post\Media::deleteByURIId($post['uri-id'], [Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::IMAGE, Post\Media::HTML]); | ||||||
| 	$post = item_process($post, $request, $preview, $return_path); | 	$post = item_process($post, $request, $preview, $return_path); | ||||||
|  | @ -274,7 +274,7 @@ function item_process(array $post, array $request, bool $preview, string $return | ||||||
| 		$post['body']           = BBCode::removeSharedData(Item::setHashtags($post['body'])); | 		$post['body']           = BBCode::removeSharedData(Item::setHashtags($post['body'])); | ||||||
| 		$post['writable']       = true; | 		$post['writable']       = true; | ||||||
| 
 | 
 | ||||||
| 		$o = DI::conversation()->create([$post], Conversation::MODE_SEARCH, false, true); | 		$o = DI::conversation()->render([$post], Conversation::MODE_SEARCH, false, true); | ||||||
| 
 | 
 | ||||||
| 		System::jsonExit(['preview' => $o]); | 		System::jsonExit(['preview' => $o]); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -85,7 +85,7 @@ function notes_content(App $a, bool $update = false) | ||||||
| 
 | 
 | ||||||
| 		$count = count($notes); | 		$count = count($notes); | ||||||
| 
 | 
 | ||||||
| 		$o .= DI::conversation()->create($notes, Conversation::MODE_NOTES, $update); | 		$o .= DI::conversation()->render($notes, Conversation::MODE_NOTES, $update); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	$o .= $pager->renderMinimal($count); | 	$o .= $pager->renderMinimal($count); | ||||||
|  |  | ||||||
|  | @ -438,17 +438,17 @@ class Conversation | ||||||
| 	 * The $mode parameter decides between the various renderings and also | 	 * The $mode parameter decides between the various renderings and also | ||||||
| 	 * figures out how to determine page owner and other contextual items | 	 * figures out how to determine page owner and other contextual items | ||||||
| 	 * that are based on unique features of the calling module. | 	 * that are based on unique features of the calling module. | ||||||
| 	 * @param array  $items | 	 * @param array  $items   An array of Posts | ||||||
| 	 * @param string $mode | 	 * @param string $mode    One of self::MODE_* | ||||||
| 	 * @param        $update @TODO Which type? | 	 * @param bool   $update  Asynchronous update rendering | ||||||
| 	 * @param bool   $preview | 	 * @param bool   $preview Post preview (no actual database record) | ||||||
| 	 * @param string $order | 	 * @param string $order   Either "received" or "commented" | ||||||
| 	 * @param int    $uid | 	 * @param int    $uid | ||||||
| 	 * @return string | 	 * @return string | ||||||
| 	 * @throws ImagickException | 	 * @throws ImagickException | ||||||
| 	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException | 	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException | ||||||
| 	 */ | 	 */ | ||||||
| 	public function create(array $items, string $mode, $update, bool $preview = false, string $order = 'commented', int $uid = 0): string | 	public function render(array $items, string $mode, bool $update = false, bool $preview = false, string $order = 'commented', int $uid = 0): string | ||||||
| 	{ | 	{ | ||||||
| 		$this->profiler->startRecording('rendering'); | 		$this->profiler->startRecording('rendering'); | ||||||
| 
 | 
 | ||||||
|  | @ -459,10 +459,6 @@ class Conversation | ||||||
| 
 | 
 | ||||||
| 		$live_update_div = ''; | 		$live_update_div = ''; | ||||||
| 
 | 
 | ||||||
| 		$blocklist = $this->getBlocklist(); |  | ||||||
| 
 |  | ||||||
| 		$previewing = (($preview) ? ' preview ' : ''); |  | ||||||
| 
 |  | ||||||
| 		if ($mode === self::MODE_NETWORK) { | 		if ($mode === self::MODE_NETWORK) { | ||||||
| 			$items = $this->addChildren($items, false, $order, $uid, $mode); | 			$items = $this->addChildren($items, false, $order, $uid, $mode); | ||||||
| 			if (!$update) { | 			if (!$update) { | ||||||
|  | @ -556,246 +552,14 @@ class Conversation | ||||||
| 
 | 
 | ||||||
| 		$items = $cb['items']; | 		$items = $cb['items']; | ||||||
| 
 | 
 | ||||||
| 		$conv_responses = [ |  | ||||||
| 			'like'        => [], |  | ||||||
| 			'dislike'     => [], |  | ||||||
| 			'attendyes'   => [], |  | ||||||
| 			'attendno'    => [], |  | ||||||
| 			'attendmaybe' => [], |  | ||||||
| 			'announce'    => [], |  | ||||||
| 		]; |  | ||||||
| 
 |  | ||||||
| 		if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'hide_dislike')) { |  | ||||||
| 			unset($conv_responses['dislike']); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// array with html for each thread (parent+comments)
 |  | ||||||
| 		$threads   = []; |  | ||||||
| 		$threadsid = -1; |  | ||||||
| 
 |  | ||||||
| 		$page_template     = Renderer::getMarkupTemplate("conversation.tpl"); |  | ||||||
| 		$formSecurityToken = BaseModule::getFormSecurityToken('contact_action'); | 		$formSecurityToken = BaseModule::getFormSecurityToken('contact_action'); | ||||||
| 
 | 
 | ||||||
| 		if (!empty($items)) { | 		$threads = $this->getThreadList($items, $mode, $preview, $page_dropping, $formSecurityToken); | ||||||
| 			if (in_array($mode, [self::MODE_COMMUNITY, self::MODE_CONTACTS, self::MODE_PROFILE])) { |  | ||||||
| 				$writable = true; |  | ||||||
| 			} else { |  | ||||||
| 				$writable = $items[0]['writable'] || ($items[0]['uid'] == 0) && in_array($items[0]['network'], Protocol::FEDERATED); |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			if (!$this->session->getLocalUserId()) { | 		if (in_array($mode, [self::MODE_FILED, self::MODE_SEARCH, self::MODE_CONTACT_POSTS])) { | ||||||
| 				$writable = false; | 			$page_template = Renderer::getMarkupTemplate('conversation.tpl'); | ||||||
| 			} | 		} else { | ||||||
| 
 | 			$page_template = Renderer::getMarkupTemplate('threaded_conversation.tpl'); | ||||||
| 			if (in_array($mode, [self::MODE_FILED, self::MODE_SEARCH, self::MODE_CONTACT_POSTS])) { |  | ||||||
| 
 |  | ||||||
| 				/* |  | ||||||
| 				* "New Item View" on network page or search page results |  | ||||||
| 				* - just loop through the items and format them minimally for display |  | ||||||
| 				*/ |  | ||||||
| 
 |  | ||||||
| 				$tpl = 'search_item.tpl'; |  | ||||||
| 
 |  | ||||||
| 				$uriids = []; |  | ||||||
| 
 |  | ||||||
| 				foreach ($items as $item) { |  | ||||||
| 					if (in_array($item['uri-id'], $uriids)) { |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$uriids[] = $item['uri-id']; |  | ||||||
| 
 |  | ||||||
| 					if (!$this->item->isVisibleActivity($item)) { |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					if (in_array($item['author-id'], $blocklist)) { |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$threadsid++; |  | ||||||
| 
 |  | ||||||
| 					// prevent private email from leaking.
 |  | ||||||
| 					if ($item['network'] === Protocol::MAIL && $this->session->getLocalUserId() != $item['uid']) { |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$profile_name = $item['author-name']; |  | ||||||
| 					if (!empty($item['author-link']) && empty($item['author-name'])) { |  | ||||||
| 						$profile_name = $item['author-link']; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$tags = Tag::populateFromItem($item); |  | ||||||
| 
 |  | ||||||
| 					$author = [ |  | ||||||
| 						'uid'     => 0, |  | ||||||
| 						'id'      => $item['author-id'], |  | ||||||
| 						'network' => $item['author-network'], |  | ||||||
| 						'url'     => $item['author-link'], |  | ||||||
| 						'alias'   => $item['author-alias'], |  | ||||||
| 					]; |  | ||||||
| 					$profile_link = Contact::magicLinkByContact($author); |  | ||||||
| 
 |  | ||||||
| 					$sparkle = ''; |  | ||||||
| 					if (strpos($profile_link, 'contact/redir/') === 0) { |  | ||||||
| 						$sparkle = ' sparkle'; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$locate = ['location' => $item['location'], 'coord' => $item['coord'], 'html' => '']; |  | ||||||
| 					Hook::callAll('render_location', $locate); |  | ||||||
| 					$location_html = $locate['html'] ?: Strings::escapeHtml($locate['location'] ?: $locate['coord'] ?: ''); |  | ||||||
| 
 |  | ||||||
| 					$this->item->localize($item); |  | ||||||
| 					if ($mode === self::MODE_FILED) { |  | ||||||
| 						$dropping = true; |  | ||||||
| 					} else { |  | ||||||
| 						$dropping = false; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$drop = [ |  | ||||||
| 						'dropping' => $dropping, |  | ||||||
| 						'pagedrop' => $page_dropping, |  | ||||||
| 						'select'   => $this->l10n->t('Select'), |  | ||||||
| 						'delete'   => $this->l10n->t('Delete'), |  | ||||||
| 					]; |  | ||||||
| 
 |  | ||||||
| 					$likebuttons = [ |  | ||||||
| 						'like'     => null, |  | ||||||
| 						'dislike'  => null, |  | ||||||
| 						'share'    => null, |  | ||||||
| 						'announce' => null, |  | ||||||
| 					]; |  | ||||||
| 
 |  | ||||||
| 					if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'hide_dislike')) { |  | ||||||
| 						unset($likebuttons['dislike']); |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$body_html = ItemModel::prepareBody($item, true, $preview); |  | ||||||
| 
 |  | ||||||
| 					[$categories, $folders] = $this->item->determineCategoriesTerms($item, $this->session->getLocalUserId()); |  | ||||||
| 
 |  | ||||||
| 					if (!empty($item['title'])) { |  | ||||||
| 						$title = $item['title']; |  | ||||||
| 					} elseif (!empty($item['content-warning']) && $this->pConfig->get($this->session->getLocalUserId(), 'system', 'disable_cw', false)) { |  | ||||||
| 						$title = ucfirst($item['content-warning']); |  | ||||||
| 					} else { |  | ||||||
| 						$title = ''; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					if (!empty($item['featured'])) { |  | ||||||
| 						$pinned = $this->l10n->t('Pinned item'); |  | ||||||
| 					} else { |  | ||||||
| 						$pinned = ''; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					$tmp_item = [ |  | ||||||
| 						'template'             => $tpl, |  | ||||||
| 						'id'                   => ($preview ? 'P0' : $item['id']), |  | ||||||
| 						'guid'                 => ($preview ? 'Q0' : $item['guid']), |  | ||||||
| 						'commented'            => $item['commented'], |  | ||||||
| 						'received'             => $item['received'], |  | ||||||
| 						'created_date'         => $item['created'], |  | ||||||
| 						'uriid'                => $item['uri-id'], |  | ||||||
| 						'network'              => $item['network'], |  | ||||||
| 						'network_name'         => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network'], $item['author-gsid']), |  | ||||||
| 						'network_icon'         => ContactSelector::networkToIcon($item['network'], $item['author-link'], $item['author-gsid']), |  | ||||||
| 						'linktitle'            => $this->l10n->t('View %s\'s profile @ %s', $profile_name, $item['author-link']), |  | ||||||
| 						'profile_url'          => $profile_link, |  | ||||||
| 						'item_photo_menu_html' => $this->item->photoMenu($item, $formSecurityToken), |  | ||||||
| 						'name'                 => $profile_name, |  | ||||||
| 						'sparkle'              => $sparkle, |  | ||||||
| 						'lock'                 => false, |  | ||||||
| 						'thumb'                => $this->baseURL->remove($this->item->getAuthorAvatar($item)), |  | ||||||
| 						'title'                => $title, |  | ||||||
| 						'body_html'            => $body_html, |  | ||||||
| 						'tags'                 => $tags['tags'], |  | ||||||
| 						'hashtags'             => $tags['hashtags'], |  | ||||||
| 						'mentions'             => $tags['mentions'], |  | ||||||
| 						'implicit_mentions'    => $tags['implicit_mentions'], |  | ||||||
| 						'txt_cats'             => $this->l10n->t('Categories:'), |  | ||||||
| 						'txt_folders'          => $this->l10n->t('Filed under:'), |  | ||||||
| 						'has_cats'             => ((count($categories)) ? 'true' : ''), |  | ||||||
| 						'has_folders'          => ((count($folders)) ? 'true' : ''), |  | ||||||
| 						'categories'           => $categories, |  | ||||||
| 						'folders'              => $folders, |  | ||||||
| 						'text'                 => strip_tags($body_html), |  | ||||||
| 						'localtime'            => DateTimeFormat::local($item['created'], 'r'), |  | ||||||
| 						'utc'                  => DateTimeFormat::utc($item['created'], 'c'), |  | ||||||
| 						'ago'                  => (($item['app']) ? $this->l10n->t('%s from %s', Temporal::getRelativeDate($item['created']), $item['app']) : Temporal::getRelativeDate($item['created'])), |  | ||||||
| 						'location_html'        => $location_html, |  | ||||||
| 						'indent'               => '', |  | ||||||
| 						'owner_name'           => '', |  | ||||||
| 						'owner_url'            => '', |  | ||||||
| 						'owner_photo'          => $this->baseURL->remove($this->item->getOwnerAvatar($item)), |  | ||||||
| 						'plink'                => ItemModel::getPlink($item), |  | ||||||
| 						'edpost'               => false, |  | ||||||
| 						'pinned'               => $pinned, |  | ||||||
| 						'isstarred'            => 'unstarred', |  | ||||||
| 						'star'                 => false, |  | ||||||
| 						'drop'                 => $drop, |  | ||||||
| 						'vote'                 => $likebuttons, |  | ||||||
| 						'like_html'            => '', |  | ||||||
| 						'dislike_html '        => '', |  | ||||||
| 						'comment_html'         => '', |  | ||||||
| 						'conv'                 => ($preview ? '' : ['href' => 'display/' . $item['guid'], 'title' => $this->l10n->t('View in context')]), |  | ||||||
| 						'previewing'           => $previewing, |  | ||||||
| 						'wait'                 => $this->l10n->t('Please wait'), |  | ||||||
| 						'thread_level'         => 1, |  | ||||||
| 					]; |  | ||||||
| 
 |  | ||||||
| 					$arr = ['item' => $item, 'output' => $tmp_item]; |  | ||||||
| 					Hook::callAll('display_item', $arr); |  | ||||||
| 
 |  | ||||||
| 					$threads[$threadsid]['id']      = $item['id']; |  | ||||||
| 					$threads[$threadsid]['network'] = $item['network']; |  | ||||||
| 					$threads[$threadsid]['items']   = [$arr['output']]; |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				// Normal View
 |  | ||||||
| 				$page_template = Renderer::getMarkupTemplate("threaded_conversation.tpl"); |  | ||||||
| 
 |  | ||||||
| 				$conv = new Thread($mode, $preview, $writable); |  | ||||||
| 
 |  | ||||||
| 				/* |  | ||||||
| 				* 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 |  | ||||||
| 				*/ |  | ||||||
| 				foreach ($items as $item) { |  | ||||||
| 					if (in_array($item['author-id'], $blocklist)) { |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					// Can we put this after the visibility check?
 |  | ||||||
| 					$this->builtinActivityPuller($item, $conv_responses); |  | ||||||
| 
 |  | ||||||
| 					// Only add what is visible
 |  | ||||||
| 					if ($item['network'] === Protocol::MAIL && $this->session->getLocalUserId() != $item['uid']) { |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					if (!$this->item->isVisibleActivity($item)) { |  | ||||||
| 						continue; |  | ||||||
| 					} |  | ||||||
| 
 |  | ||||||
| 					/// @todo Check if this call is needed or not
 |  | ||||||
| 					$arr = ['item' => $item]; |  | ||||||
| 					Hook::callAll('display_item', $arr); |  | ||||||
| 
 |  | ||||||
| 					$item['pagedrop'] = $page_dropping; |  | ||||||
| 
 |  | ||||||
| 					if ($item['gravity'] == ItemModel::GRAVITY_PARENT) { |  | ||||||
| 						$item_object = new PostObject($item); |  | ||||||
| 						$conv->addParent($item_object); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				$threads = $conv->getTemplateData($conv_responses, $formSecurityToken); |  | ||||||
| 				if (!$threads) { |  | ||||||
| 					$this->logger->info('[ERROR] conversation : Failed to get template data.'); |  | ||||||
| 					$threads = []; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$o = Renderer::replaceMacros($page_template, [ | 		$o = Renderer::replaceMacros($page_template, [ | ||||||
|  | @ -813,6 +577,91 @@ class Conversation | ||||||
| 		return $o; | 		return $o; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param array  $items | ||||||
|  | 	 * @param string $mode One of self::MODE_* | ||||||
|  | 	 * @param bool   $preview | ||||||
|  | 	 * @param bool   $pagedrop Whether to enable the user to select the thread for deletion | ||||||
|  | 	 * @param string $formSecurityToken A 'contact_action' form security token | ||||||
|  | 	 * @return array | ||||||
|  | 	 * @throws InternalServerErrorException | ||||||
|  | 	 * @throws \ImagickException | ||||||
|  | 	 */ | ||||||
|  | 	public function getThreadList(array $items, string $mode, bool $preview, bool $pagedrop, string $formSecurityToken): array | ||||||
|  | 	{ | ||||||
|  | 		if (in_array($mode, [self::MODE_FILED, self::MODE_SEARCH, self::MODE_CONTACT_POSTS])) { | ||||||
|  | 			$threads = $this->getContextLessThreadList($items, $mode, $preview, $pagedrop, $formSecurityToken); | ||||||
|  | 		} else { | ||||||
|  | 			$conv_responses = [ | ||||||
|  | 				'like'        => [], | ||||||
|  | 				'dislike'     => [], | ||||||
|  | 				'attendyes'   => [], | ||||||
|  | 				'attendno'    => [], | ||||||
|  | 				'attendmaybe' => [], | ||||||
|  | 				'announce'    => [], | ||||||
|  | 			]; | ||||||
|  | 
 | ||||||
|  | 			if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'hide_dislike')) { | ||||||
|  | 				unset($conv_responses['dislike']); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (in_array($mode, [self::MODE_COMMUNITY, self::MODE_CONTACTS, self::MODE_PROFILE])) { | ||||||
|  | 				$writable = true; | ||||||
|  | 			} else { | ||||||
|  | 				$writable = $items[0]['writable'] || ($items[0]['uid'] == 0) && in_array($items[0]['network'], Protocol::FEDERATED); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!$this->session->getLocalUserId()) { | ||||||
|  | 				$writable = false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// Normal View
 | ||||||
|  | 			$conv = new Thread($mode, $preview, $writable); | ||||||
|  | 
 | ||||||
|  | 			/* | ||||||
|  | 			* 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 | ||||||
|  | 			*/ | ||||||
|  | 			foreach ($items as $item) { | ||||||
|  | 				if (in_array($item['author-id'], $this->getBlocklist())) { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// Can we put this after the visibility check?
 | ||||||
|  | 				$this->builtinActivityPuller($item, $conv_responses); | ||||||
|  | 
 | ||||||
|  | 				// Only add what is visible
 | ||||||
|  | 				if ($item['network'] === Protocol::MAIL && $this->session->getLocalUserId() != $item['uid']) { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if (!$this->item->isVisibleActivity($item)) { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				/// @todo Check if this call is needed or not
 | ||||||
|  | 				$arr = ['item' => $item]; | ||||||
|  | 				Hook::callAll('display_item', $arr); | ||||||
|  | 
 | ||||||
|  | 				$item['pagedrop'] = $pagedrop; | ||||||
|  | 
 | ||||||
|  | 				if ($item['gravity'] == ItemModel::GRAVITY_PARENT) { | ||||||
|  | 					$item_object = new PostObject($item); | ||||||
|  | 					$conv->addParent($item_object); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$threads = $conv->getTemplateData($conv_responses, $formSecurityToken); | ||||||
|  | 			if (!$threads) { | ||||||
|  | 				$this->logger->info('[ERROR] conversation : Failed to get template data.'); | ||||||
|  | 				$threads = []; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return $threads; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	private function getBlocklist(): array | 	private function getBlocklist(): array | ||||||
| 	{ | 	{ | ||||||
| 		if (!$this->session->getLocalUserId()) { | 		if (!$this->session->getLocalUserId()) { | ||||||
|  | @ -1494,4 +1343,180 @@ class Conversation | ||||||
| 	{ | 	{ | ||||||
| 		return strcmp($b['created'], $a['created']); | 		return strcmp($b['created'], $a['created']); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * "New Item View" on network page or search page results | ||||||
|  | 	 * - just loop through the items and format them minimally for display | ||||||
|  | 	 * | ||||||
|  | 	 * @param array  $items | ||||||
|  | 	 * @param string $mode              One of self::MODE_* | ||||||
|  | 	 * @param bool   $preview           Whether the display is a preview | ||||||
|  | 	 * @param bool   $pagedrop          Whether the user can select the threads for deletion | ||||||
|  | 	 * @param string $formSecurityToken A 'contact_action' form security token | ||||||
|  | 	 * @return array | ||||||
|  | 	 * @throws InternalServerErrorException | ||||||
|  | 	 * @throws \ImagickException | ||||||
|  | 	 */ | ||||||
|  | 	public function getContextLessThreadList(array $items, string $mode, bool $preview, bool $pagedrop, string $formSecurityToken): array | ||||||
|  | 	{ | ||||||
|  | 		$threads = []; | ||||||
|  | 		$uriids = []; | ||||||
|  | 
 | ||||||
|  | 		foreach ($items as $item) { | ||||||
|  | 			if (in_array($item['uri-id'], $uriids)) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$uriids[] = $item['uri-id']; | ||||||
|  | 
 | ||||||
|  | 			if (!$this->item->isVisibleActivity($item)) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (in_array($item['author-id'], $this->getBlocklist())) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$threadsid++; | ||||||
|  | 
 | ||||||
|  | 			// prevent private email from leaking.
 | ||||||
|  | 			if ($item['network'] === Protocol::MAIL && $this->session->getLocalUserId() != $item['uid']) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$profile_name = $item['author-name']; | ||||||
|  | 			if (!empty($item['author-link']) && empty($item['author-name'])) { | ||||||
|  | 				$profile_name = $item['author-link']; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$tags = Tag::populateFromItem($item); | ||||||
|  | 
 | ||||||
|  | 			$author       = [ | ||||||
|  | 				'uid'     => 0, | ||||||
|  | 				'id'      => $item['author-id'], | ||||||
|  | 				'network' => $item['author-network'], | ||||||
|  | 				'url'     => $item['author-link'], | ||||||
|  | 				'alias'   => $item['author-alias'], | ||||||
|  | 			]; | ||||||
|  | 			$profile_link = Contact::magicLinkByContact($author); | ||||||
|  | 
 | ||||||
|  | 			$sparkle = ''; | ||||||
|  | 			if (strpos($profile_link, 'contact/redir/') === 0) { | ||||||
|  | 				$sparkle = ' sparkle'; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$locate = ['location' => $item['location'], 'coord' => $item['coord'], 'html' => '']; | ||||||
|  | 			Hook::callAll('render_location', $locate); | ||||||
|  | 			$location_html = $locate['html'] ?: Strings::escapeHtml($locate['location'] ?: $locate['coord'] ?: ''); | ||||||
|  | 
 | ||||||
|  | 			$this->item->localize($item); | ||||||
|  | 			if ($mode === self::MODE_FILED) { | ||||||
|  | 				$dropping = true; | ||||||
|  | 			} else { | ||||||
|  | 				$dropping = false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$drop = [ | ||||||
|  | 				'dropping' => $dropping, | ||||||
|  | 				'pagedrop' => $pagedrop, | ||||||
|  | 				'select'   => $this->l10n->t('Select'), | ||||||
|  | 				'delete'   => $this->l10n->t('Delete'), | ||||||
|  | 			]; | ||||||
|  | 
 | ||||||
|  | 			$likebuttons = [ | ||||||
|  | 				'like'     => null, | ||||||
|  | 				'dislike'  => null, | ||||||
|  | 				'share'    => null, | ||||||
|  | 				'announce' => null, | ||||||
|  | 			]; | ||||||
|  | 
 | ||||||
|  | 			if ($this->pConfig->get($this->session->getLocalUserId(), 'system', 'hide_dislike')) { | ||||||
|  | 				unset($likebuttons['dislike']); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$body_html = ItemModel::prepareBody($item, true, $preview); | ||||||
|  | 
 | ||||||
|  | 			[$categories, $folders] = $this->item->determineCategoriesTerms($item, $this->session->getLocalUserId()); | ||||||
|  | 
 | ||||||
|  | 			if (!empty($item['title'])) { | ||||||
|  | 				$title = $item['title']; | ||||||
|  | 			} elseif (!empty($item['content-warning']) && $this->pConfig->get($this->session->getLocalUserId(), 'system', 'disable_cw', false)) { | ||||||
|  | 				$title = ucfirst($item['content-warning']); | ||||||
|  | 			} else { | ||||||
|  | 				$title = ''; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!empty($item['featured'])) { | ||||||
|  | 				$pinned = $this->l10n->t('Pinned item'); | ||||||
|  | 			} else { | ||||||
|  | 				$pinned = ''; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			$tmp_item = [ | ||||||
|  | 				'template'             => 'search_item.tpl', | ||||||
|  | 				'id'                   => ($preview ? 'P0' : $item['id']), | ||||||
|  | 				'guid'                 => ($preview ? 'Q0' : $item['guid']), | ||||||
|  | 				'commented'            => $item['commented'], | ||||||
|  | 				'received'             => $item['received'], | ||||||
|  | 				'created_date'         => $item['created'], | ||||||
|  | 				'uriid'                => $item['uri-id'], | ||||||
|  | 				'network'              => $item['network'], | ||||||
|  | 				'network_name'         => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network'], $item['author-gsid']), | ||||||
|  | 				'network_icon'         => ContactSelector::networkToIcon($item['network'], $item['author-link'], $item['author-gsid']), | ||||||
|  | 				'linktitle'            => $this->l10n->t('View %s\'s profile @ %s', $profile_name, $item['author-link']), | ||||||
|  | 				'profile_url'          => $profile_link, | ||||||
|  | 				'item_photo_menu_html' => $this->item->photoMenu($item, $formSecurityToken), | ||||||
|  | 				'name'                 => $profile_name, | ||||||
|  | 				'sparkle'              => $sparkle, | ||||||
|  | 				'lock'                 => false, | ||||||
|  | 				'thumb'                => $this->baseURL->remove($this->item->getAuthorAvatar($item)), | ||||||
|  | 				'title'                => $title, | ||||||
|  | 				'body_html'            => $body_html, | ||||||
|  | 				'tags'                 => $tags['tags'], | ||||||
|  | 				'hashtags'             => $tags['hashtags'], | ||||||
|  | 				'mentions'             => $tags['mentions'], | ||||||
|  | 				'implicit_mentions'    => $tags['implicit_mentions'], | ||||||
|  | 				'txt_cats'             => $this->l10n->t('Categories:'), | ||||||
|  | 				'txt_folders'          => $this->l10n->t('Filed under:'), | ||||||
|  | 				'has_cats'             => ((count($categories)) ? 'true' : ''), | ||||||
|  | 				'has_folders'          => ((count($folders)) ? 'true' : ''), | ||||||
|  | 				'categories'           => $categories, | ||||||
|  | 				'folders'              => $folders, | ||||||
|  | 				'text'                 => strip_tags($body_html), | ||||||
|  | 				'localtime'            => DateTimeFormat::local($item['created'], 'r'), | ||||||
|  | 				'utc'                  => DateTimeFormat::utc($item['created'], 'c'), | ||||||
|  | 				'ago'                  => (($item['app']) ? $this->l10n->t('%s from %s', Temporal::getRelativeDate($item['created']), $item['app']) : Temporal::getRelativeDate($item['created'])), | ||||||
|  | 				'location_html'        => $location_html, | ||||||
|  | 				'indent'               => '', | ||||||
|  | 				'owner_name'           => '', | ||||||
|  | 				'owner_url'            => '', | ||||||
|  | 				'owner_photo'          => $this->baseURL->remove($this->item->getOwnerAvatar($item)), | ||||||
|  | 				'plink'                => ItemModel::getPlink($item), | ||||||
|  | 				'edpost'               => false, | ||||||
|  | 				'pinned'               => $pinned, | ||||||
|  | 				'isstarred'            => 'unstarred', | ||||||
|  | 				'star'                 => false, | ||||||
|  | 				'drop'                 => $drop, | ||||||
|  | 				'vote'                 => $likebuttons, | ||||||
|  | 				'like_html'            => '', | ||||||
|  | 				'dislike_html '        => '', | ||||||
|  | 				'comment_html'         => '', | ||||||
|  | 				'conv'                 => $preview ? '' : ['href' => 'display/' . $item['guid'], 'title' => $this->l10n->t('View in context')], | ||||||
|  | 				'previewing'           => $preview ? ' preview ' : '', | ||||||
|  | 				'wait'                 => $this->l10n->t('Please wait'), | ||||||
|  | 				'thread_level'         => 1, | ||||||
|  | 			]; | ||||||
|  | 
 | ||||||
|  | 			$arr = ['item' => $item, 'output' => $tmp_item]; | ||||||
|  | 			Hook::callAll('display_item', $arr); | ||||||
|  | 
 | ||||||
|  | 			$threads[] = [ | ||||||
|  | 				'id'      => $item['id'], | ||||||
|  | 				'network' => $item['network'], | ||||||
|  | 				'items'   => [$arr['output']], | ||||||
|  | 			]; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return $threads; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1626,7 +1626,7 @@ class Contact | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			$o .= DI::conversation()->create($items, ConversationContent::MODE_CONTACTS, $update, false, 'pinned_commented', DI::userSession()->getLocalUserId()); | 			$o .= DI::conversation()->render($items, ConversationContent::MODE_CONTACTS, $update, false, 'pinned_commented', DI::userSession()->getLocalUserId()); | ||||||
| 		} else { | 		} else { | ||||||
| 			$fields = array_merge(Item::DISPLAY_FIELDLIST, ['featured']); | 			$fields = array_merge(Item::DISPLAY_FIELDLIST, ['featured']); | ||||||
| 			$items = Post::toArray(Post::selectForUser(DI::userSession()->getLocalUserId(), $fields, $condition, $params)); | 			$items = Post::toArray(Post::selectForUser(DI::userSession()->getLocalUserId(), $fields, $condition, $params)); | ||||||
|  | @ -1643,7 +1643,7 @@ class Contact | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			$o .= DI::conversation()->create($items, ConversationContent::MODE_CONTACT_POSTS, $update); | 			$o .= DI::conversation()->render($items, ConversationContent::MODE_CONTACT_POSTS, $update); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!$update) { | 		if (!$update) { | ||||||
|  |  | ||||||
|  | @ -92,7 +92,7 @@ class Community extends BaseModule | ||||||
| 					'accesskey' => 'l' | 					'accesskey' => 'l' | ||||||
| 				]; | 				]; | ||||||
| 			} | 			} | ||||||
| 	 | 
 | ||||||
| 			if (DI::userSession()->isAuthenticated() || in_array(self::$page_style, [self::LOCAL_AND_GLOBAL, self::GLOBAL])) { | 			if (DI::userSession()->isAuthenticated() || in_array(self::$page_style, [self::LOCAL_AND_GLOBAL, self::GLOBAL])) { | ||||||
| 				$tabs[] = [ | 				$tabs[] = [ | ||||||
| 					'label' => DI::l10n()->t('Global Community'), | 					'label' => DI::l10n()->t('Global Community'), | ||||||
|  | @ -110,14 +110,14 @@ class Community extends BaseModule | ||||||
| 			Nav::setSelected('community'); | 			Nav::setSelected('community'); | ||||||
| 
 | 
 | ||||||
| 			DI::page()['aside'] .= Widget::accountTypes('community/' . self::$content, self::$accountTypeString); | 			DI::page()['aside'] .= Widget::accountTypes('community/' . self::$content, self::$accountTypeString); | ||||||
| 	 | 
 | ||||||
| 			if (DI::userSession()->getLocalUserId() && DI::config()->get('system', 'community_no_sharer')) { | 			if (DI::userSession()->getLocalUserId() && DI::config()->get('system', 'community_no_sharer')) { | ||||||
| 				$path = self::$content; | 				$path = self::$content; | ||||||
| 				if (!empty($this->parameters['accounttype'])) { | 				if (!empty($this->parameters['accounttype'])) { | ||||||
| 					$path .= '/' . $this->parameters['accounttype']; | 					$path .= '/' . $this->parameters['accounttype']; | ||||||
| 				} | 				} | ||||||
| 				$query_parameters = []; | 				$query_parameters = []; | ||||||
| 		 | 
 | ||||||
| 				if (!empty($_GET['min_id'])) { | 				if (!empty($_GET['min_id'])) { | ||||||
| 					$query_parameters['min_id'] = $_GET['min_id']; | 					$query_parameters['min_id'] = $_GET['min_id']; | ||||||
| 				} | 				} | ||||||
|  | @ -127,7 +127,7 @@ class Community extends BaseModule | ||||||
| 				if (!empty($_GET['last_commented'])) { | 				if (!empty($_GET['last_commented'])) { | ||||||
| 					$query_parameters['max_id'] = $_GET['last_commented']; | 					$query_parameters['max_id'] = $_GET['last_commented']; | ||||||
| 				} | 				} | ||||||
| 		 | 
 | ||||||
| 				$path_all = $path . (!empty($query_parameters) ? '?' . http_build_query($query_parameters) : ''); | 				$path_all = $path . (!empty($query_parameters) ? '?' . http_build_query($query_parameters) : ''); | ||||||
| 				$path_no_sharer = $path . '?' . http_build_query(array_merge($query_parameters, ['no_sharer' => true])); | 				$path_no_sharer = $path . '?' . http_build_query(array_merge($query_parameters, ['no_sharer' => true])); | ||||||
| 				DI::page()['aside'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/community_sharer.tpl'), [ | 				DI::page()['aside'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/community_sharer.tpl'), [ | ||||||
|  | @ -139,7 +139,7 @@ class Community extends BaseModule | ||||||
| 					'$no_sharer_label' => DI::l10n()->t('Hide'), | 					'$no_sharer_label' => DI::l10n()->t('Hide'), | ||||||
| 				]); | 				]); | ||||||
| 			} | 			} | ||||||
| 	 | 
 | ||||||
| 			if (Feature::isEnabled(DI::userSession()->getLocalUserId(), 'trending_tags')) { | 			if (Feature::isEnabled(DI::userSession()->getLocalUserId(), 'trending_tags')) { | ||||||
| 				DI::page()['aside'] .= TrendingTags::getHTML(self::$content); | 				DI::page()['aside'] .= TrendingTags::getHTML(self::$content); | ||||||
| 			} | 			} | ||||||
|  | @ -157,7 +157,7 @@ class Community extends BaseModule | ||||||
| 			return $o; | 			return $o; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$o .= DI::conversation()->create($items, Conversation::MODE_COMMUNITY, false, false, 'commented', DI::userSession()->getLocalUserId()); | 		$o .= DI::conversation()->render($items, Conversation::MODE_COMMUNITY, false, false, 'commented', DI::userSession()->getLocalUserId()); | ||||||
| 
 | 
 | ||||||
| 		$pager = new BoundariesPager( | 		$pager = new BoundariesPager( | ||||||
| 			DI::l10n(), | 			DI::l10n(), | ||||||
|  | @ -339,7 +339,7 @@ class Community extends BaseModule | ||||||
| 				$condition[0] .= " AND NOT `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `post-user`.`uid` = ? AND `post-user`.`uri-id` = `post-thread-user-view`.`uri-id`)"; | 				$condition[0] .= " AND NOT `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `post-user`.`uid` = ? AND `post-user`.`uri-id` = `post-thread-user-view`.`uri-id`)"; | ||||||
| 				$condition[] = DI::userSession()->getLocalUserId(); | 				$condition[] = DI::userSession()->getLocalUserId(); | ||||||
| 			} | 			} | ||||||
| 	 | 
 | ||||||
| 			if (isset($max_id)) { | 			if (isset($max_id)) { | ||||||
| 				$condition[0] .= " AND `commented` < ?"; | 				$condition[0] .= " AND `commented` < ?"; | ||||||
| 				$condition[] = $max_id; | 				$condition[] = $max_id; | ||||||
|  |  | ||||||
|  | @ -201,7 +201,7 @@ class Network extends BaseModule | ||||||
| 			$ordering = '`commented`'; | 			$ordering = '`commented`'; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$o .= DI::conversation()->create($items, Conversation::MODE_NETWORK, false, false, $ordering, DI::userSession()->getLocalUserId()); | 		$o .= DI::conversation()->render($items, Conversation::MODE_NETWORK, false, false, $ordering, DI::userSession()->getLocalUserId()); | ||||||
| 
 | 
 | ||||||
| 		if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll')) { | 		if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll')) { | ||||||
| 			$o .= HTML::scrollLoader(); | 			$o .= HTML::scrollLoader(); | ||||||
|  |  | ||||||
|  | @ -275,7 +275,7 @@ class Display extends BaseModule | ||||||
| 			$output .= $this->conversation->statusEditor([], 0, true); | 			$output .= $this->conversation->statusEditor([], 0, true); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$output .= $this->conversation->create([$item], Conversation::MODE_DISPLAY, $updateUid, false, 'commented', $itemUid); | 		$output .= $this->conversation->render([$item], Conversation::MODE_DISPLAY, $updateUid, false, 'commented', $itemUid); | ||||||
| 
 | 
 | ||||||
| 		return $output; | 		return $output; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -240,7 +240,7 @@ class Conversations extends BaseProfile | ||||||
| 			$items  = array_merge($items, $pinned); | 			$items  = array_merge($items, $pinned); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$o .= $this->conversation->create($items, Conversation::MODE_PROFILE, false, false, 'pinned_received', $profile['uid']); | 		$o .= $this->conversation->render($items, Conversation::MODE_PROFILE, false, false, 'pinned_received', $profile['uid']); | ||||||
| 
 | 
 | ||||||
| 		$o .= $pager->renderMinimal(count($items)); | 		$o .= $pager->renderMinimal(count($items)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -99,7 +99,7 @@ class Filed extends BaseSearch | ||||||
| 
 | 
 | ||||||
| 		$items = Post::toArray(Post::selectForUser(DI::userSession()->getLocalUserId(), Item::DISPLAY_FIELDLIST, $item_condition, $item_params)); | 		$items = Post::toArray(Post::selectForUser(DI::userSession()->getLocalUserId(), Item::DISPLAY_FIELDLIST, $item_condition, $item_params)); | ||||||
| 
 | 
 | ||||||
| 		$o .= DI::conversation()->create($items, Conversation::MODE_FILED, false, false, '', DI::userSession()->getLocalUserId()); | 		$o .= DI::conversation()->render($items, Conversation::MODE_FILED, false, false, '', DI::userSession()->getLocalUserId()); | ||||||
| 
 | 
 | ||||||
| 		if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll')) { | 		if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll')) { | ||||||
| 			$o .= HTML::scrollLoader(); | 			$o .= HTML::scrollLoader(); | ||||||
|  |  | ||||||
|  | @ -213,7 +213,7 @@ class Index extends BaseSearch | ||||||
| 
 | 
 | ||||||
| 		Logger::info('Start Conversation.', ['q' => $search]); | 		Logger::info('Start Conversation.', ['q' => $search]); | ||||||
| 
 | 
 | ||||||
| 		$o .= DI::conversation()->create($items, Conversation::MODE_SEARCH, false, false, 'commented', DI::userSession()->getLocalUserId()); | 		$o .= DI::conversation()->render($items, Conversation::MODE_SEARCH, false, false, 'commented', DI::userSession()->getLocalUserId()); | ||||||
| 
 | 
 | ||||||
| 		if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll')) { | 		if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'infinite_scroll')) { | ||||||
| 			$o .= HTML::scrollLoader(); | 			$o .= HTML::scrollLoader(); | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ class Community extends CommunityModule | ||||||
| 
 | 
 | ||||||
| 		$o = ''; | 		$o = ''; | ||||||
| 		if (!empty($request['force'])) { | 		if (!empty($request['force'])) { | ||||||
| 			$o = DI::conversation()->create(self::getItems(), Conversation::MODE_COMMUNITY, true, false, 'commented', DI::userSession()->getLocalUserId()); | 			$o = DI::conversation()->render(self::getItems(), Conversation::MODE_COMMUNITY, true, false, 'commented', DI::userSession()->getLocalUserId()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		System::htmlUpdateExit($o); | 		System::htmlUpdateExit($o); | ||||||
|  |  | ||||||
|  | @ -79,7 +79,7 @@ class Network extends NetworkModule | ||||||
| 			$ordering = '`commented`'; | 			$ordering = '`commented`'; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$o = DI::conversation()->create($items, Conversation::MODE_NETWORK, $profile_uid, false, $ordering, DI::userSession()->getLocalUserId()); | 		$o = DI::conversation()->render($items, Conversation::MODE_NETWORK, $profile_uid, false, $ordering, DI::userSession()->getLocalUserId()); | ||||||
| 
 | 
 | ||||||
| 		System::htmlUpdateExit($o); | 		System::htmlUpdateExit($o); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -116,7 +116,7 @@ class Profile extends BaseModule | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		$o .= DI::conversation()->create($items, Conversation::MODE_PROFILE, $a->getProfileOwner(), false, 'received', $a->getProfileOwner()); | 		$o .= DI::conversation()->render($items, Conversation::MODE_PROFILE, $a->getProfileOwner(), false, 'received', $a->getProfileOwner()); | ||||||
| 
 | 
 | ||||||
| 		System::htmlUpdateExit($o); | 		System::htmlUpdateExit($o); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -190,13 +190,13 @@ class Thread | ||||||
| 	 * We should find a way to avoid using those arguments (at least most of them) | 	 * We should find a way to avoid using those arguments (at least most of them) | ||||||
| 	 * | 	 * | ||||||
| 	 * @param array $conv_responses data | 	 * @param array $conv_responses data | ||||||
| 	 * @param string $formSecurityToken A security Token to avoid CSF attacks | 	 * @param string $formSecurityToken A 'contact_action' form security token | ||||||
| 	 * | 	 * | ||||||
| 	 * @return mixed The data requested on success | 	 * @return mixed The data requested on success | ||||||
| 	 *               false on failure | 	 *               false on failure | ||||||
| 	 * @throws \Exception | 	 * @throws \Exception | ||||||
| 	 */ | 	 */ | ||||||
| 	public function getTemplateData($conv_responses, string $formSecurityToken) | 	public function getTemplateData(array $conv_responses, string $formSecurityToken) | ||||||
| 	{ | 	{ | ||||||
| 		$result = []; | 		$result = []; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue