Merge pull request #10760 from annando/conversation-moved

The conversation functionality moved to a class
This commit is contained in:
Hypolite Petovan 2021-09-26 10:03:26 -04:00 committed by GitHub
commit 2a88262732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 2021 additions and 1969 deletions

View File

@ -33,6 +33,7 @@ return $config
'operators' => [
'=>' => 'align_single_space_minimal',
'=' => 'align_single_space_minimal',
'??' => 'align_single_space_minimal',
],
],
'blank_line_after_namespace' => true,
@ -65,6 +66,7 @@ return $config
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'switch_case_space' => true,
'ternary_operator_spaces' => false,
'visibility_required' => [
'elements' => ['property', 'method']
],

View File

@ -84,7 +84,6 @@
"Friendica\\Addon\\": "addon/"
},
"files": [
"include/conversation.php",
"include/dba.php",
"include/enotify.php",
"boot.php"

View File

@ -526,7 +526,7 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php
### src/Content/Conversation.php
Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate);

View File

@ -220,7 +220,7 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php
### src/Content/Conversation.php
Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate);

View File

@ -2997,7 +2997,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
list($status_user, $author_user, $owner_user) = api_item_get_user($a, $item);
}
localize_item($item);
DI::contentItem()->localize($item);
$in_reply_to = api_in_reply_to($item);

File diff suppressed because it is too large Load Diff

View File

@ -272,7 +272,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
// We need the editor here to be able to reshare an item.
if ($is_owner && !$update) {
$o .= status_editor($a, [], 0, true);
$o .= DI::conversation()->statusEditor([], 0, true);
}
$sql_extra = Item::getPermissionsSQLByUserId($page_uid);
@ -306,7 +306,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
$o .= "<script> var netargs = '?uri_id=" . $item['uri-id'] . "'; </script>";
}
$o .= conversation($a, [$item], 'display', $update_uid, false, 'commented', $item_uid);
$o .= DI::conversation()->create([$item], 'display', $update_uid, false, 'commented', $item_uid);
// Preparing the meta header
$description = trim(BBCode::toPlaintext($item['body']));

View File

@ -677,7 +677,7 @@ function item_post(App $a) {
$datarray["uri-id"] = -1;
$datarray["author-network"] = Protocol::DFRN;
$o = conversation($a, [array_merge($contact_record, $datarray)], 'search', false, true);
$o = DI::conversation()->create([array_merge($contact_record, $datarray)], 'search', false, true);
System::jsonExit(['preview' => $o]);
}

View File

@ -57,7 +57,7 @@ function notes_content(App $a, $update = false)
'acl_data' => '',
];
$o .= status_editor($a, $x, $a->getContactId());
$o .= DI::conversation()->statusEditor($x, $a->getContactId());
}
$condition = ['uid' => local_user(), 'post-type' => Item::PT_PERSONAL_NOTE, 'gravity' => GRAVITY_PARENT,
@ -84,7 +84,7 @@ function notes_content(App $a, $update = false)
$count = count($notes);
$o .= conversation($a, $notes, 'notes', $update);
$o .= DI::conversation()->create($notes, 'notes', $update);
}
$o .= $pager->renderMinimal($count);

View File

