<?php
/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
+ * @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* @return array importer
* @throws \Exception
*/
- public static function getImporter($cid, $uid = 0)
+ public static function getImporter(int $cid, int $uid = 0): array
{
$condition = ['id' => $cid, 'blocked' => false, 'pending' => false];
$contact = DBA::selectFirst('contact', [], $condition);
* @throws \ImagickException
* @todo Find proper type-hints
*/
- public static function entries($items, $owner)
+ public static function entries(array $items, array $owner): string
{
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
- public static function itemFeed(int $uri_id, int $uid, bool $conversation = false)
+ public static function itemFeed(int $uri_id, int $uid, bool $conversation = false): string
{
if ($conversation) {
$condition = ['parent-uri-id' => $uri_id];
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Find proper type-hints
*/
- public static function mail(array $mail, array $owner)
+ public static function mail(array $mail, array $owner): string
{
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Find proper type-hints
*/
- public static function fsuggest($item, $owner)
+ public static function fsuggest(array $item, array $owner): string
{
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Find proper type-hints
*/
- public static function relocate($owner, $uid)
+ public static function relocate(array $owner, int $uid): string
{
/* get site pubkey. this could be a new installation with no site keys*/
*
* @return object XML root object
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
- * @todo Find proper type-hints
+ * @todo Find proper type-hint for returned type
*/
- private static function addHeader(DOMDocument $doc, $owner, $authorelement, $alternatelink = "", $public = false)
+ private static function addHeader(DOMDocument $doc, array $owner, string $authorelement, string $alternatelink = '', bool $public = false)
{
if ($alternatelink == "") {
return $root;
}
+ /**
+ * Determine the next birthday, but only if the birthday is published
+ * in the default profile. We _could_ also look for a private profile that the
+ * recipient can see, but somebody could get mad at us if they start getting
+ * public birthday greetings when they haven't made this info public.
+ *
+ * Assuming we are able to publish this info, we are then going to convert
+ * the start time from the owner's timezone to UTC.
+ *
+ * This will potentially solve the problem found with some social networks
+ * where birthdays are converted to the viewer's timezone and salutations from
+ * elsewhere in the world show up on the wrong day. We will convert it to the
+ * viewer's timezone also, but first we are going to convert it from the birthday
+ * person's timezone to GMT - so the viewer may find the birthday starting at
+ * 6:00PM the day before, but that will correspond to midnight to the birthday person.
+ *
+ * @param int $uid User id
+ * @param string $tz Time zone string, like UTC
+ * @return string Formatted birthday string
+ */
+ private static function determineNextBirthday(int $uid, string $tz): string
+ {
+ $birthday = '';
+
+ if (!strlen($tz)) {
+ $tz = 'UTC';
+ }
+
+ $profile = DBA::selectFirst('profile', ['dob'], ['uid' => $uid]);
+ if (DBA::isResult($profile)) {
+ $tmp_dob = substr($profile['dob'], 5);
+ if (intval($tmp_dob)) {
+ $y = DateTimeFormat::timezoneNow($tz, 'Y');
+ $bd = $y . '-' . $tmp_dob . ' 00:00';
+ $t_dob = strtotime($bd);
+ $now = strtotime(DateTimeFormat::timezoneNow($tz));
+ if ($t_dob < $now) {
+ $bd = $y + 1 . '-' . $tmp_dob . ' 00:00';
+ }
+ $birthday = DateTimeFormat::convert($bd, 'UTC', $tz, DateTimeFormat::ATOM);
+ }
+ }
+
+ return $birthday;
+ }
+
/**
* Adds the author element in the header for the DFRN protocol
*
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Find proper type-hints
*/
- private static function addAuthor(DOMDocument $doc, array $owner, $authorelement, $public)
+ private static function addAuthor(DOMDocument $doc, array $owner, string $authorelement, bool $public)
{
// Should the profile be "unsearchable" in the net? Then add the "hide" element
$hide = DBA::exists('profile', ['uid' => $owner['uid'], 'net-publish' => false]);
return $author;
}
- $birthday = feed_birthday($owner['uid'], $owner['timezone']);
+ $birthday = self::determineNextBirthday($owner['uid'], $owner['timezone']);
if ($birthday) {
XML::addElement($doc, $author, "dfrn:birthday", $birthday);
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Find proper type-hints
*/
- private static function addEntryAuthor(DOMDocument $doc, $element, $contact_url, $item)
+ private static function addEntryAuthor(DOMDocument $doc, string $element, string $contact_url, array $item)
{
$author = $doc->createElement($element);
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Find proper type-hints
*/
- private static function createActivity(DOMDocument $doc, $element, $activity, $uriid)
+ private static function createActivity(DOMDocument $doc, string $element, string $activity, int $uriid)
{
if ($activity) {
$entry = $doc->createElement($element);
* @return void XML attachment object
* @todo Find proper type-hints
*/
- private static function getAttachment($doc, $root, $item)
+ private static function getAttachment($doc, $root, array $item)
{
foreach (Post\Media::getByURIId($item['uri-id'], [Post\Media::DOCUMENT, Post\Media::TORRENT, Post\Media::UNKNOWN]) as $attachment) {
$attributes = ['rel' => 'enclosure',
* @throws \ImagickException
* @todo Find proper type-hints
*/
- private static function entry(DOMDocument $doc, $type, array $item, array $owner, $comment = false, $cid = 0, $single = false)
+ private static function entry(DOMDocument $doc, string $type, array $item, array $owner, bool $comment = false, int $cid = 0, bool $single = false)
{
$mentioned = [];
foreach ($mentioned as $mention) {
$condition = ['uid' => $owner["uid"], 'nurl' => Strings::normaliseLink($mention)];
- $contact = DBA::selectFirst('contact', ['forum', 'prv'], $condition);
+ $contact = DBA::selectFirst('contact', ['contact-type'], $condition);
- if (DBA::isResult($contact) && ($contact["forum"] || $contact["prv"])) {
+ if (DBA::isResult($contact) && ($contact['contact-type'] == Contact::TYPE_COMMUNITY)) {
XML::addElement(
$doc,
$entry,
* @param array $owner Owner record
* @param array $contact Contact record of the receiver
* @param string $atom Content that will be transmitted
- *
* @param bool $public_batch
* @return int Deliver status. Negative values mean an error.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
- public static function transmit($owner, $contact, $atom, $public_batch = false)
+ public static function transmit(array $owner, array $contact, string $atom, bool $public_batch = false)
{
if (!$public_batch) {
if (empty($contact['addr'])) {
* @throws \ImagickException
* @todo Find good type-hints for all parameter
*/
- private static function fetchauthor(\DOMXPath $xpath, \DOMNode $context, $importer, $element, $onlyfetch, $xml = "")
+ private static function fetchauthor(\DOMXPath $xpath, \DOMNode $context, array $importer, string $element, bool $onlyfetch, string $xml = ''): array
{
$author = [];
$author["name"] = XML::getFirstNodeValue($xpath, $element."/atom:name/text()", $context);
* @return string XML string
* @todo Find good type-hints for all parameter
*/
- private static function transformActivity($xpath, $activity, $element)
+ private static function transformActivity($xpath, $activity, string $element): string
{
if (!is_object($activity)) {
return "";
* @throws \Exception
* @todo Find good type-hints for all parameter
*/
- private static function processMail($xpath, $mail, $importer)
+ private static function processMail($xpath, $mail, array $importer)
{
Logger::notice("Processing mails");
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Find good type-hints for all parameter
*/
- private static function processSuggestion($xpath, $suggestion, $importer)
+ private static function processSuggestion($xpath, $suggestion, array $importer)
{
Logger::notice('Processing suggestions');
* @param integer $from_cid
* @return bool Was the adding successful?
*/
- private static function addSuggestion(int $uid, int $cid, int $from_cid, string $note = '')
+ private static function addSuggestion(int $uid, int $cid, int $from_cid, string $note = ''): bool
{
$owner = User::getOwnerDataById($uid);
$contact = Contact::getById($cid);
* @throws \ImagickException
* @todo Find good type-hints for all parameter
*/
- private static function processRelocation($xpath, $relocation, $importer)
+ private static function processRelocation($xpath, $relocation, array $importer): bool
{
Logger::notice("Processing relocations");
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo set proper type-hints (array?)
*/
- private static function updateContent($current, $item, $importer, $entrytype)
+ private static function updateContent(array $current, array $item, array $importer, int $entrytype)
{
$changed = false;
* @throws \Exception
* @todo set proper type-hints (array?)
*/
- private static function getEntryType($importer, $item)
+ private static function getEntryType(array $importer, array $item): int
{
if ($item["thr-parent"] != $item["uri"]) {
$community = false;
- if ($importer["page-flags"] == User::PAGE_FLAGS_COMMUNITY || $importer["page-flags"] == User::PAGE_FLAGS_PRVGROUP) {
+ if ($importer['account-type'] == User::ACCOUNT_TYPE_COMMUNITY) {
$sql_extra = "";
$community = true;
Logger::notice("possible community action");
// was the top-level post for this action written by somebody on this site?
// Specifically, the recipient?
- $parent = Post::selectFirst(['forum_mode', 'wall'],
+ $parent = Post::selectFirst(['wall'],
["`uri` = ? AND `uid` = ?" . $sql_extra, $item["thr-parent"], $importer["importer_uid"]]);
$is_a_remote_action = DBA::isResult($parent);
- /*
- * Does this have the characteristics of a community or private group action?
- * If it's an action to a wall post on a community/prvgroup page it's a
- * valid community action. Also forum_mode makes it valid for sure.
- * If neither, it's not.
- */
- if ($is_a_remote_action && $community && (!$parent["forum_mode"]) && (!$parent["wall"])) {
- $is_a_remote_action = false;
- Logger::notice("not a community action");
- }
-
if ($is_a_remote_action) {
return DFRN::REPLY_RC;
} else {
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo set proper type-hints (array?)
*/
- private static function processVerbs($entrytype, $importer, &$item, &$is_like)
+ private static function processVerbs(int $entrytype, array $importer, array &$item, bool &$is_like)
{
Logger::info("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype);
}
if ($activity->match($item["verb"], Activity::UNFRIEND)) {
Logger::notice("Lost sharer");
- Contact::removeSharer($importer, $contact, $item);
+ Contact::removeSharer($contact);
return false;
}
} else {
* @return void
* @todo set proper type-hints
*/
- private static function parseLinks($links, &$item)
+ private static function parseLinks($links, array &$item)
{
$rel = "";
$href = "";
* Checks if an incoming message is wanted
*
* @param array $item
+ * @param array $imporer
* @return boolean Is the message wanted?
*/
- private static function isSolicitedMessage(array $item)
+ private static function isSolicitedMessage(array $item, array $importer): bool
{
if (DBA::exists('contact', ["`nurl` = ? AND `uid` != ? AND `rel` IN (?, ?)",
Strings::normaliseLink($item["author-link"]), 0, Contact::FRIEND, Contact::SHARING])) {
- Logger::info('Author has got followers - accepted', ['uri' => $item['uri'], 'author' => $item["author-link"]]);
+ Logger::debug('Author has got followers - accepted', ['uri-id' => $item['uri-id'], 'guid' => $item['guid'], 'url' => $item['uri'], 'author' => $item["author-link"]]);
+ return true;
+ }
+
+ if ($importer['importer_uid'] != 0) {
+ Logger::debug('Message is directed to a user - accepted', ['uri-id' => $item['uri-id'], 'guid' => $item['guid'], 'url' => $item['uri'], 'importer' => $importer['importer_uid']]);
+ return true;
+ }
+
+ if ($item['uri'] != $item['thr-parent']) {
+ Logger::debug('Message is no parent - accepted', ['uri-id' => $item['uri-id'], 'guid' => $item['guid'], 'url' => $item['uri']]);
return true;
}
- $taglist = Tag::getByURIId($item['uri-id'], [Tag::HASHTAG]);
- $tags = array_column($taglist, 'name');
- return Relay::isSolicitedPost($tags, $item['body'], $item['author-id'], $item['uri'], Protocol::DFRN);
+ $tags = array_column(Tag::getByURIId($item['uri-id'], [Tag::HASHTAG]), 'name');
+ if (Relay::isSolicitedPost($tags, $item['body'], $item['author-id'], $item['uri'], Protocol::DFRN)) {
+ Logger::debug('Post is accepted because of the relay settings', ['uri-id' => $item['uri-id'], 'guid' => $item['guid'], 'url' => $item['uri'], 'author' => $item["author-link"]]);
+ return true;
+ } else {
+ return false;
+ }
}
/**
* @param object $entry entry elements
* @param array $importer Record of the importer user mixed with contact of the content
* @param string $xml xml
+ * @param int $protocol Protocol
* @return void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
* @todo Add type-hints
*/
- private static function processEntry($header, $xpath, $entry, $importer, $xml, $protocol)
+ private static function processEntry(array $header, $xpath, $entry, array $importer, string $xml, int $protocol)
{
Logger::notice("Processing entries");
}
// Check if the message is wanted
- if (($importer['importer_uid'] == 0) && ($item['uri'] == $item['thr-parent'])) {
- if (!self::isSolicitedMessage($item)) {
- DBA::delete('item-uri', ['uri' => $item['uri']]);
- return 403;
- }
+ if (!self::isSolicitedMessage($item, $importer)) {
+ DBA::delete('item-uri', ['uri' => $item['uri']]);
+ return 403;
}
// Get the type of the item (Top level post, reply or remote reply)
}
}
+ // Need to initialize variable, otherwise E_NOTICE will happen
+ $is_like = false;
+
if (!self::processVerbs($entrytype, $importer, $item, $is_like)) {
Logger::info("Exiting because 'processVerbs' told us so");
return;
* @throws \Exception
* @todo set proper type-hints
*/
- private static function processDeletion($xpath, $deletion, $importer)
+ private static function processDeletion($xpath, $deletion, array $importer)
{
Logger::notice("Processing deletions");
$uri = null;
* @return integer Import status
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
- * @todo set proper type-hints
*/
- public static function import($xml, $importer, $protocol, $direction)
+ public static function import(string $xml, array $importer, int $protocol, int $direction): int
{
if ($xml == "") {
return 400;
*
* @return string activity verb
*/
- private static function constructVerb(array $item)
+ private static function constructVerb(array $item): string
{
if ($item['verb']) {
return $item['verb'];
return Activity::POST;
}
- private static function tgroupCheck($uid, $item)
+ // @TODO Documentation missing
+ private static function tgroupCheck(int $uid, array $item): bool
{
$mention = false;
return false;
}
- $user = DBA::selectFirst('user', ['page-flags', 'nickname'], ['uid' => $uid]);
+ $user = DBA::selectFirst('user', ['account-type', 'nickname'], ['uid' => $uid]);
if (!DBA::isResult($user)) {
return false;
}
- $community_page = ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY);
- $prvgroup = ($user['page-flags'] == User::PAGE_FLAGS_PRVGROUP);
-
$link = Strings::normaliseLink(DI::baseUrl() . '/profile/' . $user['nickname']);
/*
return false;
}
- return $community_page || $prvgroup;
+ return ($user['account-type'] == User::ACCOUNT_TYPE_COMMUNITY);
}
/**
* item is assumed to be up-to-date. If the timestamps are equal it
* assumes the update has been seen before and should be ignored.
*
- * @param $existing
- * @param $update
+ * @param array $existing
+ * @param array $update
* @return bool
* @throws \Exception
*/
- private static function isEditedTimestampNewer($existing, $update)
+ private static function isEditedTimestampNewer(array $existing, array $update): bool
{
if (empty($existing['edited'])) {
return true;
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
- public static function isSupportedByContactUrl($url)
+ public static function isSupportedByContactUrl(string $url): bool
{
$probe = Probe::uri($url, Protocol::DFRN);
return $probe['network'] == Protocol::DFRN;