Compare commits

...

38 Commits

Author SHA1 Message Date
Michael e5f2b06afb
Some changes after code review
1 year ago
Michael fb8b37cd43
Reverted experimental change
1 year ago
Michael 1760d3b76d
Some more changed log levels
1 year ago
Michael 44e2cf7ef4
Loglevels are adjusted
1 year ago
Michael b30da1aa1c
Some more warnings and erors are fixed
1 year ago
Michael 8b7ad2cfca
Issue 11870: Weeks can now start at every day
1 year ago
Michael be6e3dba9d
Avoid warnings/fatal errors
1 year ago
Michael ac2f67958d
Issue 11853/11867: Fix reshare of public posts
1 year ago
Michael d6481247d2
Fix issue 11865
1 year ago
Michael eadccf3f8c
Warnings/Errors reduced - improved relay processing
1 year ago
Tobias Diekershoff c8fa33ff30
FR translation update
1 year ago
Hypolite Petovan 60ad11d9cf
Ensure Util\Profiler->rendertime is bool
1 year ago
Roland Häder 953aee86fb
Changes:
1 year ago
Roland Häder d107c4e342
Changed:
1 year ago
Michael bc8371824b
Some more protection against database errors
1 year ago
Michael a4f2185aee
Avoid some database errors
1 year ago
Michael 866346a39f
Diaspora: Don't check the author signature when author = parent author
1 year ago
Michael 66475baa28
The contact-id of a wall posting is always the owner contact
1 year ago
Michael c08918a774
Improved function to fetch the contact id
1 year ago
Michael 76c798411b
Improved contact-id detection
1 year ago
Michael cee0580341
Fetch the parent only - thread parents only on reshares
1 year ago
Michael ac9dcdaa70
Improved checks in "storeForUserByUriId" to reduce recursion depth
1 year ago
Michael 8370898cc7
Some more index / fatal erros fixed
1 year ago
Michael 28904ffe05
Cascade on author deletion
1 year ago
Michael 99ef72a3fa
This cache key doesn't exist anymore
1 year ago
Michael bb231524dd
Several performance improvements
1 year ago
Roland Häder d76e9b0602
Changed double-quotes to single
1 year ago
Roland Häder 672c2e2b0b
Fixes:
1 year ago
Roland Häder 8fc742d730
Fixes:
1 year ago
Roland Häder 0ecbd3b3c5
Changed:
1 year ago
Roland Häder d9d1e0b867
Changed:
1 year ago
Roland Häder dafcd45629
Changes:
1 year ago
Roland Häder 72ec943b26
Changes:
1 year ago
Roland Häder 787242d3ed
Changes:
1 year ago
Roland Häder 291a2565ab
Changes:
1 year ago
Michael 9a4714d09c
Don't delete the post when there is some undeleted post-user
1 year ago
Michael 49ac5a93c9
Return value added
1 year ago
Michael 9a1ceb7405
Improved performance when updating contacts
1 year ago

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 2022.09-dev (Giant Rhubarb)
-- DB_UPDATE_VERSION 1479
-- DB_UPDATE_VERSION 1481
-- ------------------------------------------
@ -141,12 +141,14 @@ CREATE TABLE IF NOT EXISTS `contact` (
`poll` varchar(255) COMMENT '',
`subscribe` varchar(255) COMMENT '',
`last-update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of the last try to update the contact info',
`next-update` datetime COMMENT 'Next connection request',
`success_update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of the last successful contact update',
`failure_update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date of the last failed update',
`failed` boolean COMMENT 'Connection failed',
`term-date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
`last-item` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'date of the last post',
`last-discovery` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'date of the last follower discovery',
`local-data` boolean COMMENT 'Is true when there are posts with this contact on the system',
`blocked` boolean NOT NULL DEFAULT '1' COMMENT 'Node-wide block status',
`block_reason` text COMMENT 'Node-wide block reason',
`readonly` boolean NOT NULL DEFAULT '0' COMMENT 'posts of the contact are readonly',
@ -213,12 +215,14 @@ CREATE TABLE IF NOT EXISTS `contact` (
INDEX `attag_uid` (`attag`(96),`uid`),
INDEX `network_uid_lastupdate` (`network`,`uid`,`last-update`),
INDEX `uid_network_self_lastupdate` (`uid`,`network`,`self`,`last-update`),
INDEX `next-update` (`next-update`),
INDEX `local-data-next-update` (`local-data`,`next-update`),
INDEX `uid_lastitem` (`uid`,`last-item`),
INDEX `baseurl` (`baseurl`(64)),
INDEX `uid_contact-type` (`uid`,`contact-type`),
INDEX `uid_self_contact-type` (`uid`,`self`,`contact-type`),
INDEX `self_network_uid` (`self`,`network`,`uid`),
INDEX `gsid` (`gsid`),
INDEX `gsid_uid_failed` (`gsid`,`uid`,`failed`),
INDEX `uri-id` (`uri-id`),
FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
@ -916,6 +920,7 @@ CREATE TABLE IF NOT EXISTS `notification` (
INDEX `target-uri-id` (`target-uri-id`),
INDEX `parent-uri-id` (`parent-uri-id`),
INDEX `seen_uid` (`seen`,`uid`),
INDEX `uid_type_parent-uri-id_actor-id` (`uid`,`type`,`parent-uri-id`,`actor-id`),
FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (`vid`) REFERENCES `verb` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT,
FOREIGN KEY (`actor-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
@ -1149,9 +1154,12 @@ CREATE TABLE IF NOT EXISTS `post-category` (
CREATE TABLE IF NOT EXISTS `post-collection` (
`uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri',
`type` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '0 - Featured',
`author-id` int unsigned COMMENT 'Author of the featured post',
PRIMARY KEY(`uri-id`,`type`),
INDEX `type` (`type`),
FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
INDEX `author-id` (`author-id`),
FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (`author-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Collection of posts';
--
@ -1408,6 +1416,7 @@ CREATE TABLE IF NOT EXISTS `post-user` (
INDEX `author-id_uid` (`author-id`,`uid`),
INDEX `author-id_received` (`author-id`,`received`),
INDEX `parent-uri-id_uid` (`parent-uri-id`,`uid`),
INDEX `uid_wall_received` (`uid`,`wall`,`received`),
INDEX `uid_contactid` (`uid`,`contact-id`),
INDEX `uid_unseen_contactid` (`uid`,`unseen`,`contact-id`),
INDEX `uid_unseen` (`uid`,`unseen`),
@ -2419,7 +2428,7 @@ DROP VIEW IF EXISTS `collection-view`;
CREATE VIEW `collection-view` AS SELECT
`post-collection`.`uri-id` AS `uri-id`,
`post-collection`.`type` AS `type`,
`post`.`author-id` AS `cid`,
`post-collection`.`author-id` AS `cid`,
`post`.`received` AS `received`,
`post`.`created` AS `created`,
`post-thread`.`commented` AS `commented`,
@ -2427,7 +2436,7 @@ CREATE VIEW `collection-view` AS SELECT
`post`.`visible` AS `visible`,
`post`.`deleted` AS `deleted`,
`post`.`thr-parent-id` AS `thr-parent-id`,
`post`.`author-id` AS `author-id`,
`post-collection`.`author-id` AS `author-id`,
`post`.`gravity` AS `gravity`
FROM `post-collection`
INNER JOIN `post` ON `post-collection`.`uri-id` = `post`.`uri-id`

@ -34,12 +34,14 @@ Fields
| poll | | varchar(255) | YES | | NULL | |
| subscribe | | varchar(255) | YES | | NULL | |
| last-update | Date of the last try to update the contact info | datetime | NO | | 0001-01-01 00:00:00 | |
| next-update | Next connection request | datetime | YES | | NULL | |
| success_update | Date of the last successful contact update | datetime | NO | | 0001-01-01 00:00:00 | |
| failure_update | Date of the last failed update | datetime | NO | | 0001-01-01 00:00:00 | |
| failed | Connection failed | boolean | YES | | NULL | |
| term-date | | datetime | NO | | 0001-01-01 00:00:00 | |
| last-item | date of the last post | datetime | NO | | 0001-01-01 00:00:00 | |
| last-discovery | date of the last follower discovery | datetime | NO | | 0001-01-01 00:00:00 | |
| local-data | Is true when there are posts with this contact on the system | boolean | YES | | NULL | |
| blocked | Node-wide block status | boolean | NO | | 1 | |
| block_reason | Node-wide block reason | text | YES | | NULL | |
| readonly | posts of the contact are readonly | boolean | NO | | 0 | |
@ -112,12 +114,14 @@ Indexes
| attag_uid | attag(96), uid |
| network_uid_lastupdate | network, uid, last-update |
| uid_network_self_lastupdate | uid, network, self, last-update |
| next-update | next-update |
| local-data-next-update | local-data, next-update |
| uid_lastitem | uid, last-item |
| baseurl | baseurl(64) |
| uid_contact-type | uid, contact-type |
| uid_self_contact-type | uid, self, contact-type |
| self_network_uid | self, network, uid |
| gsid | gsid |
| gsid_uid_failed | gsid, uid, failed |
| uri-id | uri-id |
Foreign Keys

@ -31,6 +31,7 @@ Indexes
| target-uri-id | target-uri-id |
| parent-uri-id | parent-uri-id |
| seen_uid | seen, uid |
| uid_type_parent-uri-id_actor-id | uid, type, parent-uri-id, actor-id |
Foreign Keys
------------

@ -6,18 +6,20 @@ Collection of posts
Fields
------
| Field | Description | Type | Null | Key | Default | Extra |
| ------ | --------------------------------------------------------- | ---------------- | ---- | --- | ------- | ----- |
| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | |
| type | 0 - Featured | tinyint unsigned | NO | PRI | 0 | |
| Field | Description | Type | Null | Key | Default | Extra |
| --------- | --------------------------------------------------------- | ---------------- | ---- | --- | ------- | ----- |
| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | |
| type | 0 - Featured | tinyint unsigned | NO | PRI | 0 | |
| author-id | Author of the featured post | int unsigned | YES | | NULL | |
Indexes
------------
| Name | Fields |
| ------- | ------------ |
| PRIMARY | uri-id, type |
| type | type |
| Name | Fields |
| --------- | ------------ |
| PRIMARY | uri-id, type |
| type | type |
| author-id | author-id |
Foreign Keys
------------
@ -25,5 +27,6 @@ Foreign Keys
| Field | Target Table | Target Field |
|-------|--------------|--------------|
| uri-id | [item-uri](help/database/db_item-uri) | id |
| author-id | [contact](help/database/db_contact) | id |
Return to [database documentation](help/database)

@ -60,6 +60,7 @@ Indexes
| author-id_uid | author-id, uid |
| author-id_received | author-id, received |
| parent-uri-id_uid | parent-uri-id, uid |
| uid_wall_received | uid, wall, received |
| uid_contactid | uid, contact-id |
| uid_unseen_contactid | uid, unseen, contact-id |
| uid_unseen | uid, unseen |

@ -102,7 +102,7 @@ function display_init(App $a)
}
if (!empty($_SERVER['HTTP_ACCEPT']) && strstr($_SERVER['HTTP_ACCEPT'], 'application/atom+xml')) {
Logger::info('Directly serving XML for uri-id '.$item['uri-id']);
Logger::debug('Directly serving XML', ['uri-id' => $item['uri-id']]);
displayShowFeed($item['uri-id'], $item['uid'], false);
}

@ -89,7 +89,7 @@ function item_post(App $a) {
*/
if (!$preview && !empty($_REQUEST['post_id_random'])) {
if (!empty($_SESSION['post-random']) && $_SESSION['post-random'] == $_REQUEST['post_id_random']) {
Logger::info('item post: duplicate post');
Logger::warning('duplicate post');
item_post_return(DI::baseUrl(), $api_source, $return_path);
} else {
$_SESSION['post-random'] = $_REQUEST['post_id_random'];
@ -177,7 +177,7 @@ function item_post(App $a) {
// Now check that valid personal details have been provided
if (!Security::canWriteToUserWall($profile_uid) && !$allow_comment) {
Logger::notice('Permission denied.', ['local' => local_user(), 'profile_uid' => $profile_uid, 'toplevel_item_id' => $toplevel_item_id, 'network' => $toplevel_item['network']]);
Logger::warning('Permission denied.', ['local' => local_user(), 'profile_uid' => $profile_uid, 'toplevel_item_id' => $toplevel_item_id, 'network' => $toplevel_item['network']]);
notice(DI::l10n()->t('Permission denied.'));
if ($return_path) {
DI::baseUrl()->redirect($return_path);
@ -755,7 +755,7 @@ function item_post(App $a) {
}
}
Logger::info('post_complete');
Logger::debug('post_complete');
if ($api_source) {
return $post_id;
@ -780,7 +780,7 @@ function item_post_return($baseurl, $api_source, $return_path)
$json['reload'] = $baseurl . '/' . $_REQUEST['jsreload'];
}
Logger::info('post_json', ['json' => $json]);
Logger::debug('post_json', ['json' => $json]);
System::jsonExit($json);
}
@ -866,7 +866,7 @@ function drop_item(int $id, string $return = '')
item_redirect_after_action($item, $return);
} else {
Logger::notice('Permission denied.', ['local' => local_user(), 'uid' => $item['uid'], 'cid' => $contact_id]);
Logger::warning('Permission denied.', ['local' => local_user(), 'uid' => $item['uid'], 'cid' => $contact_id]);
notice(DI::l10n()->t('Permission denied.'));
DI::baseUrl()->redirect('display/' . $item['guid']);
//NOTREACHED

@ -304,7 +304,7 @@ function photos_post(App $a)
}
if (!empty($_POST['rotate']) && (intval($_POST['rotate']) == 1 || intval($_POST['rotate']) == 2)) {
Logger::notice('rotate');
Logger::debug('rotate');
$photo = Photo::getPhotoForUser($page_owner_uid, $resource_id);
@ -580,7 +580,7 @@ function photos_post(App $a)
$album = trim($_REQUEST['album'] ?? '');
$newalbum = trim($_REQUEST['newalbum'] ?? '');
Logger::info('album= ' . $album . ' newalbum= ' . $newalbum);
Logger::debug('album= ' . $album . ' newalbum= ' . $newalbum);
if (!strlen($album)) {
if (strlen($newalbum)) {
@ -678,14 +678,14 @@ function photos_post(App $a)
return;
}
Logger::info('loading the contents of ' . $src);
Logger::debug('loading contents', ['src' => $src]);
$imagedata = @file_get_contents($src);
$image = new Image($imagedata, $type);
if (!$image->isValid()) {
Logger::info('unable to process image');
Logger::notice('unable to process image');
notice(DI::l10n()->t('Unable to process image.'));
@unlink($src);
$foo = 0;
@ -711,7 +711,7 @@ function photos_post(App $a)
$r = Photo::store($image, $page_owner_uid, $visitor, $resource_id, $filename, $album, 0 , Photo::DEFAULT, $str_contact_allow, $str_group_allow, $str_contact_deny, $str_group_deny);
if (!$r) {
Logger::info('image store failed');
Logger::warning('image store failed');
notice(DI::l10n()->t('Image upload failed.'));
return;
}

@ -109,7 +109,7 @@ function settings_post(App $a)
'pubmail' => $mail_pubmail
], ['uid' => local_user()]);
Logger::notice('updating mailaccount', ['response' => $r]);
Logger::debug('updating mailaccount', ['response' => $r]);
$mailacct = DBA::selectFirst('mailacct', [], ['uid' => local_user()]);
if (DBA::isResult($mailacct)) {
$mb = Email::constructMailboxName($mailacct);

@ -51,7 +51,7 @@ function tagger_content(App $a) {
$item_id = ((DI::args()->getArgc() > 1) ? trim(DI::args()->getArgv()[1]) : 0);
Logger::notice('tagger: tag ' . $term . ' item ' . $item_id);
Logger::info('tagger: tag', ['term' => $term, 'item' => $item_id]);
$item = Post::selectFirst([], ['id' => $item_id]);
@ -69,7 +69,7 @@ function tagger_content(App $a) {
$contact = Contact::selectFirst([], ['self' => true, 'uid' => local_user()]);
if (!DBA::isResult($contact)) {
Logger::notice('tagger: no contact_id');
Logger::warning('Self contact not found.', ['uid' => local_user()]);
return;
}

@ -46,7 +46,7 @@ class MoveToAvatarCache extends \Asika\SimpleConsole\Console
/**
* @var $baseurl Friendica\App\BaseURL
*/
private $baseurl;
private $baseUrl;
/**
* @var L10n
@ -75,12 +75,12 @@ HELP;
return $help;
}
public function __construct(\Friendica\Database\Database $dba, BaseURL $baseurl, L10n $l10n, IManageConfigValues $config, array $argv = null)
public function __construct(\Friendica\Database\Database $dba, BaseURL $baseUrl, L10n $l10n, IManageConfigValues $config, array $argv = null)
{
parent::__construct($argv);
$this->dba = $dba;
$this->baseurl = $baseurl;
$this->baseUrl = $baseUrl;
$this->l10n = $l10n;
$this->config = $config;
}
@ -94,7 +94,7 @@ HELP;
$fields = ['id', 'avatar', 'photo', 'thumb', 'micro', 'uri-id', 'url', 'avatar', 'network'];
$condition = ["NOT `self` AND `avatar` != ? AND `photo` LIKE ? AND `uid` = ? AND `uri-id` != ? AND NOT `uri-id` IS NULL AND NOT `network` IN (?, ?)",
'', $this->baseurl->get() . '/photo/%', 0, 0, Protocol::MAIL, Protocol::FEED];
'', $this->baseUrl->get() . '/photo/%', 0, 0, Protocol::MAIL, Protocol::FEED];
$count = 0;
$total = $this->dba->count('contact', $condition);

@ -161,15 +161,15 @@ class Avatar
$dirpath .= $part . '/';
if (!file_exists($dirpath)) {
if (!mkdir($dirpath, $dir_perm)) {
if (!@mkdir($dirpath, $dir_perm)) {
Logger::warning('Directory could not be created', ['directory' => $dirpath]);
}
} elseif ((($old_perm = fileperms($dirpath) & 0777) != $dir_perm) && !chmod($dirpath, $dir_perm)) {
Logger::notice('Directory permissions could not be changed', ['directory' => $dirpath, 'old' => $old_perm, 'new' => $dir_perm]);
Logger::warning('Directory permissions could not be changed', ['directory' => $dirpath, 'old' => $old_perm, 'new' => $dir_perm]);
}
if ((($old_group = filegroup($dirpath)) != $group) && !chgrp($dirpath, $group)) {
Logger::notice('Directory group could not be changed', ['directory' => $dirpath, 'old' => $old_group, 'new' => $group]);
Logger::warning('Directory group could not be changed', ['directory' => $dirpath, 'old' => $old_group, 'new' => $group]);
}
}
@ -181,11 +181,11 @@ class Avatar
$old_group = filegroup($filepath);
if (($old_perm != $file_perm) && !chmod($filepath, $file_perm)) {
Logger::notice('File permissions could not be changed', ['file' => $filepath, 'old' => $old_perm, 'new' => $file_perm]);
Logger::warning('File permissions could not be changed', ['file' => $filepath, 'old' => $old_perm, 'new' => $file_perm]);
}
if (($old_group != $group) && !chgrp($filepath, $group)) {
Logger::notice('File group could not be changed', ['file' => $filepath, 'old' => $old_group, 'new' => $group]);
Logger::warning('File group could not be changed', ['file' => $filepath, 'old' => $old_group, 'new' => $group]);
}
DI::profiler()->stopRecording();

@ -42,7 +42,7 @@ class PageInfo
*/
public static function searchAndAppendToBody(string $body, bool $searchNakedUrls = false, bool $no_photos = false)
{
Logger::info('add_page_info_to_body: fetch page info for body', ['body' => $body]);
Logger::debug('add_page_info_to_body: fetch page info for body', ['body' => $body]);
$url = self::getRelevantUrlFromBody($body, $searchNakedUrls);
if (!$url) {
@ -208,7 +208,7 @@ class PageInfo
}
}
Logger::info('fetch page info for URL', ['url' => $url, 'data' => $data]);
Logger::debug('fetch page info for URL', ['url' => $url, 'data' => $data]);
return $data;
}

@ -58,7 +58,7 @@ class Pager
$this->setQueryString($queryString);
$this->setItemsPerPage($itemsPerPage);
$this->setPage(($_GET['page'] ?? 0) ?: 1);
$this->setPage((int)($_GET['page'] ?? 0) ?: 1);
}
/**

@ -498,7 +498,7 @@ class BBCode
$c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism', $s, $matches, PREG_SET_ORDER);
if ($c) {
foreach ($matches as $mtch) {
Logger::info('scale_external_image', ['image' => $mtch[1]]);
Logger::debug('scale_external_image', ['image' => $mtch[1]]);
$hostname = str_replace('www.', '', substr(DI::baseUrl(), strpos(DI::baseUrl(), '://') + 3));
if (stristr($mtch[1], $hostname)) {
@ -526,14 +526,14 @@ class BBCode
$Image->scaleDown(640);
$new_width = $Image->getWidth();
$new_height = $Image->getHeight();
Logger::info('External images scaled', ['orig_width' => $orig_width, 'new_width' => $new_width, 'orig_height' => $orig_height, 'new_height' => $new_height, 'match' => $mtch[0]]);
Logger::debug('External images scaled', ['orig_width' => $orig_width, 'new_width' => $new_width, 'orig_height' => $orig_height, 'new_height' => $new_height, 'match' => $mtch[0]]);
$s = str_replace(
$mtch[0],
'[img=' . $new_width . 'x' . $new_height. ']' . $mtch[1] . '[/img]'
. "\n",
$s
);
Logger::info('New string', ['image' => $s]);
Logger::debug('New string', ['image' => $s]);
}
}
}
@ -583,7 +583,7 @@ class BBCode
if (($textlen + $img_start) > $maxlen) {
if ($textlen < $maxlen) {
Logger::info('the limit happens before an embedded image');
Logger::debug('the limit happens before an embedded image');
$new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen);
$textlen = $maxlen;
}
@ -597,7 +597,7 @@ class BBCode
if (($textlen + $img_end) > $maxlen) {
if ($textlen < $maxlen) {
Logger::info('the limit happens before the end of a non-embedded image');
Logger::debug('the limit happens before the end of a non-embedded image');
$new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen);
$textlen = $maxlen;
}
@ -620,11 +620,11 @@ class BBCode
if (($textlen + strlen($orig_body)) > $maxlen) {
if ($textlen < $maxlen) {
Logger::info('the limit happens after the end of the last image');
Logger::debug('the limit happens after the end of the last image');
$new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen);
}
} else {
Logger::info('the text size with embedded images extracted did not violate the limit');
Logger::debug('the text size with embedded images extracted did not violate the limit');
$new_body = $new_body . $orig_body;
}

@ -128,7 +128,7 @@ class Addon
{
$addon = Strings::sanitizeFilePathItem($addon);
Logger::notice("Addon {addon}: {action}", ['action' => 'uninstall', 'addon' => $addon]);
Logger::debug("Addon {addon}: {action}", ['action' => 'uninstall', 'addon' => $addon]);
DBA::delete('addon', ['name' => $addon]);
@include_once('addon/' . $addon . '/' . $addon . '.php');
@ -160,7 +160,7 @@ class Addon
return false;
}
Logger::notice("Addon {addon}: {action}", ['action' => 'install', 'addon' => $addon]);
Logger::debug("Addon {addon}: {action}", ['action' => 'install', 'addon' => $addon]);
$t = @filemtime($addon_file_path);
@include_once($addon_file_path);
if (function_exists($addon . '_install')) {
@ -200,7 +200,7 @@ class Addon
continue;
}
Logger::notice("Addon {addon}: {action}", ['action' => 'reload', 'addon' => $addon['name']]);
Logger::debug("Addon {addon}: {action}", ['action' => 'reload', 'addon' => $addon['name']]);
self::uninstall($addon['name']);
self::install($addon['name']);

@ -493,30 +493,30 @@ class System
*
* @return boolean the directory is usable
*/
public static function isDirectoryUsable($directory, $check_writable = true)
private static function isDirectoryUsable($directory, $check_writable = true)
{
if ($directory == '') {
Logger::info('Directory is empty. This shouldn\'t happen.');
Logger::warning('Directory is empty. This shouldn\'t happen.');
return false;
}
if (!file_exists($directory)) {
Logger::info('Path "' . $directory . '" does not exist for user ' . static::getUser());
Logger::warning('Path does not exist', ['directory' => $directory, 'user' => static::getUser()]);
return false;
}
if (is_file($directory)) {
Logger::info('Path "' . $directory . '" is a file for user ' . static::getUser());
Logger::warning('Path is a file', ['directory' => $directory, 'user' => static::getUser()]);
return false;
}
if (!is_dir($directory)) {
Logger::info('Path "' . $directory . '" is not a directory for user ' . static::getUser());
Logger::warning('Path is not a directory', ['directory' => $directory, 'user' => static::getUser()]);
return false;
}
if ($check_writable && !is_writable($directory)) {
Logger::info('Path "' . $directory . '" is not writable for user ' . static::getUser());
Logger::warning('Path is not writable', ['directory' => $directory, 'user' => static::getUser()]);
return false;
}
@ -550,7 +550,7 @@ class System
{
$temppath = DI::config()->get("system", "temppath");
if (($temppath != "") && System::isDirectoryUsable($temppath)) {
if (($temppath != "") && self::isDirectoryUsable($temppath)) {
// We have a temp path and it is usable
return BasePath::getRealPath($temppath);
}
@ -559,7 +559,7 @@ class System
$temppath = sys_get_temp_dir();
// Check if it is usable
if (($temppath != "") && System::isDirectoryUsable($temppath)) {
if (($temppath != "") && self::isDirectoryUsable($temppath)) {
// Always store the real path, not the path through symlinks
$temppath = BasePath::getRealPath($temppath);
@ -570,7 +570,7 @@ class System
mkdir($new_temppath);
}
if (System::isDirectoryUsable($new_temppath)) {
if (self::isDirectoryUsable($new_temppath)) {
// The new path is usable, we are happy
DI::config()->set("system", "temppath", $new_temppath);
return $new_temppath;
@ -593,7 +593,7 @@ class System
public static function getSpoolPath()
{
$spoolpath = DI::config()->get('system', 'spoolpath');
if (($spoolpath != "") && System::isDirectoryUsable($spoolpath)) {
if (($spoolpath != "") && self::isDirectoryUsable($spoolpath)) {
// We have a spool path and it is usable
return $spoolpath;
}
@ -608,7 +608,7 @@ class System
mkdir($spoolpath);
}
if (System::isDirectoryUsable($spoolpath)) {
if (self::isDirectoryUsable($spoolpath)) {
// The new path is usable, we are happy
DI::config()->set("system", "spoolpath", $spoolpath);
return $spoolpath;

@ -104,7 +104,7 @@ class Worker
foreach ($r as $entry) {
// The work will be done
if (!self::execute($entry)) {
Logger::notice('Process execution failed, quitting.');
Logger::warning('Process execution failed, quitting.', ['entry' => $entry]);
return;
}

@ -101,7 +101,7 @@ class Cron
// How long is the process already running?
$duration = (time() - strtotime($entry["executed"])) / 60;
if ($duration > $max_duration) {
Logger::notice('Worker process took too much time - killed', ['duration' => number_format($duration, 3), 'max' => $max_duration, 'id' => $entry["id"], 'pid' => $entry["pid"], 'command' => $command]);
Logger::warning('Worker process took too much time - killed', ['duration' => number_format($duration, 3), 'max' => $max_duration, 'id' => $entry["id"], 'pid' => $entry["pid"], 'command' => $command]);
posix_kill($entry["pid"], SIGTERM);
// We killed the stale process.

@ -68,7 +68,7 @@ class Database
protected $connection;
protected $driver = '';
protected $pdo_emulate_prepares = false;
private $error = false;
private $error = '';
private $errorno = 0;
private $affected_rows = 0;
protected $in_transaction = false;
@ -558,8 +558,8 @@ class Database
if (count($args) == 0) {
if (!$retval = $this->connection->query($this->replaceParameters($sql, $args))) {
$errorInfo = $this->connection->errorInfo();
$this->error = $errorInfo[2];
$this->errorno = (int) $errorInfo[1];
$this->error = (string)$errorInfo[2];
$this->errorno = (int)$errorInfo[1];
$retval = false;
$is_error = true;
break;
@ -571,8 +571,8 @@ class Database
/** @var $stmt mysqli_stmt|PDOStatement */
if (!$stmt = $this->connection->prepare($sql)) {
$errorInfo = $this->connection->errorInfo();
$this->error = $errorInfo[2];
$this->errorno = (int) $errorInfo[1];
$this->error = (string)$errorInfo[2];
$this->errorno = (int)$errorInfo[1];
$retval = false;
$is_error = true;
break;
@ -591,8 +591,8 @@ class Database
if (!$stmt->execute()) {
$errorInfo = $stmt->errorInfo();
$this->error = $errorInfo[2];
$this->errorno = (int) $errorInfo[1];
$this->error = (string)$errorInfo[2];
$this->errorno = (int)$errorInfo[1];
$retval = false;
$is_error = true;
} else {
@ -610,8 +610,8 @@ class Database
if (!$can_be_prepared || (count($args) == 0)) {
$retval = $this->connection->query($this->replaceParameters($sql, $args));
if ($this->connection->errno) {
$this->error = $this->connection->error;
$this->errorno = $this->connection->errno;
$this->error = (string)$this->connection->error;
$this->errorno = (int)$this->connection->errno;
$retval = false;
$is_error = true;
} else {
@ -627,8 +627,8 @@ class Database
$stmt = $this->connection->stmt_init();
if (!$stmt->prepare($sql)) {
$this->error = $stmt->error;
$this->errorno = $stmt->errno;
$this->error = (string)$stmt->error;
$this->errorno = (int)$stmt->errno;
$retval = false;
$is_error = true;
break;
@ -658,8 +658,8 @@ class Database
}
if (!$stmt->execute()) {
$this->error = $this->connection->error;
$this->errorno = $this->connection->errno;
$this->error = (string)$this->connection->error;
$this->errorno = (int)$this->connection->errno;
$retval = false;
$is_error = true;
} else {
@ -726,8 +726,8 @@ class Database
}
}
$this->error = $error;
$this->errorno = (int) $errorno;
$this->error = (string)$error;
$this->errorno = (int)$errorno;
}
$this->profiler->stopRecording();

@ -42,11 +42,16 @@ class Activities extends BaseFactory
}
/**
* Creates activities array from URI id, user id
*
* @param int $uriId Uri-ID of the item
* @return Array
* @param int $uid User id
* @param string $type Type of returned activities, can be 'json' or 'xml', default: json
*
* @return array Array of found activities
* @throws HTTPException\InternalServerErrorException
*/
public function createFromUriId(int $uriId, int $uid, $type = 'json'): array
public function createFromUriId(int $uriId, int $uid, string $type = 'json'): array
{
$activities = [
'like' => [],
@ -68,22 +73,29 @@ class Activities extends BaseFactory
case Activity::LIKE:
$activities['like'][] = $user;
break;
case Activity::DISLIKE:
$activities['dislike'][] = $user;
break;
case Activity::ATTEND:
$activities['attendyes'][] = $user;
break;
case Activity::ATTENDNO:
$activities['attendno'][] = $user;
break;
case Activity::ATTENDMAYBE:
$activities['attendmaybe'][] = $user;
break;
case Activity::ANNOUNCE:
$activities['announce'][] = $user;
break;
default:
$this->logger->warning('Unsupported verb in parent item:', ['parent_item' => $parent_item]);
break;
}
}
@ -94,7 +106,7 @@ class Activities extends BaseFactory
$xml_activities = [];
foreach ($activities as $k => $v) {
// change xml element from "like" to "friendica:like"
$xml_activities["friendica:".$k] = $v;
$xml_activities['friendica:' . $k] = $v;
// add user data into xml output
$k_user = 0;
foreach ($v as $user) {

@ -41,7 +41,6 @@ class Application extends BaseFactory
* @param int $id Application ID
*
* @return \Friendica\Object\Api\Mastodon\Application
*
* @throws UnprocessableEntityException
*/
public function createFromApplicationId(int $id): \Friendica\Object\Api\Mastodon\Application

@ -46,9 +46,12 @@ class Conversation extends BaseFactory
}
/**
* @param int $id Conversation id
*
* @return \Friendica\Object\Api\Mastodon\Conversation
* @throws ImagickException|HTTPException\InternalServerErrorException|HTTPException\NotFoundException
*/
public function CreateFromConvId(int $id): \Friendica\Object\Api\Mastodon\Conversation
public function createFromConvId(int $id): \Friendica\Object\Api\Mastodon\Conversation
{
$accounts = [];
$unread = false;

@ -33,6 +33,7 @@ class Emoji extends BaseFactory
/**
* @param array $smilies
*
* @return Emojis
*/
public function createCollectionFromSmilies(array $smilies): Emojis

@ -43,6 +43,7 @@ class Field extends BaseFactory
/**
* @param ProfileFields $profileFields
*
* @return Fields
* @throws HTTPException\InternalServerErrorException
*/

@ -45,6 +45,12 @@ class Notification extends BaseFactory
$this->mstdnStatusFactory = $mstdnStatusFactoryFactory;
}
/**
* @param Notifications\Entity\Notification $Notification
*
* @return MstdnNotification
* @throws UnexpectedNotificationTypeException
*/
public function createFromNotification(Notifications\Entity\Notification $Notification): MstdnNotification
{
$type = self::getType($Notification);

@ -31,8 +31,11 @@ class Poll extends BaseFactory
/**
* @param int $id Id the question
* @param int $uid Item user
*
* @return \Friendica\Object\Api\Mastodon\Poll
* @throws HTTPException\NotFoundException
*/
public function createFromId(int $id, $uid = 0): \Friendica\Object\Api\Mastodon\Poll
public function createFromId(int $id, int $uid = 0): \Friendica\Object\Api\Mastodon\Poll
{
$question = Post\Question::getById($id);
if (empty($question)) {

@ -31,6 +31,7 @@ class Relationship extends BaseFactory
/**
* @param int $contactId Contact ID (public or user contact)
* @param int $uid User ID
*
* @return RelationshipEntity
* @throws Exception
*/

@ -78,7 +78,7 @@ class Status extends BaseFactory
* @throws HTTPException\InternalServerErrorException
* @throws ImagickException|HTTPException\NotFoundException
*/
public function createFromUriId(int $uriId, $uid = 0): \Friendica\Object\Api\Mastodon\Status
public function createFromUriId(int $uriId, int $uid = 0): \Friendica\Object\Api\Mastodon\Status
{
$fields = ['uri-id', 'uid', 'author-id', 'author-uri-id', 'author-link', 'starred', 'app', 'title', 'body', 'raw-body', 'content-warning', 'question-id',
'created', 'network', 'thr-parent-id', 'parent-author-id', 'language', 'uri', 'plink', 'private', 'vid', 'gravity', 'featured', 'has-media'];

@ -41,6 +41,7 @@ class Tag extends BaseFactory
/**
* @param int $uriId Uri-ID of the item
*
* @return array
* @throws HTTPException\InternalServerErrorException
*/

@ -35,6 +35,7 @@ class Attachment extends BaseFactory
/**
* @param int $uriId Uri-ID of the attachments
*
* @return array
* @throws HTTPException\InternalServerErrorException
*/

@ -35,6 +35,8 @@ class Hashtag extends BaseFactory
/**
* @param int $uriId Uri-ID of the attachments
* @param string $text
*
* @return array
* @throws HTTPException\InternalServerErrorException
*/

@ -41,6 +41,8 @@ class Media extends BaseFactory
/**
* @param int $uriId Uri-ID of the attachments
* @param string $text
*
* @return array
* @throws HTTPException\InternalServerErrorException
*/

@ -47,11 +47,12 @@ class User extends BaseFactory
* @param int $uid Public contact (=0) or owner user id
* @param bool $skip_status
* @param bool $include_user_entities
*
* @return \Friendica\Object\Api\Twitter\User
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public function createFromContactId(int $contactId, int $uid = 0, bool $skip_status = true, bool $include_user_entities = true)
public function createFromContactId(int $contactId, int $uid = 0, bool $skip_status = true, bool $include_user_entities = true): \Friendica\Object\Api\Twitter\User
{
$cdata = Contact::getPublicAndUserContactID($contactId, $uid);
if (!empty($cdata)) {
@ -78,7 +79,14 @@ class User extends BaseFactory
return new \Friendica\Object\Api\Twitter\User($publicContact, $apcontact, $userContact, $status, $include_user_entities);
}
public function createFromUserId(int $uid, bool $skip_status = true, bool $include_user_entities = true)
/**
* @param int $uid Public contact (=0) or owner user id
* @param bool $skip_status
* @param bool $include_user_entities
*
* @return \Friendica\Object\Api\Twitter\User
*/
public function createFromUserId(int $uid, bool $skip_status = true, bool $include_user_entities = true): \Friendica\Object\Api\Twitter\User
{
return $this->createFromContactId(Contact::getPublicIdByUserId($uid), $uid, $skip_status, $include_user_entities);
}

@ -24,6 +24,7 @@ namespace Friendica\Model;
use Friendica\Content\Text\HTML;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
@ -352,17 +353,18 @@ class APContact
if (!empty($apcontact['outbox'])) {
if (!empty($local_owner)) {
$outbox = ActivityPub\Transmitter::getOutbox($local_owner);
$statuses_count = self::getStatusesCount($local_owner);
} else {
$outbox = ActivityPub::fetchContent($apcontact['outbox']);
$statuses_count = $outbox['totalItems'] ?? 0;
}
if (!empty($outbox['totalItems'])) {
if (!empty($statuses_count)) {
// Mastodon seriously allows for this condition?
// Jul 20 2021 - See https://chaos.social/@m11 for a negative posts count
if ($outbox['totalItems'] < 0) {
$outbox['totalItems'] = 0;
if ($statuses_count < 0) {
$statuses_count = 0;
}
$apcontact['statuses_count'] = $outbox['totalItems'];
$apcontact['statuses_count'] = $statuses_count;
}
}
@ -483,6 +485,30 @@ class APContact
return DBA::selectFirst('apcontact', [], ['url' => $apcontact['url']]) ?: [];
}
/**
* Fetch the number of statuses for the given owner
*
* @param array $owner
*
* @return integer
*/
private static function getStatusesCount(array $owner): int
{
$condition = [
'private' => [Item::PUBLIC, Item::UNLISTED],
'author-id' => Contact::getIdForURL($owner['url'], 0, false),
'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
'network' => Protocol::DFRN,
'parent-network' => Protocol::FEDERATED,
'deleted' => false,
'visible' => true
];
$count = Post::countPosts($condition);
return $count;
}
/**
* Mark the given AP Contact as "to archive"
*

@ -160,6 +160,7 @@ class Contact
$fields['created'] = DateTimeFormat::utcNow();
}
$fields = DI::dbaDefinition()->truncateFieldsForTable('contact', $fields);
DBA::insert('contact', $fields, $duplicate_mode);
$contact = DBA::selectFirst('contact', [], ['id' => DBA::lastInsertId()]);
if (!DBA::isResult($contact)) {
@ -191,6 +192,7 @@ class Contact
*/
public static function update(array $fields, array $condition, $old_fields = [])
{
$fields = DI::dbaDefinition()->truncateFieldsForTable('contact', $fields);
$ret = DBA::update('contact', $fields, $condition, $old_fields);
// Apply changes to the "user-contact" table on dedicated fields
@ -327,14 +329,15 @@ class Contact
/**
* Tests if the given contact is a follower
*
* @param int $cid Either public contact id or user's contact id
* @param int $uid User ID
* @param int $cid Either public contact id or user's contact id
* @param int $uid User ID
* @param bool $strict If "true" then contact mustn't be set to pending or readonly
*
* @return boolean is the contact id a follower?
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function isFollower(int $cid, int $uid): bool
public static function isFollower(int $cid, int $uid, bool $strict = false): bool
{
if (Contact\User::isBlocked($cid, $uid)) {
return false;
@ -346,20 +349,24 @@ class Contact
}
$condition = ['id' => $cdata['user'], 'rel' => [self::FOLLOWER, self::FRIEND]];
if ($strict) {
$condition = array_merge($condition, ['pending' => false, 'readonly' => false, 'blocked' => false]);
}
return DBA::exists('contact', $condition);
}
/**
* Tests if the given contact url is a follower
*
* @param string $url Contact URL
* @param int $uid User ID
* @param string $url Contact URL
* @param int $uid User ID
* @param bool $strict If "true" then contact mustn't be set to pending or readonly
*
* @return boolean is the contact id a follower?
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function isFollowerByURL(string $url, int $uid): bool
public static function isFollowerByURL(string $url, int $uid, bool $strict = false): bool
{
$cid = self::getIdForURL($url, $uid);
@ -367,20 +374,21 @@ class Contact
return false;
}
return self::isFollower($cid, $uid);
return self::isFollower($cid, $uid, $strict);
}
/**
* Tests if the given user shares with the given contact
*
* @param int $cid Either public contact id or user's contact id
* @param int $uid User ID
* @param int $cid Either public contact id or user's contact id
* @param int $uid User ID
* @param bool $strict If "true" then contact mustn't be set to pending or readonly
*
* @return boolean is the contact sharing with given user?
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function isSharing(int $cid, int $uid): bool
public static function isSharing(int $cid, int $uid, bool $strict = false): bool
{
if (Contact\User::isBlocked($cid, $uid)) {
return false;
@ -392,20 +400,24 @@ class Contact
}
$condition = ['id' => $cdata['user'], 'rel' => [self::SHARING, self::FRIEND]];
if ($strict) {
$condition = array_merge($condition, ['pending' => false, 'readonly' => false, 'blocked' => false]);
}
return DBA::exists('contact', $condition);
}
/**
* Tests if the given user follow the given contact url
*
* @param string $url Contact URL
* @param int $uid User ID
* @param string $url Contact URL
* @param int $uid User ID
* @param bool $strict If "true" then contact mustn't be set to pending or readonly
*
* @return boolean is the contact url being followed?
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function isSharingByURL(string $url, int $uid): bool
public static function isSharingByURL(string $url, int $uid, bool $strict = false): bool
{
$cid = self::getIdForURL($url, $uid);
@ -413,7 +425,7 @@ class Contact
return false;
}
return self::isSharing($cid, $uid);
return self::isSharing($cid, $uid, $strict);
}
/**
@ -1287,7 +1299,7 @@ class Contact
}
if (!$contact_id) {
Logger::info('Contact was not inserted', ['url' => $url, 'uid' => $uid]);
Logger::warning('Contact was not inserted', ['url' => $url, 'uid' => $uid]);
return 0;
}
} else {
@ -2339,6 +2351,47 @@ class Contact
return self::updateFromProbeArray($id, $ret);
}
/**
* Checks if the given contact has got local data