diff --git a/.phpstan.neon b/.phpstan.neon index 173693b743..0eef6d2240 100644 --- a/.phpstan.neon +++ b/.phpstan.neon @@ -3,7 +3,7 @@ # SPDX-License-Identifier: CC0-1.0 parameters: - level: 0 + level: 1 paths: - addon/ @@ -16,5 +16,9 @@ parameters: scanDirectories: - mod + - static - vendor - view + + dynamicConstantNames: + - DB_UPDATE_VERSION diff --git a/doc/AddonStorageBackend.md b/doc/AddonStorageBackend.md index c3a6d1639c..5053b641cb 100644 --- a/doc/AddonStorageBackend.md +++ b/doc/AddonStorageBackend.md @@ -126,14 +126,14 @@ Override the two necessary instances: ```php use Friendica\Core\Storage\Capability\ICanWriteToStorage; -abstract class StorageTest +abstract class StorageTest { // returns an instance of your newly created storage class abstract protected function getInstance(); // Assertion for the option array you return for your new StorageClass abstract protected function assertOption(ICanWriteToStorage $storage); -} +} ``` ## Exception handling @@ -158,7 +158,7 @@ Example: ```php use Friendica\Core\Storage\Capability\ICanWriteToStorage; -class ExampleStorage implements ICanWriteToStorage +class ExampleStorage implements ICanWriteToStorage { public function get(string $reference) : string { @@ -168,7 +168,7 @@ class ExampleStorage implements ICanWriteToStorage throw new \Friendica\Core\Storage\Exception\StorageException(sprintf('The Example Storage throws an exception for reference %s', $reference), 500, $exception); } } -} +} ``` ## Example @@ -200,11 +200,11 @@ class SampleStorageBackend implements ICanWriteToStorage /** * SampleStorageBackend constructor. - * + * * You can add here every dynamic class as dependency you like and add them to a private field - * Friendica automatically creates these classes and passes them as argument to the constructor + * Friendica automatically creates these classes and passes them as argument to the constructor */ - public function __construct(string $filename) + public function __construct(string $filename) { $this->filename = $filename; } @@ -215,7 +215,7 @@ class SampleStorageBackend implements ICanWriteToStorage // a config key return file_get_contents($this->filename); } - + public function put(string $data, string $reference = '') { if ($reference === '') { @@ -224,13 +224,13 @@ class SampleStorageBackend implements ICanWriteToStorage // we don't save $data ! return $reference; } - + public function delete(string $reference) { // we pretend to delete the data return true; } - + public function __toString() { return self::NAME; @@ -261,11 +261,11 @@ class SampleStorageBackendConfig implements ICanConfigureStorage /** * SampleStorageBackendConfig constructor. - * + * * You can add here every dynamic class as dependency you like and add them to a private field - * Friendica automatically creates these classes and passes them as argument to the constructor + * Friendica automatically creates these classes and passes them as argument to the constructor */ - public function __construct(IManageConfigValues $config, L10n $l10n) + public function __construct(IManageConfigValues $config, L10n $l10n) { $this->config = $config; $this->l10n = $l10n; @@ -289,12 +289,12 @@ class SampleStorageBackendConfig implements ICanConfigureStorage ], ]; } - + public function saveOptions(array $data) { // the keys in $data are the same keys we defined in getOptions() $newfilename = trim($data['filename']); - + // this function should always validate the data. // in this example we check if file exists if (!file_exists($newfilename)) { @@ -302,9 +302,9 @@ class SampleStorageBackendConfig implements ICanConfigureStorage // ['optionname' => 'error message'] return ['filename' => 'The file doesn\'t exists']; } - + $this->config->set('storage', 'samplestorage', $newfilename); - + // no errors, return empty array return []; } @@ -341,13 +341,13 @@ function samplestorage_storage_uninstall() DI::storageManager()->unregister(SampleStorageBackend::class); } -function samplestorage_storage_instance(App $a, array &$data) +function samplestorage_storage_instance(AppHelper $appHelper, array &$data) { $config = new SampleStorageBackendConfig(DI::l10n(), DI::config()); $data['storage'] = new SampleStorageBackendConfig($config->getFileName()); } -function samplestorage_storage_config(App $a, array &$data) +function samplestorage_storage_config(AppHelper $appHelper, array &$data) { $data['storage_config'] = new SampleStorageBackendConfig(DI::l10n(), DI::config()); } @@ -360,7 +360,7 @@ function samplestorage_storage_config(App $a, array &$data) use Friendica\Core\Storage\Capability\ICanWriteToStorage; use Friendica\Test\src\Core\Storage\StorageTest; -class SampleStorageTest extends StorageTest +class SampleStorageTest extends StorageTest { // returns an instance of your newly created storage class protected function getInstance() @@ -382,5 +382,5 @@ class SampleStorageTest extends StorageTest ], ], $storage->getOptions()); } -} +} ``` diff --git a/doc/autoloader.md b/doc/autoloader.md index 954c28813c..5bc0bfe9b3 100644 --- a/doc/autoloader.md +++ b/doc/autoloader.md @@ -46,9 +46,9 @@ The code will be something like: // mod/network.php getAll(); diff --git a/src/App.php b/src/App.php index 48574662fd..58c617c118 100644 --- a/src/App.php +++ b/src/App.php @@ -447,6 +447,7 @@ class App implements AppHelper $requeststring = ($server['REQUEST_METHOD'] ?? '') . ' ' . ($server['REQUEST_URI'] ?? '') . ' ' . ($server['SERVER_PROTOCOL'] ?? ''); $this->logger->debug('Request received', ['address' => $server['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $server['HTTP_REFERER'] ?? '', 'user-agent' => $server['HTTP_USER_AGENT'] ?? '']); $request_start = microtime(true); + $request = $_REQUEST; $this->profiler->set($start_time, 'start'); $this->profiler->set(microtime(true), 'classinit'); @@ -581,7 +582,7 @@ class App implements AppHelper // Processes data from GET requests $httpinput = $httpInput->process(); - $input = array_merge($httpinput['variables'], $httpinput['files'], $request ?? $_REQUEST); + $input = array_merge($httpinput['variables'], $httpinput['files'], $request); // Let the module run its internal process (init, get, post, ...) $timestamp = microtime(true); diff --git a/src/App/BaseURL.php b/src/App/BaseURL.php index 953b13c791..83416866f0 100644 --- a/src/App/BaseURL.php +++ b/src/App/BaseURL.php @@ -103,6 +103,8 @@ class BaseURL extends Uri implements UriInterface * @throws HTTPException\TemporaryRedirectException * * @throws HTTPException\InternalServerErrorException In Case the given URL is not relative to the Friendica node + * + * @return never */ public function redirect(string $toUrl = '', bool $ssl = false) { diff --git a/src/App/Router.php b/src/App/Router.php index 7e11ce727a..31162ec1b6 100644 --- a/src/App/Router.php +++ b/src/App/Router.php @@ -334,17 +334,17 @@ class Router $stamp = microtime(true); - try { - /** @var ICanHandleRequests $module */ - return $this->dice->create($moduleClass, $this->parameters); - } finally { - if ($this->dice_profiler_threshold > 0) { - $dur = floatval(microtime(true) - $stamp); - if ($dur >= $this->dice_profiler_threshold) { - $this->logger->notice('Dice module creation lasts too long.', ['duration' => round($dur, 3), 'module' => $moduleClass, 'parameters' => $this->parameters]); - } + /** @var ICanHandleRequests $module */ + $module = $this->dice->create($moduleClass, $this->parameters); + + if ($this->dice_profiler_threshold > 0) { + $dur = floatval(microtime(true) - $stamp); + if ($dur >= $this->dice_profiler_threshold) { + $this->logger->notice('Dice module creation lasts too long.', ['duration' => round($dur, 3), 'module' => $moduleClass, 'parameters' => $this->parameters]); } } + + return $module; } /** diff --git a/src/BaseModule.php b/src/BaseModule.php index 5f72a0f79b..a1f4c033c6 100644 --- a/src/BaseModule.php +++ b/src/BaseModule.php @@ -245,10 +245,10 @@ abstract class BaseModule implements ICanHandleRequests $this->response->setStatus($e->getCode(), $e->getMessage()); $this->response->addContent($httpException->content($e)); - } finally { - $this->profiler->set(microtime(true) - $timestamp, 'content'); } + $this->profiler->set(microtime(true) - $timestamp, 'content'); + return $this->response->generate(); } @@ -269,7 +269,7 @@ abstract class BaseModule implements ICanHandleRequests $request[$parameter] = $this->getRequestValue($input, $parameter, $defaultvalue); } - foreach ($input ?? [] as $parameter => $value) { + foreach ($input as $parameter => $value) { if ($parameter == 'pagename') { continue; } @@ -456,7 +456,7 @@ abstract class BaseModule implements ICanHandleRequests * @param string $content * @param string $type * @param string|null $content_type - * @return void + * @return never * @throws HTTPException\InternalServerErrorException */ public function httpExit(string $content, string $type = Response::TYPE_HTML, ?string $content_type = null) @@ -493,7 +493,7 @@ abstract class BaseModule implements ICanHandleRequests * @param mixed $content * @param string $content_type * @param int $options A combination of json_encode() binary flags - * @return void + * @return never * @throws HTTPException\InternalServerErrorException * @see json_encode() */ @@ -508,7 +508,7 @@ abstract class BaseModule implements ICanHandleRequests * @param int $httpCode * @param mixed $content * @param string $content_type - * @return void + * @return never * @throws HTTPException\InternalServerErrorException */ public function jsonError(int $httpCode, $content, string $content_type = 'application/json') diff --git a/src/Console/MoveToAvatarCache.php b/src/Console/MoveToAvatarCache.php index 978a35a74b..90a35630e1 100644 --- a/src/Console/MoveToAvatarCache.php +++ b/src/Console/MoveToAvatarCache.php @@ -12,7 +12,6 @@ use Friendica\Contact\Avatar; use Friendica\Core\L10n; use Friendica\Model\Contact; use Friendica\Model\Photo; -use Friendica\Util\Images; use Friendica\Object\Image; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Protocol; @@ -115,6 +114,10 @@ HELP; private function storeAvatar(string $resourceid, array $contact, bool $quit_on_invalid) { + $photo = false; + $imgdata = false; + $image = null; + $valid = !empty($resourceid); if ($valid) { $this->out('1', false); @@ -143,7 +146,7 @@ HELP; } } - if ($valid) { + if ($valid && $image instanceof Image) { $this->out('4', false); $fields = Avatar::storeAvatarByImage($contact, $image); } else { diff --git a/src/Content/ContactSelector.php b/src/Content/ContactSelector.php index 5a00feeaf6..4e75ea34d1 100644 --- a/src/Content/ContactSelector.php +++ b/src/Content/ContactSelector.php @@ -142,17 +142,18 @@ class ContactSelector $replace = array_values($nets); $networkname = str_replace($search, $replace, $network); + $platform = ''; if (in_array($network, Protocol::FEDERATED) && !empty($gsid)) { $gserver = self::getServerForId($gsid); if (!empty($gserver['platform'])) { - $platform = $gserver['platform']; + $platform = (string) $gserver['platform']; } elseif (!empty($gserver['network']) && ($gserver['network'] != Protocol::ACTIVITYPUB)) { $platform = self::networkToName($gserver['network']); } - if (!empty($platform)) { + if ($platform !== '') { $networkname = $platform; } } @@ -161,7 +162,7 @@ class ContactSelector $networkname = DI::l10n()->t('%s (via %s)', $networkname, self::networkToName($protocol)); } elseif (in_array($network, ['', $protocol]) && ($network == Protocol::DFRN)) { $networkname .= ' (DFRN)'; - } elseif (in_array($network, ['', $protocol]) && ($network == Protocol::DIASPORA) && ($platform != 'diaspora')) { + } elseif (in_array($network, ['', $protocol]) && ($network == Protocol::DIASPORA) && ($platform !== 'diaspora')) { $networkname .= ' (Diaspora)'; } @@ -191,7 +192,7 @@ class ContactSelector $nets = [ Protocol::ACTIVITYPUB => 'activitypub', // https://commons.wikimedia.org/wiki/File:ActivityPub-logo-symbol.svg Protocol::BLUESKY => 'bluesky', // https://commons.wikimedia.org/wiki/File:Bluesky_Logo.svg - Protocol::DFRN => 'friendica', + Protocol::DFRN => 'friendica', Protocol::DIASPORA => 'diaspora', // https://www.svgrepo.com/svg/362315/diaspora Protocol::DIASPORA2 => 'diaspora', // https://www.svgrepo.com/svg/362315/diaspora Protocol::DISCOURSE => 'discourse', // https://commons.wikimedia.org/wiki/File:Discourse_icon.svg diff --git a/src/Content/Item.php b/src/Content/Item.php index a5a1a17a19..66a3328b04 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -180,6 +180,7 @@ class Item public static function replaceTag(string &$body, int $profile_uid, string $tag, string $network = '') { $replaced = false; + $contact = []; //is it a person tag? if (Tag::isType($tag, Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION)) { @@ -247,6 +248,8 @@ class Item } } + $newname = ''; + // Check if $contact has been successfully loaded if (DBA::isResult($contact)) { $profile = $contact['url']; diff --git a/src/Content/OEmbed.php b/src/Content/OEmbed.php index 4d3c589041..e5841ea22e 100644 --- a/src/Content/OEmbed.php +++ b/src/Content/OEmbed.php @@ -178,7 +178,7 @@ class OEmbed $oembed->thumbnail_height = $data['images'][0]['height']; } - Hook::callAll('oembed_fetch_url', $embedurl, $oembed); + Hook::callAll('oembed_fetch_url', $embedurl); return $oembed; } diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index e46bd99486..778591c1ab 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -116,9 +116,10 @@ class PostMedia extends BaseRepository return $attachments; } - $heights = []; + $heights = []; $selected = ''; $previews = []; + $video = []; foreach ($PostMedias as $PostMedia) { foreach ($links as $link) { diff --git a/src/Content/Text/NPF.php b/src/Content/Text/NPF.php index a0dd84fafa..c830d64a0f 100644 --- a/src/Content/Text/NPF.php +++ b/src/Content/Text/NPF.php @@ -543,6 +543,8 @@ class NPF return $npf; } + $block = []; + $media = Post\Media::getByURL($uri_id, $attributes['src'], [Post\Media::AUDIO, Post\Media::VIDEO]); if (!empty($media)) { switch ($media['type']) { diff --git a/src/Content/Text/Plaintext.php b/src/Content/Text/Plaintext.php index d2362714f4..8a1b479937 100644 --- a/src/Content/Text/Plaintext.php +++ b/src/Content/Text/Plaintext.php @@ -114,6 +114,8 @@ class Plaintext $post['text'] = trim($item['title']); } + $abstract = ''; + // Fetch the abstract from the given target network switch ($htmlmode) { case BBCode::TWITTER: @@ -123,7 +125,7 @@ class Plaintext case BBCode::BLUESKY: $abstract = BBCode::getAbstract($item['body'], Protocol::BLUESKY); break; - + default: // We don't know the exact target. // We fetch an abstract since there is a posting limit. if ($limit > 0) { @@ -242,6 +244,8 @@ class Plaintext $part = ''; $break_pos = 0; $comma_pos = 0; + $pos = 0; + $word = ''; $limit = $baselimit; @@ -256,8 +260,8 @@ class Plaintext } elseif ($pos_paragraph !== false) { $pos = $pos_paragraph + 1; } else { - $word = $message; - $message = ''; + $word = $message; + $message = ''; } if (trim($message)) { @@ -272,7 +276,7 @@ class Plaintext $break = mb_strrpos($word, "\n") !== false; if (!$break && (mb_strrpos($word, '. ') !== false || mb_strrpos($word, '? ') !== false || mb_strrpos($word, '! ') !== false)) { $break = IntlChar::isupper(mb_substr($message, 0, 1)); - } + } $comma = (mb_strrpos($word, ', ') !== false) && IntlChar::isalpha(mb_substr($message, 0, 1)); @@ -291,7 +295,7 @@ class Plaintext $break_pos = 0; $comma_pos = 0; } elseif ($break) { - $break_pos = $pos + mb_strlen($part); + $break_pos = $pos + mb_strlen($part); } elseif ($comma) { $comma_pos = $pos + mb_strlen($part); } diff --git a/src/Content/Widget.php b/src/Content/Widget.php index 6f030b640f..0c73df9091 100644 --- a/src/Content/Widget.php +++ b/src/Content/Widget.php @@ -402,7 +402,7 @@ class Widget return ''; } - $commonContacts = Contact\Relation::listCommon($localPCid, $visitorPCid, $condition, 0, 5, true); + $commonContacts = Contact\Relation::listCommon($localPCid, $visitorPCid, $condition, 0, 5); if (!DBA::isResult($commonContacts)) { return ''; } @@ -479,6 +479,10 @@ class Widget DI::cache()->set($cachekey, $dthen, Duration::HOUR); } + $cutoffday = ''; + $thisday = ''; + $nextday = ''; + if ($dthen) { // Set the start and end date to the beginning of the month $cutoffday = $dthen; @@ -513,7 +517,6 @@ class Widget return $o; } - $cutoff_year = intval(DateTimeFormat::localNow('Y')) - $visible_years; $cutoff = array_key_exists($cutoff_year, $ret); diff --git a/src/Content/Widget/VCard.php b/src/Content/Widget/VCard.php index 737db45ac2..cda7bb53b8 100644 --- a/src/Content/Widget/VCard.php +++ b/src/Content/Widget/VCard.php @@ -34,7 +34,7 @@ class VCard public static function getHTML(array $contact, bool $hide_mention = false, bool $hide_follow = false): string { if (!isset($contact['network']) || !isset($contact['id'])) { - Logger::warning('Incomplete contact', ['contact' => $contact ?? []]); + Logger::warning('Incomplete contact', ['contact' => $contact]); } $contact_url = Contact::getProfileLink($contact); @@ -61,7 +61,7 @@ class VCard $hide_follow = true; $hide_mention = true; } - + if ($contact['uid']) { $id = $contact['id']; $rel = $contact['rel']; diff --git a/src/Core/Addon/Exception/AddonInvalidConfigFileException.php b/src/Core/Addon/Exception/AddonInvalidConfigFileException.php index 677a9e42bd..f7d245ba16 100644 --- a/src/Core/Addon/Exception/AddonInvalidConfigFileException.php +++ b/src/Core/Addon/Exception/AddonInvalidConfigFileException.php @@ -14,8 +14,8 @@ use Throwable; */ class AddonInvalidConfigFileException extends \RuntimeException { - public function __construct($message = '', $code = 0, Throwable $previous = null) + public function __construct($message = '') { - parent::__construct($message, 500, $previous); + parent::__construct($message, 500); } } diff --git a/src/Core/Cache/Type/DatabaseCache.php b/src/Core/Cache/Type/DatabaseCache.php index 629472535a..efb9a8d03e 100644 --- a/src/Core/Cache/Type/DatabaseCache.php +++ b/src/Core/Cache/Type/DatabaseCache.php @@ -47,17 +47,21 @@ class DatabaseCache extends AbstractCache implements ICanCache } $stmt = $this->dba->select('cache', ['k'], $where); + } catch (\Exception $exception) { + throw new CachePersistenceException(sprintf('Cannot fetch all keys with prefix %s', $prefix), $exception); + } + try { $keys = []; while ($key = $this->dba->fetch($stmt)) { array_push($keys, $key['k']); } } catch (\Exception $exception) { - throw new CachePersistenceException(sprintf('Cannot fetch all keys with prefix %s', $prefix), $exception); - } finally { $this->dba->close($stmt); + throw new CachePersistenceException(sprintf('Cannot fetch all keys with prefix %s', $prefix), $exception); } + $this->dba->close($stmt); return $keys; } diff --git a/src/Core/Config/Exception/ConfigFileException.php b/src/Core/Config/Exception/ConfigFileException.php index 8b4ff1188f..fea882d180 100644 --- a/src/Core/Config/Exception/ConfigFileException.php +++ b/src/Core/Config/Exception/ConfigFileException.php @@ -11,8 +11,8 @@ use Throwable; class ConfigFileException extends \RuntimeException { - public function __construct($message = "", $code = 0, Throwable $previous = null) + public function __construct($message = "") { - parent::__construct($message, 500, $previous); + parent::__construct($message, 500); } } diff --git a/src/Core/Config/Util/ConfigFileManager.php b/src/Core/Config/Util/ConfigFileManager.php index 74b5e15541..ecb06a7cc8 100644 --- a/src/Core/Config/Util/ConfigFileManager.php +++ b/src/Core/Config/Util/ConfigFileManager.php @@ -245,59 +245,61 @@ class ConfigFileManager $fullName = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php'; $config = []; - if (file_exists($fullName)) { - $a = new \stdClass(); - $a->config = []; - include $fullName; + if (!file_exists($fullName)) { + return $config; + } - $htConfigCategories = array_keys($a->config); + $a = new \stdClass(); + $a->config = []; + include $fullName; - // map the legacy configuration structure to the current structure - foreach ($htConfigCategories as $htConfigCategory) { - if (is_array($a->config[$htConfigCategory])) { - $keys = array_keys($a->config[$htConfigCategory]); + $htConfigCategories = array_keys($a->config); - foreach ($keys as $key) { - $config[$htConfigCategory][$key] = $a->config[$htConfigCategory][$key]; - } - } else { - $config['config'][$htConfigCategory] = $a->config[$htConfigCategory]; + // map the legacy configuration structure to the current structure + foreach ($htConfigCategories as $htConfigCategory) { + if (is_array($a->config[$htConfigCategory])) { + $keys = array_keys($a->config[$htConfigCategory]); + + foreach ($keys as $key) { + $config[$htConfigCategory][$key] = $a->config[$htConfigCategory][$key]; } + } else { + $config['config'][$htConfigCategory] = $a->config[$htConfigCategory]; } + } - unset($a); + unset($a); - if (isset($db_host)) { - $config['database']['hostname'] = $db_host; - unset($db_host); - } - if (isset($db_user)) { - $config['database']['username'] = $db_user; - unset($db_user); - } - if (isset($db_pass)) { - $config['database']['password'] = $db_pass; - unset($db_pass); - } - if (isset($db_data)) { - $config['database']['database'] = $db_data; - unset($db_data); - } - if (isset($config['system']['db_charset'])) { - $config['database']['charset'] = $config['system']['db_charset']; - } - if (isset($pidfile)) { - $config['system']['pidfile'] = $pidfile; - unset($pidfile); - } - if (isset($default_timezone)) { - $config['system']['default_timezone'] = $default_timezone; - unset($default_timezone); - } - if (isset($lang)) { - $config['system']['language'] = $lang; - unset($lang); - } + if (isset($db_host)) { + $config['database']['hostname'] = $db_host; + unset($db_host); + } + if (isset($db_user)) { + $config['database']['username'] = $db_user; + unset($db_user); + } + if (isset($db_pass)) { + $config['database']['password'] = $db_pass; + unset($db_pass); + } + if (isset($db_data)) { + $config['database']['database'] = $db_data; + unset($db_data); + } + if (isset($config['system']) && isset($config['system']['db_charset'])) { + $config['database']['charset'] = $config['system']['db_charset']; + } + if (isset($pidfile)) { + $config['system']['pidfile'] = $pidfile; + unset($pidfile); + } + if (isset($default_timezone)) { + $config['system']['default_timezone'] = $default_timezone; + unset($default_timezone); + } + if (isset($lang)) { + $config['system']['language'] = $lang; + unset($lang); } return $config; diff --git a/src/Core/Lock/Type/DatabaseLock.php b/src/Core/Lock/Type/DatabaseLock.php index 9a00791007..d05871689c 100644 --- a/src/Core/Lock/Type/DatabaseLock.php +++ b/src/Core/Lock/Type/DatabaseLock.php @@ -182,17 +182,22 @@ class DatabaseLock extends AbstractLock } $stmt = $this->dba->select('locks', ['name'], $where); + } catch (\Exception $exception) { + throw new LockPersistenceException(sprintf('Cannot get lock with prefix %s', $prefix), $exception); + } + try { $keys = []; while ($key = $this->dba->fetch($stmt)) { array_push($keys, $key['name']); } } catch (\Exception $exception) { - throw new LockPersistenceException(sprintf('Cannot get lock with prefix %s', $prefix), $exception); - } finally { $this->dba->close($stmt); + throw new LockPersistenceException(sprintf('Cannot get lock with prefix %s', $prefix), $exception); } + $this->dba->close($stmt); + return $keys; } } diff --git a/src/Core/PConfig/Repository/PConfig.php b/src/Core/PConfig/Repository/PConfig.php index 39a5c31800..d3b68b8ce1 100644 --- a/src/Core/PConfig/Repository/PConfig.php +++ b/src/Core/PConfig/Repository/PConfig.php @@ -60,7 +60,11 @@ class PConfig } else { $configs = $this->db->select(static::$table_name, ['cat', 'v', 'k'], ['cat' => $cat, 'uid' => $uid]); } + } catch (\Exception $exception) { + throw new PConfigPersistenceException(sprintf('Cannot load config category "%s" for user %d', $cat, $uid), $exception); + } + try { while ($config = $this->db->fetch($configs)) { $key = $config['k']; $value = ValueConversion::toConfigValue($config['v']); @@ -71,11 +75,12 @@ class PConfig } } } catch (\Exception $exception) { - throw new PConfigPersistenceException(sprintf('Cannot load config category %s for user %d', $cat, $uid), $exception); - } finally { $this->db->close($configs); + throw new PConfigPersistenceException(sprintf('Cannot load config category "%s" for user %d', $cat, $uid), $exception); } + $this->db->close($configs); + return $return; } diff --git a/src/Core/Session/Factory/Session.php b/src/Core/Session/Factory/Session.php index 7855cf35d6..734e34efa6 100644 --- a/src/Core/Session/Factory/Session.php +++ b/src/Core/Session/Factory/Session.php @@ -13,11 +13,14 @@ use Friendica\Core\Cache\Factory\Cache; use Friendica\Core\Cache\Type\DatabaseCache; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Session\Capability\IHandleSessions; -use Friendica\Core\Session\Type; -use Friendica\Core\Session\Handler; +use Friendica\Core\Session\Handler\Cache as CacheHandler; +use Friendica\Core\Session\Handler\Database as DatabaseHandler; +use Friendica\Core\Session\Type\Memory; +use Friendica\Core\Session\Type\Native; use Friendica\Database\Database; use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; +use Throwable; /** * Factory for creating a valid Session for this run @@ -49,36 +52,45 @@ class Session $profiler->startRecording('session'); $session_handler = $config->get('system', 'session_handler', self::HANDLER_DEFAULT); - try { - if ($mode->isInstall() || $mode->isBackend()) { - $session = new Type\Memory(); - } else { - switch ($session_handler) { - case self::HANDLER_DATABASE: - $handler = new Handler\Database($dba, $logger, $server); - break; - case self::HANDLER_CACHE: - $cache = $cacheFactory->createDistributed(); - - // In case we're using the db as cache driver, use the native db session, not the cache - if ($config->get('system', 'cache_driver') === DatabaseCache::NAME) { - $handler = new Handler\Database($dba, $logger, $server); - } else { - $handler = new Handler\Cache($cache, $logger); - } - break; - default: - $handler = null; - } - - $session = new Type\Native($baseURL, $handler); - } - } catch (\Throwable $e) { - $logger->notice('Unable to create session', ['mode' => $mode, 'session_handler' => $session_handler, 'exception' => $e]); - $session = new Type\Memory(); - } finally { + if ($mode->isInstall() || $mode->isBackend()) { + $session = new Memory(); $profiler->stopRecording(); return $session; } + + try { + switch ($session_handler) { + case self::HANDLER_DATABASE: + $handler = new DatabaseHandler($dba, $logger, $server); + break; + case self::HANDLER_CACHE: + $cache = $cacheFactory->createDistributed(); + + // In case we're using the db as cache driver, use the native db session, not the cache + if ($config->get('system', 'cache_driver') === DatabaseCache::NAME) { + $handler = new DatabaseHandler($dba, $logger, $server); + } else { + $handler = new CacheHandler($cache, $logger); + } + break; + default: + $handler = null; + } + } catch (Throwable $e) { + $logger->notice('Unable to create session', ['mode' => $mode, 'session_handler' => $session_handler, 'exception' => $e]); + $session = new Memory(); + $profiler->stopRecording(); + return $session; + } + + try { + $session = new Native($baseURL, $handler); + } catch (Throwable $e) { + $logger->notice('Unable to create session', ['mode' => $mode, 'session_handler' => $session_handler, 'exception' => $e]); + $session = new Memory(); + } + + $profiler->stopRecording(); + return $session; } } diff --git a/src/Core/Storage/Type/ExternalResource.php b/src/Core/Storage/Type/ExternalResource.php index b9b67a122a..0345f3ae8e 100644 --- a/src/Core/Storage/Type/ExternalResource.php +++ b/src/Core/Storage/Type/ExternalResource.php @@ -54,16 +54,13 @@ class ExternalResource implements ICanReadFromStorage $this->logger->notice('URL is invalid', ['url' => $data->url, 'error' => $exception]); throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference), $exception->getCode(), $exception); } - if (!empty($fetchResult) && $fetchResult->isSuccess()) { - $this->logger->debug('Got picture', ['Content-Type' => $fetchResult->getHeader('Content-Type'), 'uid' => $data->uid, 'url' => $data->url]); - return $fetchResult->getBodyString(); - } else { - if (empty($fetchResult)) { - throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference)); - } else { - throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference), $fetchResult->getReturnCode(), new Exception($fetchResult->getBodyString())); - } + + if (!$fetchResult->isSuccess()) { + throw new ReferenceStorageException(sprintf('External resource failed to get %s', $reference), $fetchResult->getReturnCode(), new Exception($fetchResult->getBodyString())); } + + $this->logger->debug('Got picture', ['Content-Type' => $fetchResult->getHeader('Content-Type'), 'uid' => $data->uid, 'url' => $data->url]); + return $fetchResult->getBodyString(); } /** diff --git a/src/Core/System.php b/src/Core/System.php index 4eca8bc80b..3eabf9695d 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -393,6 +393,8 @@ class System /** * Exit the program execution. + * + * @return never */ public static function exit() { @@ -506,6 +508,8 @@ class System * @throws TemporaryRedirectException * * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * + * @return never */ public static function externalRedirect($url, $code = 302) { diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index 65a9f450ea..098a47d675 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -275,7 +275,7 @@ class DBStructure $is_new_table = false; $sql3 = ""; if (!isset($database[$name])) { - $sql = DbaDefinitionSqlWriter::createTable($name, $structure, $verbose, $action); + $sql = DbaDefinitionSqlWriter::createTable($name, $structure); if ($verbose) { echo $sql; } diff --git a/src/Database/Database.php b/src/Database/Database.php index 1deb454190..15bb84765a 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -534,6 +534,8 @@ class Database throw new ServiceUnavailableException('The Connection is empty, although connected is set true.'); } + $retval = false; + switch ($this->driver) { case self::PDO: // If there are no arguments we use "query" @@ -1074,6 +1076,8 @@ class Database */ public function lastInsertId(): int { + $id = 0; + switch ($this->driver) { case self::PDO: $id = $this->connection->lastInsertId(); @@ -1681,6 +1685,8 @@ class Database return false; } + $ret = false; + switch ($this->driver) { case self::PDO: $ret = $stmt->closeCursor(); @@ -1695,8 +1701,6 @@ class Database } elseif ($stmt instanceof mysqli_result) { $stmt->free(); $ret = true; - } else { - $ret = false; } break; } @@ -1770,8 +1774,8 @@ class Database /** * Acquire a lock to prevent a table optimization * - * @return bool - * @throws LockPersistenceException + * @return bool + * @throws LockPersistenceException */ public function acquireOptimizeLock(): bool { @@ -1781,8 +1785,8 @@ class Database /** * Release the table optimization lock * - * @return bool - * @throws LockPersistenceException + * @return bool + * @throws LockPersistenceException */ public function releaseOptimizeLock(): bool { diff --git a/src/Database/PostUpdate.php b/src/Database/PostUpdate.php index 0f0eb12899..65c8e98c22 100644 --- a/src/Database/PostUpdate.php +++ b/src/Database/PostUpdate.php @@ -284,7 +284,7 @@ class PostUpdate } while ($item = DBA::fetch($items)) { - Tag::storeFromBody($item['uri-id'], $item['body'], '#!@', false); + Tag::storeFromBody($item['uri-id'], $item['body'], '#!@'); $id = $item['uri-id']; ++$rows; if ($rows % 1000 == 0) { @@ -775,11 +775,8 @@ class PostUpdate while ($photo = DBA::fetch($photos)) { $img = Photo::getImageForPhoto($photo); - if (!empty($img)) { - $md5 = md5($img->asString()); - } else { - $md5 = ''; - } + $md5 = md5($img->asString()); + DBA::update('photo', ['hash' => $md5], ['id' => $photo['id']]); ++$rows; } @@ -1220,7 +1217,7 @@ class PostUpdate $parts = parse_url($contact['url']); unset($parts['path']); $server = (string)Uri::fromParts($parts); - + DBA::update('contact', ['gsid' => GServer::getID($server, true), 'baseurl' => GServer::cleanURL($server)], ['id' => $contact['id']]); diff --git a/src/Database/View.php b/src/Database/View.php index dee61428ff..0d34c3a4bc 100644 --- a/src/Database/View.php +++ b/src/Database/View.php @@ -25,11 +25,11 @@ class View foreach (['post-view', 'post-thread-view'] as $view) { if (self::isView($view)) { $sql = sprintf("DROP VIEW IF EXISTS `%s`", DBA::escape($view)); - if (!empty($sql) && $verbose) { + if ($verbose) { echo $sql . ";\n"; } - if (!empty($sql) && $action) { + if ($action) { DBA::e($sql); } } diff --git a/src/Factory/Api/Twitter/DirectMessage.php b/src/Factory/Api/Twitter/DirectMessage.php index f80bdd85cc..fd276bd205 100644 --- a/src/Factory/Api/Twitter/DirectMessage.php +++ b/src/Factory/Api/Twitter/DirectMessage.php @@ -48,6 +48,9 @@ class DirectMessage extends BaseFactory throw new HTTPException\NotFoundException('Direct message with ID ' . $mail . ' not found.'); } + $title = ''; + $text = ''; + if (!empty($text_mode)) { $title = $mail['title']; if ($text_mode == 'html') { @@ -56,7 +59,6 @@ class DirectMessage extends BaseFactory $text = HTML::toPlaintext(BBCode::convertForUriId($mail['uri-id'], $mail['body'], BBCode::TWITTER_API), 0); } } else { - $title = ''; $text = $mail['title'] . "\n" . HTML::toPlaintext(BBCode::convertForUriId($mail['uri-id'], $mail['body'], BBCode::TWITTER_API), 0); } diff --git a/src/Factory/Api/Twitter/User.php b/src/Factory/Api/Twitter/User.php index 71721f143b..8ffe07f10e 100644 --- a/src/Factory/Api/Twitter/User.php +++ b/src/Factory/Api/Twitter/User.php @@ -57,7 +57,7 @@ class User extends BaseFactory ['author-id' => $publicContact['id'], 'gravity' => [Item::GRAVITY_COMMENT, Item::GRAVITY_PARENT], 'private' => [Item::PUBLIC, Item::UNLISTED]], ['order' => ['uri-id' => true]]); if (!empty($post['uri-id'])) { - $status = $this->status->createFromUriId($post['uri-id'], $uid)->toArray(); + $status = $this->status->createFromUriId($post['uri-id'], $uid); } } diff --git a/src/Model/APContact.php b/src/Model/APContact.php index 27bf3aedab..10534498ac 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -178,7 +178,7 @@ class APContact try { $curlResult = HTTPSignature::fetchRaw($url); - $failed = empty($curlResult) || empty($curlResult->getBodyString()) || + $failed = empty($curlResult->getBodyString()) || (!$curlResult->isSuccess() && ($curlResult->getReturnCode() != 410)); if (!$failed) { diff --git a/src/Model/Contact.php b/src/Model/Contact.php index a561c00c02..e007afc2d8 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -2364,6 +2364,8 @@ class Contact $cache_avatar = !DBA::exists('contact', ['nurl' => $contact['nurl'], 'self' => true]); } + $fields = []; + if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL]) || $cache_avatar) { if (Avatar::deleteCache($contact)) { $force = true; @@ -2380,6 +2382,8 @@ class Contact Logger::debug('Use default avatar', ['id' => $cid, 'uid' => $uid]); } + $local_uid = 0; + // Use the data from the self account if (empty($fields)) { $local_uid = User::getIdForURL($contact['url']); @@ -2411,8 +2415,15 @@ class Contact if ($update) { $photos = Photo::importProfilePhoto($avatar, $uid, $cid, true); if ($photos) { - $fields = ['avatar' => $avatar, 'photo' => $photos[0], 'thumb' => $photos[1], 'micro' => $photos[2], 'blurhash' => $photos[3], 'avatar-date' => DateTimeFormat::utcNow()]; - $update = !empty($fields); + $fields = [ + 'avatar' => $avatar, + 'photo' => $photos[0], + 'thumb' => $photos[1], + 'micro' => $photos[2], + 'blurhash' => $photos[3], + 'avatar-date' => DateTimeFormat::utcNow(), + ]; + $update = true; Logger::debug('Created new cached avatars', ['id' => $cid, 'uid' => $uid, 'owner-uid' => $local_uid]); } else { $update = false; diff --git a/src/Model/Event.php b/src/Model/Event.php index 7c68588b43..210f601691 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -333,7 +333,7 @@ class Event $item['uri'] = $event['uri']; $item['uri-id'] = ItemURI::getIdByURI($event['uri']); $item['guid'] = $event['guid']; - $item['plink'] = $arr['plink'] ?? ''; + $item['plink'] = ''; $item['post-type'] = Item::PT_EVENT; $item['wall'] = $event['cid'] ? 0 : 1; $item['contact-id'] = $contact['id']; diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 73d7d1df08..5e8cd33310 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -224,6 +224,8 @@ class GServer */ public static function reachable(array $contact): bool { + $server = ''; + if (!empty($contact['gsid'])) { $gsid = $contact['gsid']; } elseif (!empty($contact['baseurl'])) { @@ -800,6 +802,8 @@ class GServer $serverdata['failed'] = false; $serverdata['blocked'] = false; + $id = 0; + $gserver = DBA::selectFirst('gserver', ['network'], ['nurl' => Strings::normaliseLink($url)]); if (!DBA::isResult($gserver)) { $serverdata['created'] = DateTimeFormat::utcNow(); @@ -1197,10 +1201,6 @@ class GServer } } - if (empty($server)) { - return []; - } - if (empty($server['network'])) { $server['network'] = Protocol::PHANTOM; } @@ -1337,10 +1337,6 @@ class GServer } } - if (empty($server)) { - return []; - } - if (empty($server['network'])) { $server['network'] = Protocol::PHANTOM; } @@ -1444,7 +1440,7 @@ class GServer } } - if (empty($server) || empty($server['platform'])) { + if (empty($server['platform'])) { return []; } @@ -1652,10 +1648,11 @@ class GServer } $data = json_decode($curlResult->getBodyString(), true); - if (empty($data)) { + if (!is_string($data)) { return ''; } - return $data ?? ''; + + return $data; } private static function getZotData(string $url, array $serverdata): array @@ -2310,13 +2307,19 @@ class GServer return $serverdata; } - if (file_exists(__DIR__ . '/../../static/platforms.config.php')) { - require __DIR__ . '/../../static/platforms.config.php'; - } else { + if (!file_exists(__DIR__ . '/../../static/platforms.config.php')) { throw new HTTPException\InternalServerErrorException('Invalid platform file'); } - $platforms = array_merge($ap_platforms, $dfrn_platforms, $zap_platforms, $platforms); + /** @var array $grouped_platforms */ + $grouped_platforms = require __DIR__ . '/../../static/platforms.config.php'; + + $platforms = array_merge( + $grouped_platforms['ap_platforms'], + $grouped_platforms['dfrn_platforms'], + $grouped_platforms['zap_platforms'], + $grouped_platforms['platforms'], + ); $doc = new DOMDocument(); @$doc->loadHTML($curlResult->getBodyString()); @@ -2367,11 +2370,11 @@ class GServer $platform = $platform_parts[0]; $serverdata['version'] = $platform_parts[1]; } - if (in_array($platform, array_values($dfrn_platforms))) { + if (in_array($platform, array_values($grouped_platforms['dfrn_platforms']))) { $serverdata['network'] = Protocol::DFRN; - } elseif (in_array($platform, array_values($ap_platforms))) { + } elseif (in_array($platform, array_values($grouped_platforms['ap_platforms']))) { $serverdata['network'] = Protocol::ACTIVITYPUB; - } elseif (in_array($platform, array_values($zap_platforms))) { + } elseif (in_array($platform, array_values($grouped_platforms['zap_platforms']))) { $serverdata['network'] = Protocol::ZOT; } if (in_array($platform, array_values($platforms))) { @@ -2414,9 +2417,9 @@ class GServer $assigned = true; } - if (in_array($attr['content'], array_keys($ap_platforms))) { + if (in_array($attr['content'], array_keys($grouped_platforms['ap_platforms']))) { $serverdata['network'] = Protocol::ACTIVITYPUB; - } elseif (in_array($attr['content'], array_values($zap_platforms))) { + } elseif (in_array($attr['content'], array_values($grouped_platforms['zap_platforms']))) { $serverdata['network'] = Protocol::ZOT; } } @@ -2492,7 +2495,7 @@ class GServer */ public static function discover() { - if (!DI::config('system', 'discover_servers')) { + if (!DI::config()->get('system', 'discover_servers')) { return; } diff --git a/src/Model/Item.php b/src/Model/Item.php index 268b808ce8..b42f89729a 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -193,6 +193,7 @@ class Item $fields['vid'] = Verb::getID($fields['verb']); } + $previous = []; if (!empty($fields['edited'])) { $previous = Post::selectFirst(['edited'], $condition); } @@ -856,6 +857,8 @@ class Item $priority = Worker::PRIORITY_HIGH; + $copy_permissions = false; + // If it is a posting where users should get notifications, then define it as wall posting if ($notify) { $item = self::prepareOriginPost($item); @@ -3205,7 +3208,7 @@ class Item } elseif ($remote_user) { // Authenticated visitor - fetch the matching permissionsets $permissionSets = DI::permissionSet()->selectByContactId($remote_user, $owner_id); - if (!empty($permissionSets)) { + if (count($permissionSets) > 0) { $condition = [ "(`private` != ? OR (`private` = ? AND `wall` AND `psid` IN (" . implode(', ', array_fill(0, count($permissionSets), '?')) . ")))", @@ -3234,17 +3237,12 @@ class Item $table = DBA::quoteIdentifier($table) . '.'; } - /* - * Construct permissions - * - * default permissions - anonymous user - */ - $sql = sprintf(" AND " . $table . "`private` != %d", self::PRIVATE); - // Profile owner - everything is visible if ($local_user && ($local_user == $owner_id)) { - $sql = ''; - } elseif ($remote_user) { + return ''; + } + + if ($remote_user) { /* * Authenticated visitor. Unless pre-verified, * check that the contact belongs to this $owner_id @@ -3254,16 +3252,21 @@ class Item */ $permissionSets = DI::permissionSet()->selectByContactId($remote_user, $owner_id); - if (!empty($permissionSets)) { + $sql_set = ''; + + if (count($permissionSets) > 0) { $sql_set = sprintf(" OR (" . $table . "`private` = %d AND " . $table . "`wall` AND " . $table . "`psid` IN (", self::PRIVATE) . implode(',', $permissionSets->column('id')) . "))"; - } else { - $sql_set = ''; } - $sql = sprintf(" AND (" . $table . "`private` != %d", self::PRIVATE) . $sql_set . ")"; + return sprintf(" AND (" . $table . "`private` != %d", self::PRIVATE) . $sql_set . ")"; } - return $sql; + /* + * Construct permissions + * + * default permissions - anonymous user + */ + return sprintf(" AND " . $table . "`private` != %d", self::PRIVATE); } /** @@ -3387,6 +3390,7 @@ class Item $shared_uri_id = 0; $shared_links = []; $quote_shared_links = []; + $shared_item = []; $shared = DI::contentItem()->getSharedPost($item, $fields); if (!empty($shared['post'])) { @@ -3430,6 +3434,8 @@ class Item } } + $sharedSplitAttachments = []; + if (!empty($shared_item['uri-id'])) { $shared_uri_id = $shared_item['uri-id']; $shared_links[] = strtolower($shared_item['plink']); @@ -3503,7 +3509,7 @@ class Item $s = self::addGallery($s, $sharedSplitAttachments['visual']); $s = self::addVisualAttachments($sharedSplitAttachments['visual'], $shared_item, $s, true); $s = self::addLinkAttachment($shared_uri_id ?: $item['uri-id'], $sharedSplitAttachments, $body, $s, true, $quote_shared_links); - $s = self::addNonVisualAttachments($sharedSplitAttachments['additional'], $item, $s, true); + $s = self::addNonVisualAttachments($sharedSplitAttachments['additional'], $item, $s); $body = BBCode::removeSharedData($body); } @@ -3516,7 +3522,7 @@ class Item $s = self::addGallery($s, $itemSplitAttachments['visual']); $s = self::addVisualAttachments($itemSplitAttachments['visual'], $item, $s, false); $s = self::addLinkAttachment($item['uri-id'], $itemSplitAttachments, $body, $s, false, $shared_links); - $s = self::addNonVisualAttachments($itemSplitAttachments['additional'], $item, $s, false); + $s = self::addNonVisualAttachments($itemSplitAttachments['additional'], $item, $s); $s = self::addQuestions($item, $s); // Map. diff --git a/src/Model/Post/Engagement.php b/src/Model/Post/Engagement.php index e6bcf35068..b48818437c 100644 --- a/src/Model/Post/Engagement.php +++ b/src/Model/Post/Engagement.php @@ -128,7 +128,7 @@ class Engagement return ($ret && !$exists) ? $engagement['uri-id'] : 0; } - public static function getContentSize(array $item): int + public static function getContentSize(array $item): int { $body = ' ' . $item['title'] . ' ' . $item['content-warning'] . ' ' . $item['body']; $body = BBCode::removeAttachment($body); @@ -318,6 +318,8 @@ class Engagement $result = Post::selectPosts(['author-addr', 'author-nick', 'author-contact-type'], ['thr-parent-id' => $uri_id, 'gravity' => Item::GRAVITY_ACTIVITY, 'verb' => Activity::ANNOUNCE, 'author-contact-type' => [Contact::TYPE_RELAY, Contact::TYPE_COMMUNITY]]); while ($reshare = Post::fetch($result)) { + $prefix = ''; + switch ($reshare['author-contact-type']) { case Contact::TYPE_RELAY: $prefix = ' application_'; diff --git a/src/Model/Post/Link.php b/src/Model/Post/Link.php index 021e8a84b7..d97d316b9c 100644 --- a/src/Model/Post/Link.php +++ b/src/Model/Post/Link.php @@ -113,9 +113,6 @@ class Link try { $curlResult = HTTPSignature::fetchRaw($url, 0, [HttpClientOptions::TIMEOUT => $timeout, HttpClientOptions::ACCEPT_CONTENT => $accept]); - if (empty($curlResult) || !$curlResult->isSuccess()) { - return []; - } } catch (\Exception $exception) { Logger::notice('Error fetching url', ['url' => $url, 'exception' => $exception]); return []; diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index e707c79ced..c4770682ab 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -699,7 +699,7 @@ class Media if (preg_match_all("/\[url\](https?:.*?)\[\/url\]/ism", $body, $matches)) { foreach ($matches[1] as $url) { Logger::info('Got page url (link without description)', ['uri-id' => $uriid, 'url' => $url]); - $result = self::insert(['uri-id' => $uriid, 'type' => self::UNKNOWN, 'url' => $url], false, $network); + $result = self::insert(['uri-id' => $uriid, 'type' => self::UNKNOWN, 'url' => $url], false); if ($result && !in_array($network, [Protocol::ACTIVITYPUB, Protocol::DIASPORA])) { self::revertHTMLType($uriid, $url, $fullbody); Logger::debug('Revert HTML type', ['uri-id' => $uriid, 'url' => $url]); @@ -715,7 +715,7 @@ class Media if (preg_match_all("/\[url\=(https?:.*?)\].*?\[\/url\]/ism", $body, $matches)) { foreach ($matches[1] as $url) { Logger::info('Got page url (link with description)', ['uri-id' => $uriid, 'url' => $url]); - $result = self::insert(['uri-id' => $uriid, 'type' => self::UNKNOWN, 'url' => $url], false, $network); + $result = self::insert(['uri-id' => $uriid, 'type' => self::UNKNOWN, 'url' => $url], false); if ($result && !in_array($network, [Protocol::ACTIVITYPUB, Protocol::DIASPORA])) { self::revertHTMLType($uriid, $url, $fullbody); Logger::debug('Revert HTML type', ['uri-id' => $uriid, 'url' => $url]); diff --git a/src/Module/Admin/Themes/Embed.php b/src/Module/Admin/Themes/Embed.php index 00a79db54d..64f686a1ab 100644 --- a/src/Module/Admin/Themes/Embed.php +++ b/src/Module/Admin/Themes/Embed.php @@ -49,7 +49,7 @@ class Embed extends BaseAdmin require_once "view/theme/$theme/config.php"; if (function_exists('theme_admin_post')) { self::checkFormSecurityTokenRedirectOnError('/admin/themes/' . $theme . '/embed?mode=minimal', 'admin_theme_settings'); - theme_admin_post($this->appHelper); + theme_admin_post(); } } diff --git a/src/Module/Api/Mastodon/Markers.php b/src/Module/Api/Mastodon/Markers.php index b5ed3e825a..11ae2e9324 100644 --- a/src/Module/Api/Mastodon/Markers.php +++ b/src/Module/Api/Mastodon/Markers.php @@ -31,7 +31,7 @@ class Markers extends BaseApi } } - if (empty($timeline) || empty($last_read_id) || empty($application['id'])) { + if ($timeline === '' || $last_read_id === '' || empty($application['id'])) { $this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity()); } diff --git a/src/Module/Api/Twitter/Friendships/Show.php b/src/Module/Api/Twitter/Friendships/Show.php index 1c2bea6cba..2099bf16a9 100644 --- a/src/Module/Api/Twitter/Friendships/Show.php +++ b/src/Module/Api/Twitter/Friendships/Show.php @@ -28,12 +28,12 @@ class Show extends ContactEndpoint $target_cid = BaseApi::getContactIDForSearchterm($this->getRequestValue($request, 'target_screen_name', ''), '', $this->getRequestValue($request, 'target_id', 0), $uid); $source = Contact::getById($source_cid); - if (empty($source)) { + if ($source === false) { throw new NotFoundException('Source not found'); } $target = Contact::getById($target_cid); - if (empty($source)) { + if ($target === false) { throw new NotFoundException('Target not found'); } diff --git a/src/Module/BaseApi.php b/src/Module/BaseApi.php index e5ec4db8dc..a2efbfc1cc 100644 --- a/src/Module/BaseApi.php +++ b/src/Module/BaseApi.php @@ -511,7 +511,7 @@ class BaseApi extends BaseModule /** * @param int $errorno * @param Error $error - * @return void + * @return never * @throws HTTPException\InternalServerErrorException */ protected function logAndJsonError(int $errorno, Error $error) diff --git a/src/Module/BaseNotifications.php b/src/Module/BaseNotifications.php index f9f47d4a21..0445075995 100644 --- a/src/Module/BaseNotifications.php +++ b/src/Module/BaseNotifications.php @@ -131,7 +131,7 @@ abstract class BaseNotifications extends BaseModule $notif_tpl = Renderer::getMarkupTemplate('notifications/notifications.tpl'); return Renderer::replaceMacros($notif_tpl, [ - '$header' => $header ?? $this->t('Notifications'), + '$header' => $header ?: $this->t('Notifications'), '$tabs' => $tabs, '$notifications' => $notifications, '$noContent' => $noContent, diff --git a/src/Module/Calendar/Event/API.php b/src/Module/Calendar/Event/API.php index 3223ecd42b..8a62efdc8a 100644 --- a/src/Module/Calendar/Event/API.php +++ b/src/Module/Calendar/Event/API.php @@ -140,9 +140,9 @@ class API extends BaseModule $share = intval($request['share'] ?? 0); $isPreview = intval($request['preview'] ?? 0); - $start = DateTimeFormat::convert($strStartDateTime ?? DBA::NULL_DATETIME, 'UTC', $this->timezone); + $start = DateTimeFormat::convert($strStartDateTime, 'UTC', $this->timezone); if (!$noFinish) { - $finish = DateTimeFormat::convert($strFinishDateTime ?? DBA::NULL_DATETIME, 'UTC', $this->timezone); + $finish = DateTimeFormat::convert($strFinishDateTime, 'UTC', $this->timezone); } else { $finish = DBA::NULL_DATETIME; } diff --git a/src/Module/Circle.php b/src/Module/Circle.php index ae81d3f757..b638eec557 100644 --- a/src/Module/Circle.php +++ b/src/Module/Circle.php @@ -70,6 +70,8 @@ class Circle extends BaseModule throw new \Exception(DI::l10n()->t('Permission denied.'), 403); } + $message = ''; + if (isset($this->parameters['command'])) { $circle_id = $this->parameters['circle']; $contact_id = $this->parameters['contact']; @@ -169,7 +171,9 @@ class Circle extends BaseModule ]); } - $nocircle = false; + $nocircle = false; + $members = []; + $preselected = []; // @TODO: Replace with parameter from router if ((DI::args()->getArgc() == 2) && (DI::args()->getArgv()[1] === 'none') || @@ -181,9 +185,6 @@ class Circle extends BaseModule 'name' => DI::l10n()->t('Contacts not in any circle'), ]; - $members = []; - $preselected = []; - $context = $context + [ '$title' => $circle['name'], '$gname' => ['circle_name', DI::l10n()->t('Circle Name: '), $circle['name'], ''], diff --git a/src/Module/Contact/Conversations.php b/src/Module/Contact/Conversations.php index 55fde3690e..b6b85e1e82 100644 --- a/src/Module/Contact/Conversations.php +++ b/src/Module/Contact/Conversations.php @@ -7,18 +7,19 @@ namespace Friendica\Module\Contact; -use Friendica\App; +use Friendica\App\Arguments; +use Friendica\App\BaseURL; +use Friendica\App\Page; use Friendica\BaseModule; use Friendica\Contact\LocalRelationship\Repository\LocalRelationship; use Friendica\Content\Conversation; use Friendica\Content\Nav; -use Friendica\Content\Widget; +use Friendica\Content\Widget\VCard; use Friendica\Core\ACL; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Theme; -use Friendica\Model; use Friendica\Model\Contact as ModelContact; use Friendica\Module\Contact; use Friendica\Module\Response; @@ -33,7 +34,7 @@ use Psr\Log\LoggerInterface; class Conversations extends BaseModule { /** - * @var App\Page + * @var Page */ private $page; /** @@ -49,7 +50,7 @@ class Conversations extends BaseModule */ private $userSession; - public function __construct(L10n $l10n, LocalRelationship $localRelationship, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, App\Page $page, Conversation $conversation, IHandleUserSessions $userSession, $server, array $parameters = []) + public function __construct(L10n $l10n, LocalRelationship $localRelationship, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, Page $page, Conversation $conversation, IHandleUserSessions $userSession, $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); @@ -67,12 +68,12 @@ class Conversations extends BaseModule // Backward compatibility: Ensure to use the public contact when the user contact is provided // Remove by version 2022.03 - $pcid = Model\Contact::getPublicContactId(intval($this->parameters['id']), $this->userSession->getLocalUserId()); + $pcid = ModelContact::getPublicContactId(intval($this->parameters['id']), $this->userSession->getLocalUserId()); if (!$pcid) { throw new NotFoundException($this->t('Contact not found.')); } - $contact = Model\Contact::getAccountById($pcid); + $contact = ModelContact::getAccountById($pcid); if (empty($contact)) { throw new NotFoundException($this->t('Contact not found.')); } @@ -83,7 +84,7 @@ class Conversations extends BaseModule } $localRelationship = $this->localRelationship->getForUserContact($this->userSession->getLocalUserId(), $contact['id']); - if ($localRelationship->rel === Model\Contact::SELF) { + if ($localRelationship->rel === ModelContact::SELF) { $this->baseUrl->redirect('profile/' . $contact['nick']); } @@ -93,10 +94,12 @@ class Conversations extends BaseModule $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.css')); $this->page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput-typeahead.css')); - $this->page['aside'] .= Widget\VCard::getHTML($contact, true); + $this->page['aside'] .= VCard::getHTML($contact, true); Nav::setSelected('contact'); + $output = ''; + if (!$contact['ap-posting-restricted']) { $options = [ 'lockstate' => ACL::getLockstateForUserId($this->userSession->getLocalUserId()) ? 'lock' : 'unlock', @@ -104,12 +107,12 @@ class Conversations extends BaseModule 'bang' => '', 'content' => ($contact['contact-type'] == ModelContact::TYPE_COMMUNITY ? '!' : '@') . ($contact['addr'] ?: $contact['url']), ]; - $o = $this->conversation->statusEditor($options); + $output = $this->conversation->statusEditor($options); } - $o .= Contact::getTabsHTML($contact, Contact::TAB_CONVERSATIONS); - $o .= Model\Contact::getThreadsFromId($contact['id'], $this->userSession->getLocalUserId(), 0, 0, $request['last_created'] ?? ''); + $output .= Contact::getTabsHTML($contact, Contact::TAB_CONVERSATIONS); + $output .= ModelContact::getThreadsFromId($contact['id'], $this->userSession->getLocalUserId(), 0, 0, $request['last_created'] ?? ''); - return $o; + return $output; } } diff --git a/src/Module/Conversation/Timeline.php b/src/Module/Conversation/Timeline.php index a53044f825..3e07820bec 100644 --- a/src/Module/Conversation/Timeline.php +++ b/src/Module/Conversation/Timeline.php @@ -7,7 +7,8 @@ namespace Friendica\Module\Conversation; -use Friendica\App; +use Friendica\App\Arguments; +use Friendica\App\BaseURL; use Friendica\App\Mode; use Friendica\BaseModule; use Friendica\Content\Conversation\Collection\Timelines; @@ -31,6 +32,8 @@ use Friendica\Model\Post; use Friendica\Model\Post\Engagement; use Friendica\Model\Post\SearchIndex; use Friendica\Module\Response; +use Friendica\Network\HTTPException\BadRequestException; +use Friendica\Network\HTTPException\ForbiddenException; use Friendica\Protocol\Activity; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; @@ -67,7 +70,7 @@ class Timeline extends BaseModule /** @var string */ protected $network; - /** @var App\Mode $mode */ + /** @var Mode $mode */ protected $mode; /** @var IHandleUserSessions */ protected $session; @@ -82,7 +85,7 @@ class Timeline extends BaseModule /** @var UserDefinedChannel */ protected $channelRepository; - public function __construct(UserDefinedChannel $channel, Mode $mode, IHandleUserSessions $session, Database $database, IManagePersonalConfigValues $pConfig, IManageConfigValues $config, ICanCache $cache, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server = [], array $parameters = []) + public function __construct(UserDefinedChannel $channel, Mode $mode, IHandleUserSessions $session, Database $database, IManagePersonalConfigValues $pConfig, IManageConfigValues $config, ICanCache $cache, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server = [], array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); @@ -98,8 +101,8 @@ class Timeline extends BaseModule /** * Computes module parameters from the request and local configuration * - * @throws HTTPException\BadRequestException - * @throws HTTPException\ForbiddenException + * @throws BadRequestException + * @throws ForbiddenException */ protected function parseRequest(array $request) { @@ -308,6 +311,8 @@ class Timeline extends BaseModule { $table = 'post-engagement'; + $condition = []; + if ($this->selectedTab == ChannelEntity::WHATSHOT) { if (!is_null($this->accountType)) { $condition = ["(`comments` > ? OR `activities` > ?) AND `contact-type` = ?", $this->getMedianComments($uid, 4), $this->getMedianActivities($uid, 4), $this->accountType]; @@ -331,11 +336,11 @@ class Timeline extends BaseModule "`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND NOT `follows`) AND (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND NOT `follows` AND `relation-thread-score` > ?) OR `owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `cid` = ? AND `relation-thread-score` > ?) OR - ((`comments` >= ? OR `activities` >= ?) AND - (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `cid` = ? AND `relation-thread-score` > ?)) OR + ((`comments` >= ? OR `activities` >= ?) AND + (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `cid` = ? AND `relation-thread-score` > ?)) OR (`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `relation-cid` = ? AND `relation-thread-score` > ?))))", $cid, $cid, $this->getMedianRelationThreadScore($cid, 4), $cid, $this->getMedianRelationThreadScore($cid, 4), - $this->getMedianComments($uid, 4), $this->getMedianActivities($uid, 4), $cid, 0, $cid, 0 + $this->getMedianComments($uid, 4), $this->getMedianActivities($uid, 4), $cid, 0, $cid, 0 ]; } elseif ($this->selectedTab == ChannelEntity::FOLLOWERS) { @@ -490,7 +495,7 @@ class Timeline extends BaseModule $placeholders = substr(str_repeat("?, ", count($search)), 0, -2); $condition = DBA::mergeConditions($condition, array_merge(["`uri-id` IN (SELECT `uri-id` FROM `post-tag` INNER JOIN `tag` ON `tag`.`id` = `post-tag`.`tid` WHERE `post-tag`.`type` = 1 AND `name` IN (" . $placeholders . "))"], $search)); } - + if (!empty($channel->excludeTags)) { $search = explode(',', mb_strtolower($channel->excludeTags)); $placeholders = substr(str_repeat("?, ", count($search)), 0, -2); @@ -500,7 +505,7 @@ class Timeline extends BaseModule if (!empty($channel->mediaType)) { $condition = DBA::mergeConditions($condition, ["`media-type` & ?", $channel->mediaType]); } - + // For "addLanguageCondition" to work, the condition must not be empty $condition = $this->addLanguageCondition($uid, $condition ?: ["true"], $channel->languages); } @@ -684,6 +689,7 @@ class Timeline extends BaseModule protected function getCommunityItems() { $items = $this->selectItems(); + $key = ''; if ($this->selectedTab == Community::LOCAL) { $maxpostperauthor = (int)$this->config->get('system', 'max_author_posts_community_page'); @@ -692,49 +698,52 @@ class Timeline extends BaseModule $maxpostperauthor = (int)$this->config->get('system', 'max_server_posts_community_page'); $key = 'author-gsid'; } else { - $maxpostperauthor = 0; + $this->setItemsSeenByCondition([ + 'unseen' => true, + 'uid' => $this->session->getLocalUserId(), + 'parent-uri-id' => array_column($items, 'uri-id') + ]); + + return $items; } - if ($maxpostperauthor != 0) { - $count = 1; - $author_posts = []; - $selected_items = []; - while (count($selected_items) < $this->itemsPerPage && ++$count < 50 && count($items) > 0) { - $maxposts = round((count($items) / $this->itemsPerPage) * $maxpostperauthor); - $minId = $items[array_key_first($items)]['received']; - $maxId = $items[array_key_last($items)]['received']; + $count = 1; + $author_posts = []; + $selected_items = []; - foreach ($items as $item) { - $author_posts[$item[$key]][$item['uri-id']] = $item['received']; + while (count($selected_items) < $this->itemsPerPage && ++$count < 50 && count($items) > 0) { + $maxposts = round((count($items) / $this->itemsPerPage) * $maxpostperauthor); + $minId = $items[array_key_first($items)]['received']; + $maxId = $items[array_key_last($items)]['received']; + + foreach ($items as $item) { + $author_posts[$item[$key]][$item['uri-id']] = $item['received']; + } + foreach ($author_posts as $posts) { + if (count($posts) <= $maxposts) { + continue; } - foreach ($author_posts as $posts) { - if (count($posts) <= $maxposts) { - continue; - } - asort($posts); - while (count($posts) > $maxposts) { - $uri_id = array_key_first($posts); - unset($posts[$uri_id]); - unset($items[$uri_id]); - } - } - $selected_items = array_merge($selected_items, $items); - - // If we're looking at a "previous page", the lookup continues forward in time because the list is - // sorted in chronologically decreasing order - if (!empty($this->minId)) { - $this->minId = $minId; - } else { - // In any other case, the lookup continues backwards in time - $this->maxId = $maxId; - } - - if (count($selected_items) < $this->itemsPerPage) { - $items = $this->selectItems(); + asort($posts); + while (count($posts) > $maxposts) { + $uri_id = array_key_first($posts); + unset($posts[$uri_id]); + unset($items[$uri_id]); } } - } else { - $selected_items = $items; + $selected_items = array_merge($selected_items, $items); + + // If we're looking at a "previous page", the lookup continues forward in time because the list is + // sorted in chronologically decreasing order + if (!empty($this->minId)) { + $this->minId = $minId; + } else { + // In any other case, the lookup continues backwards in time + $this->maxId = $maxId; + } + + if (count($selected_items) < $this->itemsPerPage) { + $items = $this->selectItems(); + } } $condition = ['unseen' => true, 'uid' => $this->session->getLocalUserId(), 'parent-uri-id' => array_column($selected_items, 'uri-id')]; @@ -808,7 +817,7 @@ class Timeline extends BaseModule } $uriids = array_keys($items); - + foreach (Post\Counts::get(['parent-uri-id' => $uriids, 'verb' => Activity::POST]) as $count) { $items[$count['parent-uri-id']]['comments'] += $count['count']; } diff --git a/src/Module/HTTPException/PageNotFound.php b/src/Module/HTTPException/PageNotFound.php index 5450250c37..ffc4957879 100644 --- a/src/Module/HTTPException/PageNotFound.php +++ b/src/Module/HTTPException/PageNotFound.php @@ -37,26 +37,13 @@ class PageNotFound extends BaseModule public function run(ModuleHTTPException $httpException, array $request = []): ResponseInterface { - /* The URL provided does not resolve to a valid module. - * - * On Dreamhost sites, quite often things go wrong for no apparent reason and they send us to '/internal_error.html'. - * We don't like doing this, but as it occasionally accounts for 10-20% or more of all site traffic - - * we are going to trap this and redirect back to the requested page. As long as you don't have a critical error on your page - * this will often succeed and eventually do the right thing. - * - * Otherwise we are going to emit a 404 not found. - */ + // The URL provided does not resolve to a valid module. $queryString = $this->server['QUERY_STRING']; // Stupid browser tried to pre-fetch our JavaScript img template. Don't log the event or return anything - just quietly exit. if (!empty($queryString) && preg_match('/{[0-9]}/', $queryString) !== 0) { System::exit(); } - if (!empty($queryString) && ($queryString === 'q=internal_error.html') && isset($dreamhost_error_hack)) { - $this->logger->info('index.php: dreamhost_error_hack invoked.', ['Original URI' => $this->server['REQUEST_URI']]); - $this->baseUrl->redirect($this->server['REQUEST_URI']); - } - $this->logger->debug('index.php: page not found.', [ 'request_uri' => $this->server['REQUEST_URI'], 'address' => $this->remoteAddress, diff --git a/src/Module/Item/Display.php b/src/Module/Item/Display.php index 7d49f4d207..2440fd549c 100644 --- a/src/Module/Item/Display.php +++ b/src/Module/Item/Display.php @@ -166,12 +166,13 @@ class Display extends BaseModule */ protected function displaySidebar(array $item) { + $author = []; $shared = $this->contentItem->getSharedPost($item, ['author-link']); - if (!empty($shared) && empty($shared['comment'])) { + if (array_key_exists('comment', $shared) && strval($shared['comment']) === '') { $author = Contact::getByURLForUser($shared['post']['author-link'], $this->session->getLocalUserId()); } - if (empty($contact)) { + if ($author === []) { $author = Contact::getById($item['author-id']); } diff --git a/src/Module/Magic.php b/src/Module/Magic.php index 24e6374f5a..c06cbd6f4e 100644 --- a/src/Module/Magic.php +++ b/src/Module/Magic.php @@ -65,31 +65,26 @@ class Magic extends BaseModule $this->logger->debug('Invoked', ['request' => $request]); - $addr = $request['addr'] ?? ''; - $bdest = $request['bdest'] ?? ''; - $dest = $request['dest'] ?? ''; - $rev = intval($request['rev'] ?? 0); + $addr = (string) $request['addr'] ?? ''; + $bdest = (string) $request['bdest'] ?? ''; + $dest = (string) $request['dest'] ?? ''; $owa = intval($request['owa'] ?? 0); - $delegate = $request['delegate'] ?? ''; // bdest is preferred as it is hex-encoded and can survive url rewrite and argument parsing - if (!empty($bdest)) { + if ($bdest !== '') { $dest = hex2bin($bdest); $this->logger->debug('bdest detected', ['dest' => $dest]); } $target = $dest ?: $addr; - if ($addr ?: $dest) { - $contact = Contact::getByURL($addr ?: $dest); + $contact = Contact::getByURL($addr ?: $dest); + if ($contact === [] && $owa === 0) { + $this->logger->info('No contact record found, no oWA, redirecting to destination.', ['request' => $request, 'server' => $_SERVER, 'dest' => $dest]); + $this->appHelper->redirect($dest); } - if (empty($contact)) { - if (!$owa) { - $this->logger->info('No contact record found, no oWA, redirecting to destination.', ['request' => $request, 'server' => $_SERVER, 'dest' => $dest]); - $this->appHelper->redirect($dest); - } - } else { + if ($contact !== []) { // Redirect if the contact is already authenticated on this site. if ($this->appHelper->getContactId() && strpos($contact['nurl'], Strings::normaliseLink($this->baseUrl)) !== false) { $this->logger->info('Contact is already authenticated, redirecting to destination.', ['dest' => $dest]); @@ -99,7 +94,7 @@ class Magic extends BaseModule $this->logger->debug('Contact found', ['url' => $contact['url']]); } - if (!$this->userSession->getLocalUserId() || !$owa) { + if (!$this->userSession->getLocalUserId() || $owa === 0) { $this->logger->notice('Not logged in or not OWA, redirecting to destination.', ['uid' => $this->userSession->getLocalUserId(), 'owa' => $owa, 'dest' => $dest]); $this->appHelper->redirect($dest); } diff --git a/src/Module/Moderation/Users/Active.php b/src/Module/Moderation/Users/Active.php index 24634157b5..b16efa46ae 100644 --- a/src/Module/Moderation/Users/Active.php +++ b/src/Module/Moderation/Users/Active.php @@ -48,15 +48,18 @@ class Active extends BaseUsers { parent::content(); - $action = $this->parameters['action'] ?? ''; - $uid = $this->parameters['uid'] ?? 0; + $action = (string) $this->parameters['action'] ?? ''; + $uid = (int) $this->parameters['uid'] ?? 0; - if ($uid) { - $user = User::getById($uid, ['username', 'blocked']); - if (!$user) { - $this->systemMessages->addNotice($this->t('User not found')); - $this->baseUrl->redirect('moderation/users'); - } + if ($uid === 0) { + $this->systemMessages->addNotice($this->t('User not found')); + $this->baseUrl->redirect('moderation/users'); + } + + $user = User::getById($uid, ['username', 'blocked']); + if (!is_array($user)) { + $this->systemMessages->addNotice($this->t('User not found')); + $this->baseUrl->redirect('moderation/users'); } switch ($action) { diff --git a/src/Module/Moderation/Users/Blocked.php b/src/Module/Moderation/Users/Blocked.php index fd8d25dfbe..6eeb11549f 100644 --- a/src/Module/Moderation/Users/Blocked.php +++ b/src/Module/Moderation/Users/Blocked.php @@ -48,15 +48,18 @@ class Blocked extends BaseUsers { parent::content(); - $action = $this->parameters['action'] ?? ''; - $uid = $this->parameters['uid'] ?? 0; + $action = (string) $this->parameters['action'] ?? ''; + $uid = (int) $this->parameters['uid'] ?? 0; - if ($uid) { - $user = User::getById($uid, ['username', 'blocked']); - if (!$user) { - $this->systemMessages->addNotice($this->t('User not found')); - $this->baseUrl->redirect('moderation/users'); - } + if ($uid === 0) { + $this->systemMessages->addNotice($this->t('User not found')); + $this->baseUrl->redirect('moderation/users'); + } + + $user = User::getById($uid, ['username', 'blocked']); + if (!is_array($user)) { + $this->systemMessages->addNotice($this->t('User not found')); + $this->baseUrl->redirect('moderation/users'); } switch ($action) { diff --git a/src/Module/Moderation/Users/Index.php b/src/Module/Moderation/Users/Index.php index 6553bcc7e3..1a7d8f1721 100644 --- a/src/Module/Moderation/Users/Index.php +++ b/src/Module/Moderation/Users/Index.php @@ -55,15 +55,18 @@ class Index extends BaseUsers { parent::content(); - $action = $this->parameters['action'] ?? ''; - $uid = $this->parameters['uid'] ?? 0; + $action = (string) $this->parameters['action'] ?? ''; + $uid = (int) $this->parameters['uid'] ?? 0; - if ($uid) { - $user = User::getById($uid, ['username', 'blocked']); - if (!$user) { - $this->systemMessages->addNotice($this->t('User not found')); - $this->baseUrl->redirect('moderation/users'); - } + if ($uid === 0) { + $this->systemMessages->addNotice($this->t('User not found')); + $this->baseUrl->redirect('moderation/users'); + } + + $user = User::getById($uid, ['username', 'blocked']); + if (!is_array($user)) { + $this->systemMessages->addNotice($this->t('User not found')); + $this->baseUrl->redirect('moderation/users'); } switch ($action) { diff --git a/src/Module/OAuth/Token.php b/src/Module/OAuth/Token.php index 47efa266e6..9ce760790b 100644 --- a/src/Module/OAuth/Token.php +++ b/src/Module/OAuth/Token.php @@ -66,32 +66,52 @@ class Token extends BaseApi $this->logAndJsonError(401, $this->errorFactory->Unauthorized('invalid_client', $this->t('Invalid data or unknown client'))); } - if ($request['grant_type'] == 'client_credentials') { - // the "client_credentials" are used as a token for the application itself. - // see https://aaronparecki.com/oauth-2-simplified/#client-credentials - $token = OAuth::createTokenForUser($application, 0, ''); - $me = null; - } elseif ($request['grant_type'] == 'authorization_code') { - // For security reasons only allow freshly created tokens - $redirect_uri = strtok($request['redirect_uri'],'?'); - $condition = [ - "`redirect_uri` LIKE ? AND `id` = ? AND `code` = ? AND `created_at` > ?", - $redirect_uri, $application['id'], $request['code'], DateTimeFormat::utc('now - 5 minutes') - ]; + $grant_type = (string) $request['grant_type']; - $token = DBA::selectFirst('application-view', ['access_token', 'created_at', 'uid'], $condition); - if (!DBA::isResult($token)) { - $this->logger->notice('Token not found or outdated', $condition); - $this->logAndJsonError(401, $this->errorFactory->Unauthorized()); - } - $owner = User::getOwnerDataById($token['uid']); - $me = $owner['url']; - } else { + if (!in_array($grant_type, ['client_credentials', 'authorization_code'])) { Logger::warning('Unsupported or missing grant type', ['request' => $_REQUEST]); $this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity($this->t('Unsupported or missing grant type'))); } - $object = new \Friendica\Object\Api\Mastodon\Token($token['access_token'], 'Bearer', $application['scopes'], $token['created_at'], $me); + if ($grant_type === 'client_credentials') { + // the "client_credentials" are used as a token for the application itself. + // see https://aaronparecki.com/oauth-2-simplified/#client-credentials + $token = OAuth::createTokenForUser($application, 0, ''); + + $object = new \Friendica\Object\Api\Mastodon\Token( + $token['access_token'], + 'Bearer', + $application['scopes'], + $token['created_at'], + null + ); + + $this->jsonExit($object->toArray()); + } + + // now check for $grant_type === 'authorization_code' + // For security reasons only allow freshly created tokens + $redirect_uri = strtok($request['redirect_uri'],'?'); + $condition = [ + "`redirect_uri` LIKE ? AND `id` = ? AND `code` = ? AND `created_at` > ?", + $redirect_uri, $application['id'], $request['code'], DateTimeFormat::utc('now - 5 minutes') + ]; + + $token = DBA::selectFirst('application-view', ['access_token', 'created_at', 'uid'], $condition); + if (!DBA::isResult($token)) { + $this->logger->notice('Token not found or outdated', $condition); + $this->logAndJsonError(401, $this->errorFactory->Unauthorized()); + } + + $owner = User::getOwnerDataById($token['uid']); + + $object = new \Friendica\Object\Api\Mastodon\Token( + $token['access_token'], + 'Bearer', + $application['scopes'], + $token['created_at'], + $owner['url'] + ); $this->jsonExit($object->toArray()); } diff --git a/src/Module/Photo.php b/src/Module/Photo.php index c2b13e1386..30e6d57672 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -142,7 +142,9 @@ class Photo extends BaseApi $cacheable = ($photo['allow_cid'] . $photo['allow_gid'] . $photo['deny_cid'] . $photo['deny_gid'] === '') && (isset($photo['cacheable']) ? $photo['cacheable'] : true); - $stamp = microtime(true); + $stamp = microtime(true); + $imgdata = ''; + $mimetype = false; if (empty($request['blur']) || empty($photo['blurhash'])) { $imgdata = MPhoto::getImageDataForPhoto($photo); @@ -150,7 +152,9 @@ class Photo extends BaseApi } if (empty($imgdata) && empty($photo['blurhash'])) { throw new HTTPException\NotFoundException(); - } elseif (empty($imgdata) && !empty($photo['blurhash'])) { + } + + if (empty($imgdata) && !empty($photo['blurhash'])) { $image = new Image('', image_type_to_mime_type(IMAGETYPE_WEBP)); $image->getFromBlurHash($photo['blurhash'], $photo['width'], $photo['height']); $imgdata = $image->asString(); @@ -376,6 +380,9 @@ class Photo extends BaseApi Logger::debug('Expected Content-Type', ['mime' => $mimetext, 'url' => $url]); } } + + $url = ''; + if (empty($mimetext) && !empty($contact['blurhash'])) { $image = new Image('', image_type_to_mime_type(IMAGETYPE_WEBP)); $image->getFromBlurHash($contact['blurhash'], $customsize, $customsize); diff --git a/src/Module/Post/Tag/Remove.php b/src/Module/Post/Tag/Remove.php index 3073032336..e5652c79a8 100644 --- a/src/Module/Post/Tag/Remove.php +++ b/src/Module/Post/Tag/Remove.php @@ -77,10 +77,11 @@ class Remove extends \Friendica\BaseModule $tag_text = Tag::getCSVByURIId($item['uri-id']); - $tags = explode(',', $tag_text); - if (empty($tags)) { + if ($tag_text === '') { $this->baseUrl->redirect($returnUrl); } + + $tags = explode(',', $tag_text); $tag_checkboxes = array_map(function ($tag_text) { return ['tag[' . bin2hex($tag_text) . ']', BBCode::toPlaintext($tag_text)]; diff --git a/src/Module/Profile/Photos.php b/src/Module/Profile/Photos.php index 19adf56354..a377cd6dc3 100644 --- a/src/Module/Profile/Photos.php +++ b/src/Module/Profile/Photos.php @@ -127,7 +127,11 @@ class Photos extends \Friendica\Module\BaseProfile $visible = 0; } - $ret = ['src' => '', 'filename' => '', 'filesize' => 0, 'type' => '']; + $ret = ['src' => '', 'filename' => '', 'filesize' => 0, 'type' => '']; + $src = null; + $filename = ''; + $filesize = 0; + $type = ''; Hook::callAll('photo_post_file', $ret); @@ -167,7 +171,11 @@ class Photos extends \Friendica\Module\BaseProfile $this->systemMessages->addNotice($this->t('Server can\'t accept new file upload at this time, please contact your administrator')); break; } - @unlink($src); + + if ($src !== null) { + @unlink($src); + } + $foo = 0; Hook::callAll('photo_post_end', $foo); return; diff --git a/src/Module/Security/TwoFactor/Trust.php b/src/Module/Security/TwoFactor/Trust.php index 5620cb9b94..f5ce8c930f 100644 --- a/src/Module/Security/TwoFactor/Trust.php +++ b/src/Module/Security/TwoFactor/Trust.php @@ -96,7 +96,7 @@ class Trust extends BaseModule // exception wanted! throw $e; } catch (\Exception $e) { - $this->logger->warning('Unexpected error during authentication.', ['user' => $this->session->getLocalUserId(), 'exception' => $exception]); + $this->logger->warning('Unexpected error during authentication.', ['user' => $this->session->getLocalUserId(), 'exception' => $e]); } } } diff --git a/src/Module/Settings/Profile/Photo/Crop.php b/src/Module/Settings/Profile/Photo/Crop.php index 0853b2ae6d..53486fe001 100644 --- a/src/Module/Settings/Profile/Photo/Crop.php +++ b/src/Module/Settings/Profile/Photo/Crop.php @@ -46,9 +46,6 @@ class Crop extends BaseSettings $base_image = Photo::selectFirst([], ['resource-id' => $resource_id, 'uid' => DI::userSession()->getLocalUserId(), 'scale' => $scale]); if (DBA::isResult($base_image)) { $Image = Photo::getImageForPhoto($base_image); - if (empty($Image)) { - throw new HTTPException\InternalServerErrorException(); - } if ($Image->isValid()) { // If setting for the default profile, unset the profile photo flag from any other photos I own @@ -185,7 +182,7 @@ class Crop extends BaseSettings } $Image = Photo::getImageForPhoto($photos[0]); - if (empty($Image)) { + if (!$Image->isValid()) { throw new HTTPException\InternalServerErrorException(); } diff --git a/src/Module/Settings/RemoveMe.php b/src/Module/Settings/RemoveMe.php index 59165bccba..cae57d2f0f 100644 --- a/src/Module/Settings/RemoveMe.php +++ b/src/Module/Settings/RemoveMe.php @@ -92,8 +92,6 @@ class RemoveMe extends BaseSettings $this->baseUrl->redirect(); } catch (\RuntimeException $e) { $this->systemMessages->addNotice($e->getMessage()); - } finally { - return; } } diff --git a/src/Module/Xrd.php b/src/Module/Xrd.php index 3e55f0571b..39b4e2538c 100644 --- a/src/Module/Xrd.php +++ b/src/Module/Xrd.php @@ -64,6 +64,8 @@ class Xrd extends BaseModule header('Vary: Accept', false); + $alias = ''; + if ($name == User::getActorName()) { $owner = User::getSystemAccount(); if (empty($owner)) { @@ -108,7 +110,7 @@ class Xrd extends BaseModule $parts[] = current(explode(';', $part)); } - if (empty($parts)) { + if ($parts === []) { return $default; } elseif (in_array('application/jrd+json', $parts) && !in_array('application/xrd+xml', $parts)) { return Response::TYPE_JSON; diff --git a/src/Navigation/Notifications/ValueObject/FormattedNotify.php b/src/Navigation/Notifications/ValueObject/FormattedNotify.php index e8abfe283a..d92d39e426 100644 --- a/src/Navigation/Notifications/ValueObject/FormattedNotify.php +++ b/src/Navigation/Notifications/ValueObject/FormattedNotify.php @@ -41,13 +41,13 @@ class FormattedNotify extends BaseDataTransferObject public function __construct(string $label, string $link, string $image, string $url, string $text, string $when, string $ago, bool $seen) { - $this->label = $label ?? ''; - $this->link = $link ?? ''; - $this->image = $image ?? ''; - $this->url = $url ?? ''; - $this->text = $text ?? ''; - $this->when = $when ?? ''; - $this->ago = $ago ?? ''; - $this->seen = $seen ?? false; + $this->label = $label; + $this->link = $link; + $this->image = $image; + $this->url = $url; + $this->text = $text; + $this->when = $when; + $this->ago = $ago; + $this->seen = $seen; } } diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 99fb9ed211..d189071162 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -220,14 +220,16 @@ class Probe Logger::notice('Got exception', ['code' => $th->getCode(), 'message' => $th->getMessage()]); return []; } + $ssl_connection_error = ($curlResult->getErrorNumber() == CURLE_COULDNT_CONNECT) || ($curlResult->getReturnCode() == 0); + + $host_url = $host; + if ($curlResult->isSuccess()) { $xml = $curlResult->getBodyString(); $xrd = XML::parseString($xml, true); if (!empty($url)) { $host_url = 'https://' . $host; - } else { - $host_url = $host; } } elseif ($curlResult->isTimeout()) { Logger::info('Probing timeout', ['url' => $ssl_url]); @@ -550,6 +552,7 @@ class Probe public static function getWebfingerArray(string $uri): array { $parts = parse_url($uri); + $lrdd = []; if (!empty($parts['scheme']) && !empty($parts['host'])) { $host = $parts['host']; @@ -562,8 +565,11 @@ class Probe $nick = ''; $addr = ''; - $path_parts = explode('/', trim($parts['path'] ?? '', '/')); - if (!empty($path_parts)) { + $path_parts = []; + + if (array_key_exists('path', $parts) && trim(strval($parts['path']), '/') !== '') { + $path_parts = explode('/', trim($parts['path'], '/')); + $nick = ltrim(end($path_parts), '@'); $addr = $nick . '@' . $host; } @@ -574,7 +580,7 @@ class Probe } if (empty($webfinger) && empty($lrdd)) { - while (empty($lrdd) && empty($webfinger) && (sizeof($path_parts) > 1)) { + while (empty($lrdd) && empty($webfinger) && (count($path_parts) > 1)) { $host .= '/' . array_shift($path_parts); $baseurl = $parts['scheme'] . '://' . $host; @@ -668,8 +674,10 @@ class Probe return null; } + $detected = ''; + // First try the address because this is the primary purpose of webfinger - if (!empty($addr)) { + if ($addr !== '') { $detected = $addr; $path = str_replace('{uri}', urlencode('acct:' . $addr), $template); $webfinger = self::webfinger($path, $type); @@ -823,13 +831,15 @@ class Probe */ private static function zot(array $webfinger, array $data): array { + $zot_url = ''; + foreach ($webfinger['links'] as $link) { if (($link['rel'] == 'http://purl.org/zot/protocol/6.0') && !empty($link['href'])) { $zot_url = $link['href']; } } - if (empty($zot_url)) { + if ($zot_url === '') { return $data; } @@ -871,7 +881,7 @@ class Probe $data['url'] = $link['href']; } } - + $data = self::pollZot($zot_url, $data); if (!empty($data['url']) && !empty($webfinger['aliases']) && is_array($webfinger['aliases'])) { @@ -1429,7 +1439,7 @@ class Probe && !empty($data['guid']) && !empty($data['baseurl']) && !empty($data['pubkey']) - && !empty($hcard_url) + && $hcard_url !== '' ) { $data['network'] = Protocol::DIASPORA; $data['manually-approve'] = false; @@ -1776,7 +1786,7 @@ class Probe $password = ''; openssl_private_decrypt(hex2bin($mailacct['pass']), $password, $user['prvkey']); $mbox = Email::connect($mailbox, $mailacct['user'], $password); - if (!$mbox) { + if ($mbox === false) { return []; } @@ -1828,7 +1838,7 @@ class Probe } } - if (!empty($mbox)) { + if ($mbox !== false) { imap_close($mbox); } diff --git a/src/Object/Api/Twitter/User.php b/src/Object/Api/Twitter/User.php index ba376263c1..151a968bff 100644 --- a/src/Object/Api/Twitter/User.php +++ b/src/Object/Api/Twitter/User.php @@ -62,7 +62,7 @@ class User extends BaseDataTransferObject protected $default_profile; /** @var bool */ protected $default_profile_image; - /** @var Status */ + /** @var array */ protected $status; /** @var array */ protected $withheld_in_countries; @@ -117,12 +117,11 @@ class User extends BaseDataTransferObject * @param array $publicContact Full contact table record with uid = 0 * @param array $apcontact Optional full apcontact table record * @param array $userContact Optional full contact table record with uid != 0 - * @param null $status * @param bool $include_user_entities Whether to add the entities property * * @throws InternalServerErrorException */ - public function __construct(array $publicContact, array $apcontact = [], array $userContact = [], $status = null, bool $include_user_entities = true) + public function __construct(array $publicContact, array $apcontact = [], array $userContact = [], ?Status $status = null, bool $include_user_entities = true) { $uid = $userContact['uid'] ?? 0; @@ -156,10 +155,10 @@ class User extends BaseDataTransferObject $this->default_profile = false; $this->default_profile_image = false; - if (!empty($status)) { - $this->status = $status; - } else { + if ($status === null) { unset($this->status); + } else { + $this->status = $status->toArray(); } // Unused optional fields diff --git a/src/Object/Image.php b/src/Object/Image.php index 256de2f284..8a06b37fbd 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -771,7 +771,7 @@ class Image public function getBlurHash(): string { $image = New Image($this->asString(), $this->getType(), $this->filename, false); - if (empty($image) || !$this->isValid()) { + if (!$this->isValid()) { return ''; } @@ -827,6 +827,7 @@ class Image { $scaled = Images::getScalingDimensions($width, $height, 90); $pixels = Blurhash::decode($blurhash, $scaled['width'], $scaled['height']); + $draw = null; if ($this->isImagick()) { $this->image = new Imagick(); @@ -839,7 +840,7 @@ class Image for ($y = 0; $y < $scaled['height']; ++$y) { for ($x = 0; $x < $scaled['width']; ++$x) { [$r, $g, $b] = $pixels[$y][$x]; - if ($this->isImagick()) { + if ($draw !== null) { $draw->setFillColor("rgb($r, $g, $b)"); $draw->point($x, $y); } else { @@ -848,7 +849,7 @@ class Image } } - if ($this->isImagick()) { + if ($draw !== null) { $this->image->drawImage($draw); $this->width = $this->image->getImageWidth(); $this->height = $this->image->getImageHeight(); diff --git a/src/Protocol/ActivityPub/ClientToServer.php b/src/Protocol/ActivityPub/ClientToServer.php index e668b77e36..4f3a8268b0 100644 --- a/src/Protocol/ActivityPub/ClientToServer.php +++ b/src/Protocol/ActivityPub/ClientToServer.php @@ -323,7 +323,7 @@ class ClientToServer $requester_id = Contact::getIdForURL($requester, $owner['uid']); if (!empty($requester_id)) { $permissionSets = DI::permissionSet()->selectByContactId($requester_id, $owner['uid']); - if (!empty($permissionSets)) { + if (count($permissionSets) > 0) { $condition = ['psid' => array_merge($permissionSets->column('id'), [DI::permissionSet()->selectPublicForUser($owner['uid'])])]; } diff --git a/src/Protocol/ActivityPub/Delivery.php b/src/Protocol/ActivityPub/Delivery.php index 7a7d484b8d..fe7b0a76ed 100644 --- a/src/Protocol/ActivityPub/Delivery.php +++ b/src/Protocol/ActivityPub/Delivery.php @@ -42,6 +42,8 @@ class Delivery continue; } + $result = []; + if (!$serverfail) { $result = self::deliverToInbox($post['command'], 0, $inbox, $owner, $post['receivers'], $post['uri-id']); @@ -121,11 +123,12 @@ class Delivery $serverfail = $response->isTimeout(); } catch (\Throwable $th) { Logger::notice('Got exception', ['code' => $th->getCode(), 'message' => $th->getMessage()]); + $response = null; $success = false; $serverfail = true; } $runtime = microtime(true) - $timestamp; - if (!$success) { + if ($success === false) { // 5xx errors are problems on the server. We don't need to continue delivery then. if (!$serverfail && ($response->getReturnCode() >= 500) && ($response->getReturnCode() <= 599)) { $serverfail = true; diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 21be0f6379..7eeae65ae5 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -520,7 +520,7 @@ class Processor if (!DI::config()->get('system', 'decoupled_receiver')) { return; } - + $replies = [$item['thr-parent']]; if (!empty($item['parent-uri'])) { $replies[] = $item['parent-uri']; @@ -561,7 +561,7 @@ class Processor if (in_array($activity['reply-to-id'], $activity['children'] ?? [])) { Logger::notice('reply-to-id is already in the list of children', ['id' => $activity['reply-to-id'], 'children' => $activity['children'], 'depth' => count($activity['children'])]); return ''; - } + } self::addActivityId($activity['reply-to-id']); @@ -1361,6 +1361,7 @@ class Processor } $hash = substr($tag['name'], 0, 1); + $type = 0; if ($tag['type'] == 'Mention') { if (in_array($hash, [Tag::TAG_CHARACTER[Tag::MENTION], @@ -1616,7 +1617,7 @@ class Processor return []; } - if (!self::isValidObject($object, $url)) { + if (!self::isValidObject($object)) { return []; } @@ -1657,10 +1658,6 @@ class Processor return ''; } - if (empty($curlResult)) { - return ''; - } - $body = $curlResult->getBodyString(); if (!$curlResult->isSuccess() || empty($body)) { if (in_array($curlResult->getReturnCode(), [403, 404, 406, 410])) { @@ -1680,7 +1677,7 @@ class Processor return null; } - if (!self::isValidObject($object, $url)) { + if (!self::isValidObject($object)) { return null; } @@ -1747,7 +1744,7 @@ class Processor $ldactivity['children'] = $child['children'] ?? []; $ldactivity['callstack'] = $child['callstack'] ?? []; // This check is mostly superfluous, since there are similar checks before. This covers the case, when the fetched id doesn't match the url - if (in_array($activity['id'], $ldactivity['children'])) { + if (in_array($activity['id'], $ldactivity['children'])) { Logger::notice('Fetched id is already in the list of children. It will not be processed.', ['id' => $activity['id'], 'children' => $ldactivity['children'], 'depth' => count($ldactivity['children'])]); return null; } @@ -1829,6 +1826,8 @@ class Processor Logger::notice('Fetch replies - start', ['replies' => $url, 'callstack' => $child['callstack'], 'system' => $callstack]); $fetched = 0; foreach ($replies as $reply) { + $id = ''; + if (is_array($reply)) { $ldobject = JsonLD::compact($reply); $id = JsonLD::fetchElement($ldobject, '@id'); @@ -2120,9 +2119,8 @@ class Processor self::transmitPendingEvents($cid, $owner['uid']); } - if (empty($contact)) { - Contact::update(['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]); - } + Contact::update(['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]); + Logger::notice('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']); Queue::remove($activity); } @@ -2334,9 +2332,10 @@ class Processor */ public static function acceptFollowUser(array $activity) { + $check_id = false; + if (!empty($activity['object_actor'])) { $uid = User::getIdForURL($activity['object_actor']); - $check_id = false; } elseif (!empty($activity['receiver']) && (count($activity['receiver']) == 1)) { $uid = array_shift($activity['receiver']); $check_id = true; diff --git a/src/Protocol/ActivityPub/Queue.php b/src/Protocol/ActivityPub/Queue.php index 059ba1a388..8d78620c3e 100644 --- a/src/Protocol/ActivityPub/Queue.php +++ b/src/Protocol/ActivityPub/Queue.php @@ -414,7 +414,7 @@ class Queue { $entries = DBA::select('inbox-entry', ['id'], ["NOT `trust` AND `wid` IS NULL"], ['order' => ['id' => true]]); while ($entry = DBA::fetch($entries)) { - $data = self::reprepareActivityById($entry['id'], false); + $data = self::reprepareActivityById($entry['id']); if ($data['trust']) { DBA::update('inbox-entry', ['trust' => true], ['id' => $entry['id']]); } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 7512e6179c..3e8ad6ff8d 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -304,9 +304,10 @@ class Receiver */ public static function prepareObjectData(array $activity, int $uid, bool $push, bool &$trust_source, string $original_actor = ''): array { - $id = JsonLD::fetchElement($activity, '@id'); - $type = JsonLD::fetchElement($activity, '@type'); - $object_id = JsonLD::fetchElement($activity, 'as:object', '@id'); + $id = JsonLD::fetchElement($activity, '@id'); + $type = JsonLD::fetchElement($activity, '@type'); + $object_id = JsonLD::fetchElement($activity, 'as:object', '@id'); + $object_type = ''; if (!empty($object_id) && in_array($type, ['as:Create', 'as:Update'])) { $fetch_id = $object_id; @@ -618,7 +619,7 @@ class Receiver } $actor = JsonLD::fetchElement($activity, 'as:actor', '@id'); - if (empty($actor)) { + if ($actor === null || $actor === '') { Logger::info('Empty actor', ['activity' => $activity]); return true; } @@ -630,7 +631,7 @@ class Receiver $id = JsonLD::fetchElement($activity, '@id'); $object_id = JsonLD::fetchElement($activity, 'as:object', '@id'); - if (!empty($published) && !empty($object_id) && in_array($type, ['as:Create', 'as:Update']) && in_array($object_type, self::CONTENT_TYPES) + if (!empty($published) && $object_id !== null && in_array($type, ['as:Create', 'as:Update']) && in_array($object_type, self::CONTENT_TYPES) && ($push || ($completion != self::COMPLETION_MANUAL)) && DI::contentItem()->isTooOld($published) && !Post::exists(['uri' => $object_id])) { Logger::debug('Activity is too old. It will not be processed', ['push' => $push, 'completion' => $completion, 'type' => $type, 'object-type' => $object_type, 'published' => $published, 'id' => $id, 'object-id' => $object_id]); return true; @@ -641,7 +642,7 @@ class Receiver // Test the provided signatures against the actor and "attributedTo" if ($trust_source) { - if (!empty($attributed_to) && !empty($actor)) { + if ($attributed_to !== false && $attributed_to !== '') { $trust_source = (in_array($actor, $signer) && in_array($attributed_to, $signer)); } else { $trust_source = in_array($actor, $signer); @@ -1185,6 +1186,8 @@ class Receiver } $parent_followers = ''; + $parent_profile = []; + $parent = Post::selectFirstPost(['parent-author-link'], ['uri' => $reply]); if (!empty($parent['parent-author-link'])) { $parent_profile = APContact::getByURL($parent['parent-author-link']); diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 883a97c10a..0aeccc3867 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -573,11 +573,12 @@ class Transmitter $exclusive = false; $mention = false; $audience = []; + $owner = false; // Check if we should always deliver our stuff via BCC if (!empty($item['uid'])) { $owner = User::getOwnerDataById($item['uid']); - if (!empty($owner)) { + if (is_array($owner)) { $always_bcc = $owner['hide-friends']; $is_group = ($owner['account-type'] == User::ACCOUNT_TYPE_COMMUNITY); @@ -1399,7 +1400,7 @@ class Transmitter $type = self::getTypeOfItem($item); if (!$object_mode) { - $data = ['@context' => $context ?? ActivityPub::CONTEXT]; + $data = ['@context' => ActivityPub::CONTEXT]; if ($item['deleted'] && ($item['gravity'] == Item::GRAVITY_ACTIVITY)) { $type = 'Undo'; @@ -1750,6 +1751,7 @@ class Transmitter $title = $item['title']; $summary = $item['content-warning'] ?: BBCode::toPlaintext(BBCode::getAbstract($item['body'], Protocol::ACTIVITYPUB)); + $type = ''; if ($item['event-type'] == 'event') { $type = 'Event'; diff --git a/src/Protocol/Delivery.php b/src/Protocol/Delivery.php index 9f87536775..c18de6264c 100644 --- a/src/Protocol/Delivery.php +++ b/src/Protocol/Delivery.php @@ -12,7 +12,6 @@ use Friendica\Contact\FriendSuggest\Exception\FriendSuggestNotFoundException; use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Worker; -use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; @@ -48,6 +47,8 @@ class Delivery $top_level = false; $followup = false; $public_message = false; + $parent = false; + $thr_parent = false; $items = []; if ($cmd == self::MAIL) { diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 74963025e9..2e5b7bfdd0 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -623,22 +623,21 @@ class Diaspora */ private static function validPosting(array $msg) { - $data = XML::parseString($msg['message']); + $element = XML::parseString($msg['message']); - if (!is_object($data)) { + if (!is_object($element)) { Logger::info('No valid XML', ['message' => $msg['message']]); return false; } + $oldXML = false; + // Is this the new or the old version? - if ($data->getName() == 'XML') { + if ($element->getName() === 'XML') { $oldXML = true; - foreach ($data->post->children() as $child) { + foreach ($element->post->children() as $child) { $element = $child; } - } else { - $oldXML = false; - $element = $data; } $type = $element->getName(); @@ -1460,7 +1459,7 @@ class Diaspora */ foreach ($matches as $match) { - if (empty($match)) { + if ($match === '') { continue; } @@ -3030,7 +3029,7 @@ class Diaspora // The "addr" field should always be filled. // If this isn't the case, it will raise a notice some lines later. // And in the log we will see where it came from, and we can handle it there. - Logger::notice('Empty addr', ['contact' => $contact ?? []]); + Logger::notice('Empty addr', ['contact' => $contact]); } $envelope = self::buildMessage($msg, $owner, $contact, $owner['uprvkey'], $pubkey ?? '', $public_batch); @@ -3655,6 +3654,8 @@ class Diaspora */ public static function sendFollowup(array $item, array $owner, array $contact, bool $public_batch = false): int { + $type = ''; + if (in_array($item['verb'], [Activity::ATTEND, Activity::ATTENDNO, Activity::ATTENDMAYBE])) { $message = self::constructAttend($item, $owner); $type = 'event_participation'; diff --git a/src/Protocol/Email.php b/src/Protocol/Email.php index 0c83a91089..765a474773 100644 --- a/src/Protocol/Email.php +++ b/src/Protocol/Email.php @@ -25,7 +25,7 @@ class Email * @param string $mailbox The mailbox name * @param string $username The username * @param string $password The password - * @return Connection|resource|bool + * @return Connection|false * @throws \Exception */ public static function connect(string $mailbox, string $username, string $password) diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index 62d58a0ec8..82227b3b47 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -736,7 +736,7 @@ class Feed $publish_at = date(DateTimeFormat::MYSQL, $publish_time); if (Post\Delayed::add($posting['item']['uri'], $posting['item'], $posting['notify'], Post\Delayed::PREPARED, $publish_at, $posting['taglist'], $posting['attachments'])) { - DI::pConfig()->set($item['uid'], 'system', 'last_publish', $publish_time); + DI::pConfig()->set($posting['item']['uid'], 'system', 'last_publish', $publish_time); } } } @@ -1407,7 +1407,7 @@ class Feed $contact = Contact::getByURL($item['author-link']) ?: $owner; $contact['nickname'] = $contact['nickname'] ?? $contact['nick']; - $author = self::addAuthor($doc, $contact, false); + $author = self::addAuthor($doc, $contact); $entry->appendChild($author); } } else { diff --git a/src/Util/EMailer/NotifyMailBuilder.php b/src/Util/EMailer/NotifyMailBuilder.php index 57fe544127..d53715a83e 100644 --- a/src/Util/EMailer/NotifyMailBuilder.php +++ b/src/Util/EMailer/NotifyMailBuilder.php @@ -109,9 +109,9 @@ class NotifyMailBuilder extends MailBuilder public function withPhoto(string $image, string $link, string $name) { $this->photo = [ - 'image' => $image ?? '', - 'link' => $link ?? '', - 'name' => $name ?? '', + 'image' => $image, + 'link' => $link, + 'name' => $name, ]; return $this; diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index 0fdfccf330..de775a17ec 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -480,10 +480,6 @@ class HTTPSignature return []; } - if (empty($curlResult)) { - return []; - } - if (!$curlResult->isSuccess() || empty($curlResult->getBodyString())) { Logger::debug('Fetching was unsuccessful', ['url' => $request, 'return-code' => $curlResult->getReturnCode(), 'error-number' => $curlResult->getErrorNumber(), 'error' => $curlResult->getError()]); return []; diff --git a/src/Util/Images.php b/src/Util/Images.php index 675f034b9c..62e22ef2f8 100644 --- a/src/Util/Images.php +++ b/src/Util/Images.php @@ -308,13 +308,13 @@ class Images $data = DI::cache()->get($cacheKey); - if (empty($data) || !is_array($data)) { + if (!is_array($data)) { $data = self::getInfoFromURL($url, $ocr); DI::cache()->set($cacheKey, $data); } - return $data ?? []; + return $data; } /** @@ -370,7 +370,7 @@ class Images if ($image->isValid()) { $data['blurhash'] = $image->getBlurHash(); - + if ($ocr) { $media = ['img_str' => $img_str]; Hook::callAll('ocr-detection', $media); diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index 1ee5c0920e..39c368818c 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -286,7 +286,7 @@ class JsonLD * @param $type * @param $type_value * - * @return string fetched element + * @return string|null fetched element */ public static function fetchElement($array, $element, $key = '@id', $type = null, $type_value = null) { diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 4238499bab..d0377e02ac 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -1087,7 +1087,7 @@ class ParseUrl $content = JsonLD::fetchElement($jsonld, 'logo', 'url', '@type', 'ImageObject'); if (!empty($content) && is_string($content)) { $jsonldinfo['publisher_img'] = trim($content); - } elseif (!empty($content) && is_array($content)) { + } elseif (is_array($content) && array_key_exists(0, $content)) { $jsonldinfo['publisher_img'] = trim($content[0]); } diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index c7b704bf63..c9b16717b7 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -220,7 +220,7 @@ class OnePoll Logger::info('Mail is enabled'); - $mbox = null; + $mbox = false; $user = DBA::selectFirst('user', ['prvkey'], ['uid' => $importer_uid]); $condition = ["`server` != ? AND `user` != ? AND `port` != ? AND `uid` = ?", '', '', 0, $importer_uid]; @@ -232,17 +232,18 @@ class OnePoll $mbox = Email::connect($mailbox, $mailconf['user'], $password); unset($password); Logger::notice('Connect', ['user' => $mailconf['user']]); - if ($mbox) { - $fields = ['last_check' => $updated]; - DBA::update('mailacct', $fields, ['id' => $mailconf['id']]); - Logger::notice('Connected', ['user' => $mailconf['user']]); - } else { + + if ($mbox === false) { Logger::notice('Connection error', ['user' => $mailconf['user'], 'error' => imap_errors()]); return false; } + + $fields = ['last_check' => $updated]; + DBA::update('mailacct', $fields, ['id' => $mailconf['id']]); + Logger::notice('Connected', ['user' => $mailconf['user']]); } - if (empty($mbox)) { + if ($mbox === false) { return false; } diff --git a/static/platforms.config.php b/static/platforms.config.php index a04b2c07d7..cfb5b16c0c 100644 --- a/static/platforms.config.php +++ b/static/platforms.config.php @@ -129,3 +129,10 @@ $zap_platforms = [ 'hubzilla' => 'hubzilla', 'osada' => 'osada', ]; + +return [ + 'ap_platforms' => $ap_platforms, + 'dfrn_platforms' => $dfrn_platforms, + 'zap_platforms' => $zap_platforms, + 'platforms' => $platforms, +]; diff --git a/tests/src/Content/PlaintextTest.php b/tests/src/Content/Text/PlaintextTest.php similarity index 63% rename from tests/src/Content/PlaintextTest.php rename to tests/src/Content/Text/PlaintextTest.php index 96830254f9..5c5877ac75 100644 --- a/tests/src/Content/PlaintextTest.php +++ b/tests/src/Content/Text/PlaintextTest.php @@ -5,7 +5,7 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -namespace Friendica\Test\src\Content; +namespace Friendica\Test\src\Content\Text; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\Plaintext; @@ -32,17 +32,17 @@ class PlaintextTest extends FixtureTest 'Ich ignoriere auch Anfragen, wenn sie von Accounts kommen, die ggf. tausenden von anderen Accounts folgen, da ich davon ausgehe, (5/6)', 'dass da niemand ernsthaft so vielen Accounts folgen kann. (6/6)' ], - 'test-2' => [ - 'data' => 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.', - 'expected' => [ - 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, (1/6)', - 'sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. (2/6)', - 'Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. (3/6)', - 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, (4/6)', - 'sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. (5/6)', - 'Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. (6/6)' - ], - ] + ], + 'test-2' => [ + 'data' => 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.', + 'expected' => [ + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, (1/6)', + 'sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. (2/6)', + 'Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. (3/6)', + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, (4/6)', + 'sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. (5/6)', + 'Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. (6/6)' + ], ], ]; } diff --git a/view/theme/duepuntozero/config.php b/view/theme/duepuntozero/config.php index 1c70b4414c..35629a9143 100644 --- a/view/theme/duepuntozero/config.php +++ b/view/theme/duepuntozero/config.php @@ -42,7 +42,7 @@ function theme_admin(AppHelper $appHelper) return clean_form($appHelper, $colorset, $user); } -function theme_admin_post(AppHelper $appHelper) +function theme_admin_post() { if (isset($_POST['duepuntozero-settings-submit'])) { DI::config()->set('duepuntozero', 'colorset', $_POST['duepuntozero_colorset']); diff --git a/view/theme/frio/config.php b/view/theme/frio/config.php index aad4dc5605..a2e120735c 100644 --- a/view/theme/frio/config.php +++ b/view/theme/frio/config.php @@ -92,7 +92,7 @@ function theme_admin_post() } } -function theme_content(): string +function theme_content(AppHelper $appHelper): string { if (!DI::userSession()->getLocalUserId()) { return ''; @@ -115,7 +115,7 @@ function theme_content(): string return frio_form($arr); } -function theme_admin(): string +function theme_admin(AppHelper $appHelper): string { if (!DI::userSession()->getLocalUserId()) { return ''; diff --git a/view/theme/quattro/config.php b/view/theme/quattro/config.php index 97f68c0579..4406b3d9ea 100644 --- a/view/theme/quattro/config.php +++ b/view/theme/quattro/config.php @@ -46,7 +46,7 @@ function theme_admin(AppHelper $appHelper) { return quattro_form($appHelper,$align, $color, $tfs, $pfs); } -function theme_admin_post(AppHelper $appHelper) { +function theme_admin_post() { if (isset($_POST['quattro-settings-submit'])){ DI::config()->set('quattro', 'align', $_POST['quattro_align']); DI::config()->set('quattro', 'color', $_POST['quattro_color']); diff --git a/view/theme/vier/config.php b/view/theme/vier/config.php index f30bf1be7e..f69e9521a7 100644 --- a/view/theme/vier/config.php +++ b/view/theme/vier/config.php @@ -91,7 +91,7 @@ function theme_admin(AppHelper $appHelper) { return $o; } -function theme_admin_post(AppHelper $appHelper) { +function theme_admin_post() { if (isset($_POST['vier-settings-submit'])){ DI::config()->set('vier', 'style', $_POST['vier_style']); DI::config()->set('vier', 'show_pages', $_POST['vier_show_pages']);