diff --git a/.phpstan.neon b/.phpstan.neon new file mode 100644 index 0000000000..ab1b5e1dc2 --- /dev/null +++ b/.phpstan.neon @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2010 - 2024 the Friendica project +# +# SPDX-License-Identifier: CC0-1.0 + +parameters: + level: 0 + + paths: + - src/ + + scanDirectories: + - mod + - vendor + - view diff --git a/composer.json b/composer.json index 36905f81d1..4acfe7e41a 100644 --- a/composer.json +++ b/composer.json @@ -152,13 +152,16 @@ "mikey179/vfsstream": "^1.6", "mockery/mockery": "^1.3", "php-mock/php-mock-phpunit": "^2.10", + "phpstan/phpstan": "^2.0", "phpunit/phpunit": "^9" }, "scripts": { "test": "phpunit", "test:unit": "phpunit -c tests/phpunit.xml --testsuite unit", + "phpstan": "phpstan analyze --memory-limit 1024M --configuration .phpstan.neon", "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './view/asset/*' -print0 | xargs -0 -n1 php -l", "docker:translate": "docker run --rm -v $PWD:/data -w /data friendicaci/transifex bin/run_xgettext.sh", + "lang:recreate": "bin/run_xgettext.sh", "cs:install": "@composer install --working-dir=bin/dev/php-cs-fixer", "cs:check": [ "@cs:install", diff --git a/composer.lock b/composer.lock index fae42ffe16..8d200a3f67 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d51158b9593011921144e90af146a86a", + "content-hash": "3e31a2243fb69e47e1b7000cca946fa2", "packages": [ { "name": "asika/simple-console", @@ -4832,6 +4832,64 @@ ], "time": "2024-02-11T07:24:16+00:00" }, + { + "name": "phpstan/phpstan", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d", + "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2024-11-11T15:43:04+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.31", diff --git a/src/App/Mode.php b/src/App/Mode.php index 070d67ee4f..ebf9f46163 100644 --- a/src/App/Mode.php +++ b/src/App/Mode.php @@ -210,7 +210,7 @@ class Mode public function isInstall(): bool { return !$this->has(Mode::LOCALCONFIGPRESENT) || - !$this->has(MODE::DBAVAILABLE); + !$this->has(Mode::DBAVAILABLE); } /** diff --git a/src/BaseCollection.php b/src/BaseCollection.php index 407448fc5a..b30dbfc6b0 100644 --- a/src/BaseCollection.php +++ b/src/BaseCollection.php @@ -89,7 +89,9 @@ class BaseCollection extends \ArrayIterator */ public function map(callable $callback): BaseCollection { - return new static(array_map($callback, $this->getArrayCopy()), $this->getTotalCount()); + $class = get_class($this); + + return new $class(array_map($callback, $this->getArrayCopy()), $this->getTotalCount()); } /** @@ -102,7 +104,9 @@ class BaseCollection extends \ArrayIterator */ public function filter(callable $callback = null, int $flag = 0): BaseCollection { - return new static(array_filter($this->getArrayCopy(), $callback, $flag)); + $class = get_class($this); + + return new $class(array_filter($this->getArrayCopy(), $callback, $flag)); } /** @@ -112,7 +116,9 @@ class BaseCollection extends \ArrayIterator */ public function reverse(): BaseCollection { - return new static(array_reverse($this->getArrayCopy()), $this->getTotalCount()); + $class = get_class($this); + + return new $class(array_reverse($this->getArrayCopy()), $this->getTotalCount()); } /** @@ -128,7 +134,9 @@ class BaseCollection extends \ArrayIterator } return array_map(function ($array) { - return new static($array); + $class = get_class($this); + + return new $class($array); }, array_chunk($this->getArrayCopy(), $length)); } diff --git a/src/Console/Addon.php b/src/Console/Addon.php index fd2093f9f5..43ce7a6be3 100644 --- a/src/Console/Addon.php +++ b/src/Console/Addon.php @@ -144,6 +144,8 @@ HELP; } $this->out($table->getTable()); + + return 0; } /** diff --git a/src/Console/AutomaticInstallation.php b/src/Console/AutomaticInstallation.php index ad0a079d23..cc932f51c4 100644 --- a/src/Console/AutomaticInstallation.php +++ b/src/Console/AutomaticInstallation.php @@ -8,6 +8,7 @@ namespace Friendica\Console; use Asika\SimpleConsole\Console; +use Exception; use Friendica\App; use Friendica\App\BaseURL; use Friendica\Core\Config\Capability\IManageConfigValues; @@ -54,12 +55,12 @@ Options -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) -u|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) - -U|--url The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) + -U|--url The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) -B|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) -b|--basepath The basepath of Friendica (env FRIENDICA_BASE_PATH) -t|--tz The timezone of Friendica (env FRIENDICA_TZ) -L|--lang The language of Friendica (env FRIENDICA_LANG) - + Environment variables MYSQL_HOST The host of the mysql/mariadb database (mandatory if mysql and environment is used) MYSQL_PORT The port of the mysql/mariadb database @@ -73,7 +74,7 @@ Environment variables FRIENDICA_ADMIN_MAIL The admin email address of Friendica (this email will be used for admin access) FRIENDICA_TZ The timezone of Friendica FRIENDICA_LANG The langauge of Friendica - + Examples bin/console autoinstall -f 'input.config.php Installs Friendica with the prepared 'input.config.php' file diff --git a/src/Console/Contact.php b/src/Console/Contact.php index e02f589714..46a26c4a9d 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -158,9 +158,10 @@ HELP; if ($result['success']) { $this->out('User ' . $user['nickname'] . ' now connected to ' . $url . ', contact ID ' . $result['cid']); - } else { - throw new RuntimeException($result['message']); + return true; } + + throw new RuntimeException($result['message']); } /** diff --git a/src/Console/FixAPDeliveryWorkerTaskParameters.php b/src/Console/FixAPDeliveryWorkerTaskParameters.php index 9c420a3a68..9cced29dec 100644 --- a/src/Console/FixAPDeliveryWorkerTaskParameters.php +++ b/src/Console/FixAPDeliveryWorkerTaskParameters.php @@ -7,12 +7,11 @@ namespace Friendica\Console; -use Friendica\App; +use Asika\SimpleConsole\CommandArgsException; +use Friendica\App\Mode; +use Friendica\Core\L10n; use Friendica\Database\Database; -use Friendica\Database\DBA; -use Friendica\DI; use Friendica\Model\Contact; -use Friendica\Util\Strings; use RuntimeException; /** @@ -23,13 +22,17 @@ class FixAPDeliveryWorkerTaskParameters extends \Asika\SimpleConsole\Console protected $helpOptions = ['h', 'help', '?']; /** - * @var App\Mode + * @var Mode */ private $appMode; /** * @var Database */ private $dba; + /** + * @var L10n + */ + private $l10n; /** * @var int */ @@ -53,7 +56,7 @@ Usage Description During the 2020.12 RC period some worker task parameters have been corrupted, resulting in the impossibility to execute them. This command restores their expected parameters. - If you didn't run Friendica during the 2020.12 RC period, you do not need to use this command. + If you didn't run Friendica during the 2020.12 RC period, you do not need to use this command. Options -h|--help|-? Show help information @@ -62,7 +65,7 @@ HELP; return $help; } - public function __construct(App\Mode $appMode, Database $dba, \Friendica\Core\L10n $l10n, array $argv = null) + public function __construct(Mode $appMode, Database $dba, L10n $l10n, array $argv = null) { parent::__construct($argv); @@ -80,7 +83,7 @@ HELP; } if (count($this->args) > 0) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + throw new CommandArgsException('Too many arguments'); } if ($this->appMode->isInstall()) { diff --git a/src/Console/User.php b/src/Console/User.php index bdbe7be578..42e85f007d 100644 --- a/src/Console/User.php +++ b/src/Console/User.php @@ -122,7 +122,7 @@ HELP; case 'search': return $this->searchUser(); case 'config': - return $this->configUser(); + return ($this->configUser()) ? 0 : 1; default: throw new \Asika\SimpleConsole\CommandArgsException('Wrong command.'); } @@ -512,5 +512,7 @@ HELP; $this->out($this->getHelp()); return false; } + + return true; } } diff --git a/src/Content/Post/Entity/PostMedia.php b/src/Content/Post/Entity/PostMedia.php index a856118b80..0dd3309176 100644 --- a/src/Content/Post/Entity/PostMedia.php +++ b/src/Content/Post/Entity/PostMedia.php @@ -228,7 +228,7 @@ class PostMedia extends BaseEntity $newHeight = $dimensionts['height']; } - return new static( + return new self( $this->uriId, $this->url, $this->type, @@ -255,7 +255,7 @@ class PostMedia extends BaseEntity public function withUrl(\GuzzleHttp\Psr7\Uri $url): self { - return new static( + return new self( $this->uriId, $url, $this->type, diff --git a/src/Content/Widget/ContactBlock.php b/src/Content/Widget/ContactBlock.php index 917f973322..b1d80653d4 100644 --- a/src/Content/Widget/ContactBlock.php +++ b/src/Content/Widget/ContactBlock.php @@ -26,7 +26,6 @@ class ContactBlock /** * Get HTML for contact block * - * @template widget/contacts.tpl * @hook contact_block_end (contacts=>array, output=>string) * @return string Formatted HTML code or empty string */ diff --git a/src/Content/Widget/VCard.php b/src/Content/Widget/VCard.php index f91384051c..737db45ac2 100644 --- a/src/Content/Widget/VCard.php +++ b/src/Content/Widget/VCard.php @@ -26,7 +26,6 @@ class VCard /** * Get HTML for vcard block * - * @template widget/vcard.tpl * @param array $contact * @param bool $hide_mention * @param bool $hide_follow diff --git a/src/Core/Cache/Type/APCuCache.php b/src/Core/Cache/Type/APCuCache.php index d65ead179a..5564a1e793 100644 --- a/src/Core/Cache/Type/APCuCache.php +++ b/src/Core/Cache/Type/APCuCache.php @@ -41,11 +41,8 @@ class APCuCache extends AbstractCache implements ICanCacheInMemory $ns = $this->getCacheKey($prefix ?? ''); $ns = preg_quote($ns, '/'); - if (class_exists('\APCIterator')) { - $iterator = new \APCIterator('user', '/^' . $ns. '/', APC_ITER_KEY); - } else { - $iterator = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY); - } + /** @phpstan-ignore-next-line see https://github.com/friendica/friendica-addons/pull/1363 */ + $iterator = new \APCUIterator('/^' . $ns . '/', APC_ITER_KEY); $keys = []; foreach ($iterator as $item) { @@ -122,11 +119,8 @@ class APCuCache extends AbstractCache implements ICanCacheInMemory $prefix = $this->getPrefix(); $prefix = preg_quote($prefix, '/'); - if (class_exists('\APCIterator')) { - $iterator = new \APCIterator('user', '/^' . $prefix . '/', APC_ITER_KEY); - } else { - $iterator = new \APCUIterator('/^' . $prefix . '/', APC_ITER_KEY); - } + /** @phpstan-ignore-next-line see https://github.com/friendica/friendica-addons/pull/1363 */ + $iterator = new \APCUIterator('/^' . $prefix . '/', APC_ITER_KEY); return apcu_delete($iterator); } @@ -149,10 +143,7 @@ class APCuCache extends AbstractCache implements ICanCacheInMemory return false; } elseif (!ini_get('apc.enabled') && !ini_get('apc.enable_cli')) { return false; - } elseif ( - version_compare(phpversion('apc') ?: '0.0.0', '4.0.6') === -1 && - version_compare(phpversion('apcu') ?: '0.0.0', '5.1.0') === -1 - ) { + } elseif (version_compare(phpversion('apcu') ?: '0.0.0', '5.1.0', '<')) { return false; } diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 4f449a1fa3..a561c00c02 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -2709,8 +2709,6 @@ class Contact * * @param int $id * @param array $contact - * - * @return boolean */ private static function hasLocalData(int $id, array $contact): bool { @@ -2770,6 +2768,8 @@ class Contact 'network', 'alias', 'baseurl', 'gsid', 'forum', 'prv', 'contact-type', 'pubkey', 'last-item', 'xmpp', 'matrix', 'created', 'last-update' ]; + + /** @var array */ $contact = DBA::selectFirst('contact', $fields, ['id' => $id]); if (!DBA::isResult($contact)) { return false; @@ -2795,22 +2795,22 @@ class Contact $has_local_data = self::hasLocalData($id, $contact); - $uid = $contact['uid']; + $uid = $contact['uid'] ?? null; unset($contact['uid']); - $uriid = $contact['uri-id']; + $uriid = $contact['uri-id'] ?? null; unset($contact['uri-id']); - $pubkey = $contact['pubkey']; + $pubkey = $contact['pubkey'] ?? null; unset($contact['pubkey']); - $created = $contact['created']; + $created = $contact['created'] ?? ''; unset($contact['created']); - $last_update = $contact['last-update']; + $last_update = $contact['last-update'] ?? ''; unset($contact['last-update']); - $contact['photo'] = $contact['avatar']; + $contact['photo'] = $contact['avatar'] ?? null; unset($contact['avatar']); $updated = DateTimeFormat::utcNow(); diff --git a/src/Model/Item.php b/src/Model/Item.php index 63cd31c5a2..037add5007 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3199,10 +3199,10 @@ class Item } elseif ($remote_user) { // Authenticated visitor - fetch the matching permissionsets $permissionSets = DI::permissionSet()->selectByContactId($remote_user, $owner_id); - if (!empty($set)) { + if (!empty($permissionSets)) { $condition = [ "(`private` != ? OR (`private` = ? AND `wall` - AND `psid` IN (" . implode(', ', array_fill(0, count($set), '?')) . ")))", + AND `psid` IN (" . implode(', ', array_fill(0, count($permissionSets), '?')) . ")))", self::PRIVATE, self::PRIVATE ]; $condition = array_merge($condition, $permissionSets->column('id')); @@ -3248,7 +3248,7 @@ class Item */ $permissionSets = DI::permissionSet()->selectByContactId($remote_user, $owner_id); - if (!empty($set)) { + if (!empty($permissionSets)) { $sql_set = sprintf(" OR (" . $table . "`private` = %d AND " . $table . "`wall` AND " . $table . "`psid` IN (", self::PRIVATE) . implode(',', $permissionSets->column('id')) . "))"; } else { $sql_set = ''; diff --git a/src/Module/Api/Mastodon/Search.php b/src/Module/Api/Mastodon/Search.php index e87c710b09..45556bc3aa 100644 --- a/src/Module/Api/Mastodon/Search.php +++ b/src/Module/Api/Mastodon/Search.php @@ -157,10 +157,6 @@ class Search extends BaseApi $condition = DBA::mergeConditions($condition, ["`uri-id` < ?", $max_id]); } - if (!empty($since_id)) { - $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $since_id]); - } - if (!empty($min_id)) { $condition = DBA::mergeConditions($condition, ["`uri-id` > ?", $min_id]); diff --git a/src/Module/Debug/ActivityPubConversion.php b/src/Module/Debug/ActivityPubConversion.php index 251b9ad26e..da165174b8 100644 --- a/src/Module/Debug/ActivityPubConversion.php +++ b/src/Module/Debug/ActivityPubConversion.php @@ -23,12 +23,12 @@ class ActivityPubConversion extends BaseModule protected function content(array $request = []): string { - function visible_whitespace($s) - { - return '
' . htmlspecialchars($s) . '
'; - } - $results = []; + + $visible_whitespace = function (string $s): string { + return '
' . htmlspecialchars($s) . '
'; + }; + if (!empty($_REQUEST['source'])) { try { $source = json_decode($_REQUEST['source'], true); @@ -43,11 +43,11 @@ class ActivityPubConversion extends BaseModule $formatted = json_encode($source, JSON_PRETTY_PRINT); $results[] = [ 'title' => DI::l10n()->t('Formatted'), - 'content' => visible_whitespace(trim(var_export($formatted, true), "'")), + 'content' => $visible_whitespace(trim(var_export($formatted, true), "'")), ]; $results[] = [ 'title' => DI::l10n()->t('Source'), - 'content' => visible_whitespace(var_export($source, true)) + 'content' => $visible_whitespace(var_export($source, true)) ]; $activity = JsonLD::compact($source); if (!$activity) { @@ -55,7 +55,7 @@ class ActivityPubConversion extends BaseModule } $results[] = [ 'title' => DI::l10n()->t('Activity'), - 'content' => visible_whitespace(var_export($activity, true)) + 'content' => $visible_whitespace(var_export($activity, true)) ]; $type = JsonLD::fetchElement($activity, '@type'); @@ -92,10 +92,6 @@ class ActivityPubConversion extends BaseModule throw new \Exception('No trust for activity type "' . $type . '", so we quit now.'); } - if (!empty($body) && empty($object_data['raw'])) { - $object_data['raw'] = $body; - } - // Internal flag for thread completion. See Processor.php if (!empty($activity['thread-completion'])) { $object_data['thread-completion'] = $activity['thread-completion']; @@ -107,14 +103,14 @@ class ActivityPubConversion extends BaseModule $results[] = [ 'title' => DI::l10n()->t('Object data'), - 'content' => visible_whitespace(var_export($object_data, true)) + 'content' => $visible_whitespace(var_export($object_data, true)) ]; $item = ActivityPub\Processor::createItem($object_data, true); $results[] = [ 'title' => DI::l10n()->t('Result Item'), - 'content' => visible_whitespace(var_export($item, true)) + 'content' => $visible_whitespace(var_export($item, true)) ]; } catch (\Throwable $e) { $results[] = [ diff --git a/src/Module/Debug/Babel.php b/src/Module/Debug/Babel.php index 8a7c5230dc..e7852847f6 100644 --- a/src/Module/Debug/Babel.php +++ b/src/Module/Debug/Babel.php @@ -29,12 +29,12 @@ class Babel extends BaseModule protected function content(array $request = []): string { - function visible_whitespace($s) - { - return '
' . htmlspecialchars($s) . '
'; - } - $results = []; + + $visible_whitespace = function (string $s): string { + return '
' . htmlspecialchars($s) . '
'; + }; + if (!empty($request['text'])) { self::checkFormSecurityTokenForbiddenOnError('babel'); switch (($request['type'] ?? '') ?: 'bbcode') { @@ -42,24 +42,24 @@ class Babel extends BaseModule $bbcode = $request['text']; $results[] = [ 'title' => DI::l10n()->t('Source input'), - 'content' => visible_whitespace($bbcode) + 'content' => $visible_whitespace($bbcode) ]; $plain = Text\BBCode::toPlaintext($bbcode, false); $results[] = [ 'title' => DI::l10n()->t('BBCode::toPlaintext'), - 'content' => visible_whitespace($plain) + 'content' => $visible_whitespace($plain) ]; $html = Text\BBCode::convertForUriId(0, $bbcode); $results[] = [ 'title' => DI::l10n()->t('BBCode::convert (raw HTML)'), - 'content' => visible_whitespace($html) + 'content' => $visible_whitespace($html) ]; $results[] = [ 'title' => DI::l10n()->t('BBCode::convert (hex)'), - 'content' => visible_whitespace(bin2hex($html)), + 'content' => $visible_whitespace(bin2hex($html)), ]; $results[] = [ @@ -70,19 +70,19 @@ class Babel extends BaseModule $bbcode2 = Text\HTML::toBBCode($html); $results[] = [ 'title' => DI::l10n()->t('BBCode::convert => HTML::toBBCode'), - 'content' => visible_whitespace($bbcode2) + 'content' => $visible_whitespace($bbcode2) ]; $markdown = Text\BBCode::toMarkdown($bbcode); $results[] = [ 'title' => DI::l10n()->t('BBCode::toMarkdown'), - 'content' => visible_whitespace($markdown) + 'content' => $visible_whitespace($markdown) ]; $html2 = Text\Markdown::convert($markdown); $results[] = [ 'title' => DI::l10n()->t('BBCode::toMarkdown => Markdown::convert (raw HTML)'), - 'content' => visible_whitespace($html2) + 'content' => $visible_whitespace($html2) ]; $results[] = [ 'title' => DI::l10n()->t('BBCode::toMarkdown => Markdown::convert'), @@ -92,13 +92,13 @@ class Babel extends BaseModule $bbcode3 = Text\Markdown::toBBCode($markdown); $results[] = [ 'title' => DI::l10n()->t('BBCode::toMarkdown => Markdown::toBBCode'), - 'content' => visible_whitespace($bbcode3) + 'content' => $visible_whitespace($bbcode3) ]; $bbcode4 = Text\HTML::toBBCode($html2); $results[] = [ 'title' => DI::l10n()->t('BBCode::toMarkdown => Markdown::convert => HTML::toBBCode'), - 'content' => visible_whitespace($bbcode4) + 'content' => $visible_whitespace($bbcode4) ]; $tags = Text\BBCode::getTags($bbcode); @@ -106,22 +106,22 @@ class Babel extends BaseModule $body = Item::setHashtags($bbcode); $results[] = [ 'title' => DI::l10n()->t('Item Body'), - 'content' => visible_whitespace($body) + 'content' => $visible_whitespace($body) ]; $results[] = [ 'title' => DI::l10n()->t('Item Tags'), - 'content' => visible_whitespace(var_export($tags, true)), + 'content' => $visible_whitespace(var_export($tags, true)), ]; $body2 = PageInfo::searchAndAppendToBody($bbcode, true); $results[] = [ 'title' => DI::l10n()->t('PageInfo::appendToBody'), - 'content' => visible_whitespace($body2) + 'content' => $visible_whitespace($body2) ]; $html3 = Text\BBCode::convertForUriId(0, $body2); $results[] = [ 'title' => DI::l10n()->t('PageInfo::appendToBody => BBCode::convert (raw HTML)'), - 'content' => visible_whitespace($html3) + 'content' => $visible_whitespace($html3) ]; $results[] = [ 'title' => DI::l10n()->t('PageInfo::appendToBody => BBCode::convert'), @@ -132,7 +132,7 @@ class Babel extends BaseModule $diaspora = trim($request['text']); $results[] = [ 'title' => DI::l10n()->t('Source input (Diaspora format)'), - 'content' => visible_whitespace($diaspora), + 'content' => $visible_whitespace($diaspora), ]; $markdown = XML::unescape($diaspora); @@ -141,13 +141,13 @@ class Babel extends BaseModule $results[] = [ 'title' => DI::l10n()->t('Source input (Markdown)'), - 'content' => visible_whitespace($markdown), + 'content' => $visible_whitespace($markdown), ]; $html = Text\Markdown::convert($markdown); $results[] = [ 'title' => DI::l10n()->t('Markdown::convert (raw HTML)'), - 'content' => visible_whitespace($html), + 'content' => $visible_whitespace($html), ]; $results[] = [ @@ -158,14 +158,14 @@ class Babel extends BaseModule $bbcode = Text\Markdown::toBBCode($markdown); $results[] = [ 'title' => DI::l10n()->t('Markdown::toBBCode'), - 'content' => visible_whitespace($bbcode), + 'content' => $visible_whitespace($bbcode), ]; break; case 'html' : $html = trim($request['text']); $results[] = [ 'title' => DI::l10n()->t('Raw HTML input'), - 'content' => visible_whitespace($html), + 'content' => $visible_whitespace($html), ]; $results[] = [ @@ -177,12 +177,12 @@ class Babel extends BaseModule $results[] = [ 'title' => DI::l10n()->t('HTML Purified (raw)'), - 'content' => visible_whitespace($purified), + 'content' => $visible_whitespace($purified), ]; $results[] = [ 'title' => DI::l10n()->t('HTML Purified (hex)'), - 'content' => visible_whitespace(bin2hex($purified)), + 'content' => $visible_whitespace(bin2hex($purified)), ]; $results[] = [ @@ -193,7 +193,7 @@ class Babel extends BaseModule $bbcode = Text\HTML::toBBCode($html); $results[] = [ 'title' => DI::l10n()->t('HTML::toBBCode'), - 'content' => visible_whitespace($bbcode) + 'content' => $visible_whitespace($bbcode) ]; $html2 = Text\BBCode::convertForUriId(0, $bbcode); @@ -210,25 +210,25 @@ class Babel extends BaseModule $bbcode2plain = Text\BBCode::toPlaintext($bbcode); $results[] = [ 'title' => DI::l10n()->t('HTML::toBBCode => BBCode::toPlaintext'), - 'content' => visible_whitespace($bbcode2plain), + 'content' => $visible_whitespace($bbcode2plain), ]; $markdown = Text\HTML::toMarkdown($html); $results[] = [ 'title' => DI::l10n()->t('HTML::toMarkdown'), - 'content' => visible_whitespace($markdown) + 'content' => $visible_whitespace($markdown) ]; $text = Text\HTML::toPlaintext($html, 0); $results[] = [ 'title' => DI::l10n()->t('HTML::toPlaintext'), - 'content' => visible_whitespace($text), + 'content' => $visible_whitespace($text), ]; $text = Text\HTML::toPlaintext($html, 0, true); $results[] = [ 'title' => DI::l10n()->t('HTML::toPlaintext (compact)'), - 'content' => visible_whitespace($text), + 'content' => $visible_whitespace($text), ]; break; case 'twitter': @@ -237,16 +237,11 @@ class Babel extends BaseModule if (file_exists('addon/twitter/twitter.php')) { require_once 'addon/twitter/twitter.php'; - if (parse_url($json) !== false) { - preg_match('#^https?://(?:mobile\.|www\.)?twitter.com/[^/]+/status/(\d+).*#', $json, $matches); - $status = twitter_statuses_show($matches[1]); - } else { - $status = json_decode($json); - } + $status = json_decode($json); $results[] = [ 'title' => DI::l10n()->t('Decoded post'), - 'content' => visible_whitespace(var_export($status, true)), + 'content' => $visible_whitespace(var_export($status, true)), ]; $postarray = []; @@ -263,23 +258,9 @@ class Babel extends BaseModule $postarray['object-type'] = Activity\ObjectType::BOOKMARK; } - $picture = \twitter_media_entities($status, $postarray); - $results[] = [ 'title' => DI::l10n()->t('Post array before expand entities'), - 'content' => visible_whitespace(var_export($postarray, true)), - ]; - - $converted = \twitter_expand_entities($postarray['body'], $status, $picture); - - $results[] = [ - 'title' => DI::l10n()->t('Post converted'), - 'content' => visible_whitespace(var_export($converted, true)), - ]; - - $results[] = [ - 'title' => DI::l10n()->t('Converted body'), - 'content' => visible_whitespace($converted['body']), + 'content' => $visible_whitespace(var_export($postarray, true)), ]; } else { $results[] = [ diff --git a/src/Module/Debug/ItemBody.php b/src/Module/Debug/ItemBody.php index fe07f51b8f..204a0dd5a8 100644 --- a/src/Module/Debug/ItemBody.php +++ b/src/Module/Debug/ItemBody.php @@ -11,36 +11,43 @@ use Friendica\BaseModule; use Friendica\Core\System; use Friendica\DI; use Friendica\Model\Post; -use Friendica\Network\HTTPException; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\Network\HTTPException\UnauthorizedException; /** * Print the body of an Item */ class ItemBody extends BaseModule { + /** + * @throws NotFoundException|UnauthorizedException + * + * @return string|never + */ protected function content(array $request = []): string { if (!DI::userSession()->getLocalUserId()) { - throw new HTTPException\UnauthorizedException(DI::l10n()->t('Access denied.')); + throw new UnauthorizedException(DI::l10n()->t('Access denied.')); } if (empty($this->parameters['item'])) { - throw new HTTPException\NotFoundException(DI::l10n()->t('Item not found.')); + throw new NotFoundException(DI::l10n()->t('Item not found.')); } $itemId = intval($this->parameters['item']); $item = Post::selectFirst(['body'], ['uid' => [0, DI::userSession()->getLocalUserId()], 'uri-id' => $itemId]); - if (!empty($item)) { - if (DI::mode()->isAjax()) { - echo str_replace("\n", '
', $item['body']); - System::exit(); - } else { - return str_replace("\n", '
', $item['body']); - } - } else { - throw new HTTPException\NotFoundException(DI::l10n()->t('Item not found.')); + if (empty($item)) { + throw new NotFoundException(DI::l10n()->t('Item not found.')); } + + // TODO: Extract this code into controller + if (DI::mode()->isAjax()) { + echo str_replace("\n", '
', $item['body']); + System::exit(); + } + + return str_replace("\n", '
', $item['body']); } } diff --git a/src/Object/Api/Mastodon/Preferences.php b/src/Object/Api/Mastodon/Preferences.php index 7447f5fa74..68f3c922a8 100644 --- a/src/Object/Api/Mastodon/Preferences.php +++ b/src/Object/Api/Mastodon/Preferences.php @@ -17,16 +17,30 @@ use Friendica\BaseDataTransferObject; */ class Preferences extends BaseDataTransferObject { -// /** @var string (Enumerable, oneOf) */ -// protected $posting_default_visibility; -// /** @var bool */ -// protected $posting_default_sensitive; -// /** @var string (ISO 639-1 language two-letter code), or null*/ -// protected $posting_default_language; -// /** @var string (Enumerable, oneOf) */ -// protected $reading_expand_media; -// /** @var bool */ -// protected $reading_expand_spoilers; + /** + * @var string (Enumerable, oneOf) + */ + private $visibility; + + /** + * @var bool + */ + private $sensitive; + + /** + * @var string (ISO 639-1 language two-letter code), or null + */ + private $language; + + /** + * @var string (Enumerable, oneOf) + */ + private $media; + + /** + * @var bool + */ + private $spoilers; /** * Creates a preferences record. @@ -39,10 +53,26 @@ class Preferences extends BaseDataTransferObject */ public function __construct(string $visibility, bool $sensitive, string $language, string $media, bool $spoilers) { - $this->{'posting:default:visibility'} = $visibility; - $this->{'posting:default:sensitive'} = $sensitive; - $this->{'posting:default:language'} = $language; - $this->{'reading:expand:media'} = $media; - $this->{'reading:expand:spoilers'} = $spoilers; + $this->visibility = $visibility; + $this->sensitive = $sensitive; + $this->language = $language; + $this->media = $media; + $this->spoilers = $spoilers; + } + + /** + * Returns the current entity as an array + * + * @return array + */ + public function toArray(): array + { + return [ + 'posting:default:visibility' => $this->visibility, + 'posting:default:sensitive' => $this->sensitive, + 'posting:default:language' => $this->language, + 'reading:expand:media' => $this->media, + 'reading:expand:spoilers' => $this->spoilers, + ]; } } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 12fd91b7cf..7512e6179c 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -1880,25 +1880,29 @@ class Receiver $object_data = self::getObjectDataFromActivity($object); - $receiverdata = self::getReceivers($object, $actor ?: $object_data['actor'] ?? '', $object_data['tags'], true, false); - $receivers = $reception_types = []; - foreach ($receiverdata as $key => $data) { - $receivers[$key] = $data['uid']; - $reception_types[$data['uid']] = $data['type'] ?? 0; - } - $object_data['receiver_urls'] = self::getReceiverURL($object); - $object_data['receiver'] = $receivers; - $object_data['reception_type'] = $reception_types; + $object_data['receiver'] = []; + $object_data['reception_type'] = []; + $object_data['unlisted'] = false; + + $receiverdata = self::getReceivers($object, $actor ?: $object_data['actor'] ?? '', $object_data['tags'], true, false); + + foreach ($receiverdata as $key => $data) { + if ($data['uid'] !== -1) { + $object_data['reception_type'][$data['uid']] = $data['type'] ?? 0; + } + + if ($key !== -1) { + $object_data['receiver'][$key] = $data['uid']; + } else { + $object_data['unlisted'] = true; + } + } if (!empty($object['pixelfed:capabilities'])) { $object_data['capabilities'] = self::getCapabilities($object); } - $object_data['unlisted'] = in_array(-1, $object_data['receiver']); - unset($object_data['receiver'][-1]); - unset($object_data['reception_type'][-1]); - return $object_data; } diff --git a/src/Util/Temporal.php b/src/Util/Temporal.php index 0ce59bfaf0..d3ed346908 100644 --- a/src/Util/Temporal.php +++ b/src/Util/Temporal.php @@ -359,6 +359,8 @@ class Temporal return sprintf($format, $r, (($r == 1) ? $str[0] : $str[1])); } } + + return ''; } /** diff --git a/tests/Unit/Object/Api/Mastodon/PreferencesTest.php b/tests/Unit/Object/Api/Mastodon/PreferencesTest.php new file mode 100644 index 0000000000..e77a4272e0 --- /dev/null +++ b/tests/Unit/Object/Api/Mastodon/PreferencesTest.php @@ -0,0 +1,46 @@ + 'visibility', + 'posting:default:sensitive' => true, + 'posting:default:language' => 'language', + 'reading:expand:media' => 'media', + 'reading:expand:spoilers' => false, + ], + $preferences->toArray(), + ); + } + + public function testJsonSerializeReturnsArray(): void + { + $preferences = new Preferences('visibility', true, 'language', 'media', false); + + self::assertSame( + [ + 'posting:default:visibility' => 'visibility', + 'posting:default:sensitive' => true, + 'posting:default:language' => 'language', + 'reading:expand:media' => 'media', + 'reading:expand:spoilers' => false, + ], + $preferences->jsonSerialize(), + ); + } +} diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 33e225886a..8c8c99879e 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2024.09-rc\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-11-15 06:54+0000\n" +"POT-Creation-Date: 2024-11-16 08:31+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -39,8 +39,8 @@ msgid "Empty post discarded." msgstr "" #: mod/item.php:425 src/Module/Admin/Themes/Details.php:31 -#: src/Module/Admin/Themes/Index.php:51 src/Module/Debug/ItemBody.php:28 -#: src/Module/Debug/ItemBody.php:43 src/Module/Item/Feed.php:66 +#: src/Module/Admin/Themes/Index.php:51 src/Module/Debug/ItemBody.php:34 +#: src/Module/Debug/ItemBody.php:42 src/Module/Item/Feed.php:66 msgid "Item not found." msgstr "" @@ -292,8 +292,8 @@ msgstr "" #: mod/photos.php:1152 mod/photos.php:1232 #: src/Module/Calendar/Event/Form.php:236 src/Module/Contact/Advanced.php:118 #: src/Module/Contact/Profile.php:376 -#: src/Module/Debug/ActivityPubConversion.php:132 -#: src/Module/Debug/Babel.php:307 src/Module/Debug/Localtime.php:50 +#: src/Module/Debug/ActivityPubConversion.php:128 +#: src/Module/Debug/Babel.php:288 src/Module/Debug/Localtime.php:50 #: src/Module/Debug/Probe.php:40 src/Module/Debug/WebFinger.php:37 #: src/Module/FriendSuggest.php:131 src/Module/Install.php:221 #: src/Module/Install.php:261 src/Module/Install.php:296 @@ -792,15 +792,15 @@ msgstr "" msgid "Common" msgstr "" -#: src/Console/Addon.php:161 src/Console/Addon.php:185 +#: src/Console/Addon.php:163 src/Console/Addon.php:187 msgid "Addon not found" msgstr "" -#: src/Console/Addon.php:165 +#: src/Console/Addon.php:167 msgid "Addon already enabled" msgstr "" -#: src/Console/Addon.php:189 +#: src/Console/Addon.php:191 msgid "Addon already disabled" msgstr "" @@ -1065,7 +1065,7 @@ msgstr "" msgid "Email" msgstr "" -#: src/Content/ContactSelector.php:122 src/Module/Debug/Babel.php:301 +#: src/Content/ContactSelector.php:122 src/Module/Debug/Babel.php:282 msgid "Diaspora" msgstr "" @@ -1365,7 +1365,7 @@ msgstr "" msgid "Public post" msgstr "" -#: src/Content/Conversation.php:410 src/Content/Widget/VCard.php:122 +#: src/Content/Conversation.php:410 src/Content/Widget/VCard.php:121 #: src/Model/Profile.php:462 src/Module/Admin/Logs/View.php:80 #: src/Module/Post/Edit.php:167 msgid "Message" @@ -2273,7 +2273,7 @@ msgstr "" msgid "The end" msgstr "" -#: src/Content/Text/HTML.php:847 src/Content/Widget/VCard.php:118 +#: src/Content/Text/HTML.php:847 src/Content/Widget/VCard.php:117 #: src/Model/Profile.php:456 src/Module/Contact/Profile.php:484 msgid "Follow" msgstr "" @@ -2416,18 +2416,18 @@ msgstr "" msgid "Export calendar as csv" msgstr "" -#: src/Content/Widget/ContactBlock.php:65 +#: src/Content/Widget/ContactBlock.php:64 msgid "No contacts" msgstr "" -#: src/Content/Widget/ContactBlock.php:96 +#: src/Content/Widget/ContactBlock.php:95 #, php-format msgid "%d Contact" msgid_plural "%d Contacts" msgstr[0] "" msgstr[1] "" -#: src/Content/Widget/ContactBlock.php:113 +#: src/Content/Widget/ContactBlock.php:112 msgid "View Contacts" msgstr "" @@ -2446,27 +2446,27 @@ msgstr[1] "" msgid "More Trending Tags" msgstr "" -#: src/Content/Widget/VCard.php:96 src/Model/Contact.php:1207 +#: src/Content/Widget/VCard.php:95 src/Model/Contact.php:1207 #: src/Model/Profile.php:441 msgid "Post to group" msgstr "" -#: src/Content/Widget/VCard.php:101 src/Model/Contact.php:1211 +#: src/Content/Widget/VCard.php:100 src/Model/Contact.php:1211 #: src/Model/Profile.php:445 src/Module/Moderation/Item/Source.php:77 msgid "Mention" msgstr "" -#: src/Content/Widget/VCard.php:111 src/Model/Profile.php:360 +#: src/Content/Widget/VCard.php:110 src/Model/Profile.php:360 #: src/Module/Contact/Profile.php:420 src/Module/Profile/Profile.php:187 msgid "XMPP:" msgstr "" -#: src/Content/Widget/VCard.php:112 src/Model/Profile.php:361 +#: src/Content/Widget/VCard.php:111 src/Model/Profile.php:361 #: src/Module/Contact/Profile.php:422 src/Module/Profile/Profile.php:191 msgid "Matrix:" msgstr "" -#: src/Content/Widget/VCard.php:113 src/Model/Event.php:68 +#: src/Content/Widget/VCard.php:112 src/Model/Event.php:68 #: src/Model/Event.php:95 src/Model/Event.php:457 src/Model/Event.php:946 #: src/Model/Profile.php:355 src/Module/Contact/Profile.php:418 #: src/Module/Directory.php:134 src/Module/Notifications/Introductions.php:180 @@ -2474,18 +2474,18 @@ msgstr "" msgid "Location:" msgstr "" -#: src/Content/Widget/VCard.php:116 src/Model/Profile.php:469 +#: src/Content/Widget/VCard.php:115 src/Model/Profile.php:469 #: src/Module/Notifications/Introductions.php:194 msgid "Network:" msgstr "" -#: src/Content/Widget/VCard.php:120 src/Model/Contact.php:1239 +#: src/Content/Widget/VCard.php:119 src/Model/Contact.php:1239 #: src/Model/Contact.php:1251 src/Model/Profile.php:458 #: src/Module/Contact/Profile.php:476 msgid "Unfollow" msgstr "" -#: src/Content/Widget/VCard.php:126 src/Model/Contact.php:1209 +#: src/Content/Widget/VCard.php:125 src/Model/Contact.php:1209 #: src/Model/Profile.php:443 msgid "View group" msgstr "" @@ -5630,7 +5630,7 @@ msgstr "" msgid "Babel" msgstr "" -#: src/Module/BaseAdmin.php:97 src/Module/Debug/ActivityPubConversion.php:129 +#: src/Module/BaseAdmin.php:97 src/Module/Debug/ActivityPubConversion.php:125 msgid "ActivityPub Conversion" msgstr "" @@ -6248,7 +6248,7 @@ msgstr[1] "" #: src/Module/Contact/Follow.php:56 src/Module/Contact/Redir.php:45 #: src/Module/Contact/Redir.php:206 src/Module/Conversation/Community.php:154 -#: src/Module/Debug/ItemBody.php:24 src/Module/Diaspora/Receive.php:45 +#: src/Module/Debug/ItemBody.php:30 src/Module/Diaspora/Receive.php:45 #: src/Module/Item/Display.php:82 src/Module/Item/Feed.php:45 #: src/Module/Item/Follow.php:27 src/Module/Item/Ignore.php:27 #: src/Module/Item/Language.php:39 src/Module/Item/Pin.php:27 @@ -6732,23 +6732,23 @@ msgstr "" msgid "Activity" msgstr "" -#: src/Module/Debug/ActivityPubConversion.php:109 +#: src/Module/Debug/ActivityPubConversion.php:105 msgid "Object data" msgstr "" -#: src/Module/Debug/ActivityPubConversion.php:116 +#: src/Module/Debug/ActivityPubConversion.php:112 msgid "Result Item" msgstr "" -#: src/Module/Debug/ActivityPubConversion.php:121 -#: src/Module/Debug/Babel.php:286 src/Module/Moderation/Item/Source.php:79 +#: src/Module/Debug/ActivityPubConversion.php:117 +#: src/Module/Debug/Babel.php:267 src/Module/Moderation/Item/Source.php:79 #: src/Module/Security/TwoFactor/Verify.php:84 msgid "Error" msgid_plural "Errors" msgstr[0] "" msgstr[1] "" -#: src/Module/Debug/ActivityPubConversion.php:130 +#: src/Module/Debug/ActivityPubConversion.php:126 msgid "Source activity" msgstr "" @@ -6884,47 +6884,39 @@ msgstr "" msgid "HTML::toPlaintext (compact)" msgstr "" -#: src/Module/Debug/Babel.php:248 +#: src/Module/Debug/Babel.php:243 msgid "Decoded post" msgstr "" -#: src/Module/Debug/Babel.php:269 +#: src/Module/Debug/Babel.php:262 msgid "Post array before expand entities" msgstr "" -#: src/Module/Debug/Babel.php:276 -msgid "Post converted" -msgstr "" - -#: src/Module/Debug/Babel.php:281 -msgid "Converted body" -msgstr "" - -#: src/Module/Debug/Babel.php:287 +#: src/Module/Debug/Babel.php:268 msgid "Twitter addon is absent from the addon/ folder." msgstr "" -#: src/Module/Debug/Babel.php:297 +#: src/Module/Debug/Babel.php:278 msgid "Babel Diagnostic" msgstr "" -#: src/Module/Debug/Babel.php:299 +#: src/Module/Debug/Babel.php:280 msgid "Source text" msgstr "" -#: src/Module/Debug/Babel.php:300 +#: src/Module/Debug/Babel.php:281 msgid "BBCode" msgstr "" -#: src/Module/Debug/Babel.php:302 +#: src/Module/Debug/Babel.php:283 msgid "Markdown" msgstr "" -#: src/Module/Debug/Babel.php:303 +#: src/Module/Debug/Babel.php:284 msgid "HTML" msgstr "" -#: src/Module/Debug/Babel.php:305 +#: src/Module/Debug/Babel.php:286 msgid "Twitter Source / Tweet URL (requires API key)" msgstr ""