@ -1394,15 +1394,15 @@ function photos_content(App $a)
// display comments
if (DBA::isResult($items)) {
foreach ($items as $item) {
builtin_activity_puller($item, $conv_responses);
DI::conversation()->builtinActivityPuller($item, $conv_responses);
}
if (!empty($conv_responses['like'][$link_item['uri']])) {
$like = format_activity($conv_responses['like'][$link_item['uri']]['links'], 'like', $link_item['id']);
$like = DI::conversation()->formatActivity($conv_responses['like'][$link_item['uri']]['links'], 'like', $link_item['id']);
}
if (!empty($conv_responses['dislike'][$link_item['uri']])) {
$dislike = format_activity($conv_responses['dislike'][$link_item['uri']]['links'], 'dislike', $link_item['id']);
$dislike = DI::conversation()->formatActivity($conv_responses['dislike'][$link_item['uri']]['links'], 'dislike', $link_item['id']);
}
if (($can_post || Security::canWriteToUserWall($owner_uid))) {

1226
src/Content/Conversation.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -21,16 +21,39 @@
namespace Friendica\Content;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Protocol;
use Friendica\Core\Session;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Item as ModelItem;
use Friendica\Model\Tag;
use Friendica\Model\Post;
use Friendica\Protocol\Activity;
use Friendica\Util\Profiler;
use Friendica\Util\Strings;
use Friendica\Util\XML;
/**
* A content helper class for displaying items
*/
class Item
{
/** @var Activity */
private $activity;
/** @var L10n */
private $l10n;
/** @var Profiler */
private $profiler;
public function __construct(Profiler $profiler, Activity $activity, L10n $l10n)
{
$this->profiler = $profiler;
$this->activity = $activity;
$this->l10n = $l10n;
}
/**
* Return array with details for categories and folders for an item
*
@ -221,4 +244,261 @@ class Item
return ['replaced' => $replaced, 'contact' => $contact];
}
/**
* Render actions localized
*
* @param $item
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function localize(&$item)
{
$this->profiler->startRecording('rendering');
/// @todo The following functionality needs to be cleaned up.
if (!empty($item['verb'])) {
$xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">";
if (stristr($item['verb'], Activity::POKE)) {
$verb = urldecode(substr($item['verb'], strpos($item['verb'],'#') + 1));
if (!$verb) {
$this->profiler->stopRecording();
return;
}
if ($item['object-type'] == "" || $item['object-type'] !== Activity\ObjectType::PERSON) {
$this->profiler->stopRecording();
return;
}
$obj = XML::parseString($xmlhead . $item['object']);
$Bname = $obj->title;
$Blink = $obj->id;
$Bphoto = "";
foreach ($obj->link as $l) {
$atts = $l->attributes();
switch ($atts['rel']) {
case "alternate": $Blink = $atts['href'];
case "photo": $Bphoto = $atts['href'];
}
}
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$A = '[url=' . Contact::magicLinkByContact($author) . ']' . $item['author-name'] . '[/url]';
if (!empty($Blink)) {
$B = '[url=' . Contact::magicLink($Blink) . ']' . $Bname . '[/url]';
} else {
$B = '';
}
if ($Bphoto != "" && !empty($Blink)) {
$Bphoto = '[url=' . Contact::magicLink($Blink) . '][img=80x80]' . $Bphoto . '[/img][/url]';
}
/*
* we can't have a translation string with three positions but no distinguishable text
* So here is the translate string.
*/
$txt = $this->l10n->t('%1$s poked %2$s');
// now translate the verb
$poked_t = trim(sprintf($txt, '', ''));
$txt = str_replace($poked_t, $this->l10n->t($verb), $txt);
// then do the sprintf on the translation string
$item['body'] = sprintf($txt, $A, $B) . "\n\n\n" . $Bphoto;
}
if ($this->activity->match($item['verb'], Activity::TAG)) {
$fields = ['author-id', 'author-link', 'author-name', 'author-network',
'verb', 'object-type', 'resource-id', 'body', 'plink'];
$obj = Post::selectFirst($fields, ['uri' => $item['parent-uri']]);
if (!DBA::isResult($obj)) {
$this->profiler->stopRecording();
return;
}
$author_arr = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$author = '[url=' . Contact::magicLinkByContact($author_arr) . ']' . $item['author-name'] . '[/url]';
$author_arr = ['uid' => 0, 'id' => $obj['author-id'],
'network' => $obj['author-network'], 'url' => $obj['author-link']];
$objauthor = '[url=' . Contact::magicLinkByContact($author_arr) . ']' . $obj['author-name'] . '[/url]';
switch ($obj['verb']) {
case Activity::POST:
switch ($obj['object-type']) {
case Activity\ObjectType::EVENT:
$post_type = $this->l10n->t('event');
break;
default:
$post_type = $this->l10n->t('status');
}
break;
default:
if ($obj['resource-id']) {
$post_type = $this->l10n->t('photo');
$m=[]; preg_match("/\[url=([^]]*)\]/", $obj['body'], $m);
$rr['plink'] = $m[1];
} else {
$post_type = $this->l10n->t('status');
}
// Let's break everthing ... ;-)
break;
}
$plink = '[url=' . $obj['plink'] . ']' . $post_type . '[/url]';
$parsedobj = XML::parseString($xmlhead . $item['object']);
$tag = sprintf('#[url=%s]%s[/url]', $parsedobj->id, $parsedobj->content);
$item['body'] = $this->l10n->t('%1$s tagged %2$s\'s %3$s with %4$s', $author, $objauthor, $plink, $tag);
}
}
$matches = null;
if (preg_match_all('/@\[url=(.*?)\]/is', $item['body'], $matches, PREG_SET_ORDER)) {
foreach ($matches as $mtch) {
if (!strpos($mtch[1], 'zrl=')) {
$item['body'] = str_replace($mtch[0], '@[url=' . Contact::magicLink($mtch[1]) . ']', $item['body']);
}
}
}
// add sparkle links to appropriate permalinks
// Only create a redirection to a magic link when logged in
if (!empty($item['plink']) && Session::isAuthenticated() && $item['private'] == ModelItem::PRIVATE) {
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$item['plink'] = Contact::magicLinkByContact($author, $item['plink']);
}
$this->profiler->stopRecording();
}
public function photoMenu($item, string $formSecurityToken)
{
$this->profiler->startRecording('rendering');
$sub_link = '';
$poke_link = '';
$contact_url = '';
$pm_url = '';
$status_link = '';
$photos_link = '';
$posts_link = '';
$block_link = '';
$ignore_link = '';
if (local_user() && local_user() == $item['uid'] && $item['gravity'] == GRAVITY_PARENT && !$item['self'] && !$item['mention']) {
$sub_link = 'javascript:doFollowThread(' . $item['id'] . '); return false;';
}
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$profile_link = Contact::magicLinkByContact($author, $item['author-link']);
$sparkle = (strpos($profile_link, 'redir/') === 0);
$cid = 0;
$pcid = $item['author-id'];
$network = '';
$rel = 0;
$condition = ['uid' => local_user(), 'nurl' => Strings::normaliseLink($item['author-link'])];
$contact = DBA::selectFirst('contact', ['id', 'network', 'rel'], $condition);
if (DBA::isResult($contact)) {
$cid = $contact['id'];
$network = $contact['network'];
$rel = $contact['rel'];
}
if ($sparkle) {
$status_link = $profile_link . '/status';
$photos_link = str_replace('/profile/', '/photos/', $profile_link);
$profile_link = $profile_link . '/profile';
}
if (!empty($pcid)) {
$contact_url = 'contact/' . $pcid;
$posts_link = $contact_url . '/posts';
$block_link = $item['self'] ? '' : $contact_url . '/block?t=' . $formSecurityToken;
$ignore_link = $item['self'] ? '' : $contact_url . '/ignore?t=' . $formSecurityToken;
}
if ($cid && !$item['self']) {
$contact_url = 'contact/' . $cid;
$poke_link = $contact_url . '/poke';
$posts_link = $contact_url . '/posts';
if (in_array($network, [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA])) {
$pm_url = 'message/new/' . $cid;
}
}
if (local_user()) {
$menu = [
$this->l10n->t('Follow Thread') => $sub_link,
$this->l10n->t('View Status') => $status_link,
$this->l10n->t('View Profile') => $profile_link,
$this->l10n->t('View Photos') => $photos_link,
$this->l10n->t('Network Posts') => $posts_link,
$this->l10n->t('View Contact') => $contact_url,
$this->l10n->t('Send PM') => $pm_url,
$this->l10n->t('Block') => $block_link,
$this->l10n->t('Ignore') => $ignore_link
];
if (!empty($item['language'])) {
$menu[$this->l10n->t('Languages')] = 'javascript:alert(\'' . ModelItem::getLanguageMessage($item) . '\');';
}
if ($network == Protocol::DFRN) {
$menu[$this->l10n->t("Poke")] = $poke_link;
}
if ((($cid == 0) || ($rel == Contact::FOLLOWER)) &&
in_array($item['network'], Protocol::FEDERATED)) {
$menu[$this->l10n->t('Connect/Follow')] = 'follow?url=' . urlencode($item['author-link']) . '&auto=1';
}
} else {
$menu = [$this->l10n->t('View Profile') => $item['author-link']];
}
$args = ['item' => $item, 'menu' => $menu];
Hook::callAll('item_photo_menu', $args);
$menu = $args['menu'];
$o = '';
foreach ($menu as $k => $v) {
if (strpos($v, 'javascript:') === 0) {
$v = substr($v, 11);
$o .= '<li role="menuitem"><a onclick="' . $v . '">' . $k . '</a></li>' . PHP_EOL;
} elseif ($v) {
$o .= '<li role="menuitem"><a href="' . $v . '">' . $k . '</a></li>' . PHP_EOL;
}
}
$this->profiler->stopRecording();
return $o;
}
public function visibleActivity($item) {
if (empty($item['verb']) || $this->activity->isHidden($item['verb'])) {
return false;
}
// @TODO below if() block can be rewritten to a single line: $isVisible = allConditionsHere;
if ($this->activity->match($item['verb'], Activity::FOLLOW) &&
$item['object-type'] === Activity\ObjectType::NOTE &&
empty($item['self']) &&
$item['uid'] == local_user()) {
return false;
}
return true;
}
}

View File

@ -134,6 +134,14 @@ abstract class DI
return self::$dice->create(Content\Item::class);
}
/**
* @return Content\Conversation
*/
public static function conversation()
{
return self::$dice->create(Content\Conversation::class);
}
/**
* @return Content\Text\BBCode\Video
*/

View File

@ -1420,11 +1420,11 @@ class Contact
if ($thread_mode) {
$items = Post::toArray(Post::selectForUser(local_user(), ['uri-id', 'gravity', 'parent-uri-id', 'thr-parent-id', 'author-id'], $condition, $params));
$o .= conversation($a, $items, 'contacts', $update, false, 'commented', local_user());
$o .= DI::conversation()->create($items, 'contacts', $update, false, 'commented', local_user());
} else {
$items = Post::toArray(Post::selectForUser(local_user(), Item::DISPLAY_FIELDLIST, $condition, $params));
$o .= conversation($a, $items, 'contact-posts', $update);
$o .= DI::conversation()->create($items, 'contact-posts', $update);
}
if (!$update) {

View File

@ -38,7 +38,6 @@ class Bookmarklet extends BaseModule
{
$_GET['mode'] = 'minimal';
$app = DI::app();
$config = DI::config();
if (!local_user()) {
@ -61,7 +60,7 @@ class Bookmarklet extends BaseModule
'title' => trim($_REQUEST['title'] ?? '', '*'),
'content' => $content
];
$output = status_editor($app, $x, 0, false);
$output = DI::conversation()->statusEditor($x, 0, false);
$output .= "<script>window.resizeTo(800,550);</script>";
} else {
$output = '<h2>' . DI::l10n()->t('The post was created') . '</h2>';

View File

@ -951,7 +951,7 @@ class Contact extends BaseModule
if (!$update) {
// We need the editor here to be able to reshare an item.
if (local_user()) {
$o = status_editor($a, [], 0, true);
$o = DI::conversation()->statusEditor([], 0, true);
}
}

View File

@ -127,7 +127,7 @@ class Community extends BaseModule
// We need the editor here to be able to reshare an item.
if (Session::isAuthenticated()) {
$o .= status_editor(DI::app(), [], 0, true);
$o .= DI::conversation()->statusEditor([], 0, true);
}
}
@ -138,7 +138,7 @@ class Community extends BaseModule
return $o;
}
$o .= conversation(DI::app(), $items, 'community', false, false, 'commented', local_user());
$o .= DI::conversation()->create($items, 'community', false, false, 'commented', local_user());
$pager = new BoundariesPager(
DI::l10n(),

View File

@ -145,7 +145,7 @@ class Network extends BaseModule
'content' => $content,
];
$o .= status_editor($a, $x);
$o .= DI::conversation()->statusEditor($x);
}
if (self::$groupId) {
@ -178,7 +178,7 @@ class Network extends BaseModule
$ordering = '`commented`';
}
$o .= conversation(DI::app(), $items, 'network', false, false, $ordering, local_user());
$o .= DI::conversation()->create($items, 'network', false, false, $ordering, local_user());
if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader();

View File

@ -132,7 +132,7 @@ class Status extends BaseProfile
'profile_uid' => $profile['uid'],
];
$o .= status_editor($a, $x);
$o .= DI::conversation()->statusEditor($x);
}
// Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
@ -224,7 +224,7 @@ class Status extends BaseProfile
$items = array_merge($items, $pinned);
}
$o .= conversation($a, $items, 'profile', false, false, 'pinned_received', $profile['uid']);
$o .= DI::conversation()->create($items, 'profile', false, false, 'pinned_received', $profile['uid']);
$o .= $pager->renderMinimal(count($items));

View File

@ -79,7 +79,7 @@ class Filed extends BaseSearch
$items = Post::toArray(Post::selectForUser(local_user(), Item::DISPLAY_FIELDLIST, $item_condition, $item_params));
$o .= conversation(DI::app(), $items, 'filed', false, false, '', local_user());
$o .= DI::conversation()->create($items, 'filed', false, false, '', local_user());
if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader();

View File

@ -200,7 +200,7 @@ class Index extends BaseSearch
Logger::info('Start Conversation.', ['q' => $search]);
$o .= conversation(DI::app(), $items, 'search', false, false, 'commented', local_user());
$o .= DI::conversation()->create($items, 'search', false, false, 'commented', local_user());
if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader();

View File

@ -39,7 +39,7 @@ class Community extends CommunityModule
$o = '';
if (!empty($_GET['force']) || !DI::pConfig()->get(local_user(), 'system', 'no_auto_update')) {
$o = conversation(DI::app(), self::getItems(), 'community', true, false, 'commented', local_user());
$o = DI::conversation()->create(self::getItems(), 'community', true, false, 'commented', local_user());
}
System::htmlUpdateExit($o);

View File

@ -53,7 +53,7 @@ class Network extends NetworkModule
$ordering = '`commented`';
}
$o = conversation(DI::app(), $items, 'network', $profile_uid, false, $ordering, local_user());
$o = DI::conversation()->create($items, 'network', $profile_uid, false, $ordering, local_user());
}
System::htmlUpdateExit($o);

View File

@ -115,7 +115,7 @@ class Profile extends BaseModule
$items = DBA::toArray($items_stmt);
$o .= conversation($a, $items, 'profile', $a->getProfileOwner(), false, 'received', $a->getProfileOwner());
$o .= DI::conversation()->create($items, 'profile', $a->getProfileOwner(), false, 'received', $a->getProfileOwner());
System::htmlUpdateExit($o);
}

View File

@ -105,7 +105,7 @@ class Post
// Only add will be displayed
if ($item['network'] === Protocol::MAIL && local_user() != $item['uid']) {
continue;
} elseif (!visible_activity($item)) {
} elseif (!DI::contentItem()->visibleActivity($item)) {
continue;
}
@ -279,7 +279,7 @@ class Post
foreach ($response_verbs as $value => $verb) {
$responses[$verb] = [
'self' => $conv_responses[$verb][$item['uri-id']]['self'] ?? 0,
'output' => !empty($conv_responses[$verb][$item['uri-id']]) ? format_activity($conv_responses[$verb][$item['uri-id']]['links'], $verb, $item['uri-id']) : '',
'output' => !empty($conv_responses[$verb][$item['uri-id']]) ? DI::conversation()->formatActivity($conv_responses[$verb][$item['uri-id']]['links'], $verb, $item['uri-id']) : '',
];
}
@ -363,7 +363,7 @@ class Post
$shiny = 'shiny';
}
localize_item($item);
DI::contentItem()->localize($item);
$body_html = Item::prepareBody($item, true);
@ -459,7 +459,7 @@ class Post
'vwall' => DI::l10n()->t('via Wall-To-Wall:'),
'profile_url' => $profile_link,
'name' => $profile_name,
'item_photo_menu_html' => item_photo_menu($item, $formSecurityToken),
'item_photo_menu_html' => DI::contentItem()->photoMenu($item, $formSecurityToken),
'thumb' => DI::baseUrl()->remove(Contact::getAvatarUrlForUrl($item['author-link'], $item['uid'], Proxy::SIZE_THUMB)),
'osparkle' => $osparkle,
'sparkle' => $sparkle,

File diff suppressed because it is too large Load Diff