1
0
Fork 0

Merge branch 'friendica:develop' into mastodon-api-reshare-fixes

This commit is contained in:
Hank G 2023-08-13 15:42:22 -04:00 committed by GitHub
commit 09a612670a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
116 changed files with 829 additions and 680 deletions

View file

@ -1,4 +1,4 @@
pipeline: steps:
restore_cache: restore_cache:
image: meltwater/drone-cache:dev image: meltwater/drone-cache:dev
settings: settings:

View file

@ -11,11 +11,11 @@ labels:
skip_clone: true skip_clone: true
pipeline: steps:
clone: clone:
image: alpine/git image: alpine/git
commands: commands:
- git clone $CI_REPO_LINK . - git clone $CI_REPO_CLONE_URL .
- git checkout $CI_COMMIT_BRANCH - git checkout $CI_COMMIT_BRANCH
- git fetch origin $CI_COMMIT_REF - git fetch origin $CI_COMMIT_REF
- git merge $CI_COMMIT_SHA - git merge $CI_COMMIT_SHA

View file

@ -6,7 +6,11 @@ matrix:
branches: branches:
exclude: [ stable ] exclude: [ stable ]
pipeline: # This forces CI executions at the "opensocial" labeled location (because of much more power...)
labels:
location: opensocial
steps:
db_version_match: db_version_match:
image: friendicaci/transifex image: friendicaci/transifex
commands: commands:

View file

@ -1,4 +1,4 @@
pipeline: steps:
check: check:
image: friendicaci/php-cs image: friendicaci/php-cs
commands: commands:

View file

@ -1,4 +1,4 @@
pipeline: steps:
build_xgettext: build_xgettext:
image: friendicaci/transifex image: friendicaci/transifex
commands: commands:

View file

@ -15,12 +15,12 @@ matrix:
labels: labels:
location: opensocial location: opensocial
pipeline: steps:
php-lint: php-lint:
image: php:${PHP_MAJOR_VERSION} image: php:${PHP_MAJOR_VERSION}
group: lint group: lint
commands: commands:
- ./bin/composer.phar run lint - find . -name \*.php -not -path './vendor/*' -not -path './view/asset/*' -print0 | xargs -0 -n1 php -l
restore_cache: restore_cache:
image: meltwater/drone-cache:dev image: meltwater/drone-cache:dev
settings: settings:

View file

@ -9,11 +9,11 @@ labels:
skip_clone: true skip_clone: true
pipeline: steps:
clone: clone:
image: alpine/git image: alpine/git
commands: commands:
- git clone $CI_REPO_LINK . - git clone $CI_REPO_CLONE_URL .
- git checkout $CI_COMMIT_BRANCH - git checkout $CI_COMMIT_BRANCH
- git fetch origin $CI_COMMIT_REF - git fetch origin $CI_COMMIT_REF
- git merge $CI_COMMIT_SHA - git merge $CI_COMMIT_SHA

View file

@ -58,7 +58,7 @@ if (php_sapi_name() !== 'cli') {
use Dice\Dice; use Dice\Dice;
use Friendica\App\Mode; use Friendica\App\Mode;
use Friendica\Core\Logger\Capabilities\LogChannel; use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Security\ExAuth; use Friendica\Security\ExAuth;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -79,8 +79,8 @@ chdir($directory);
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php'); $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */ /** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class); $addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies')); $dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class,['constructParams' => [LogChannel::AUTH_JABBERED]]); $dice = $dice->addRule(LoggerInterface::class,['constructParams' => [LogChannel::AUTH_JABBERED]]);

View file

@ -26,15 +26,15 @@ if (php_sapi_name() !== 'cli') {
} }
use Dice\Dice; use Dice\Dice;
use Friendica\Core\Logger\Capabilities\LogChannel; use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\DI; use Friendica\DI;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php'); $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */ /** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class); $addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies')); $dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [LogChannel::CONSOLE]]); $dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [LogChannel::CONSOLE]]);

View file

@ -60,10 +60,10 @@ if (!file_exists('index.php') && (sizeof($_SERVER['argv']) != 0)) {
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php'); $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */ /** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class); $addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies')); $dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [Logger\Capabilities\LogChannel::DAEMON]]); $dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [Logger\Capability\LogChannel::DAEMON]]);
DI::init($dice); DI::init($dice);
\Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class)); \Friendica\Core\Logger\Handler\ErrorHandler::register($dice->create(\Psr\Log\LoggerInterface::class));

View file

@ -29,7 +29,7 @@ if (php_sapi_name() !== 'cli') {
use Dice\Dice; use Dice\Dice;
use Friendica\App; use Friendica\App;
use Friendica\App\Mode; use Friendica\App\Mode;
use Friendica\Core\Logger\Capabilities\LogChannel; use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Update; use Friendica\Core\Update;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\DI; use Friendica\DI;
@ -55,8 +55,8 @@ if (!file_exists("index.php") && (sizeof($_SERVER["argv"]) != 0)) {
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php'); $dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */ /** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class); $addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies')); $dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [LogChannel::WORKER]]); $dice = $dice->addRule(LoggerInterface::class, ['constructParams' => [LogChannel::WORKER]]);

View file

@ -77,6 +77,12 @@
"npm-asset/textcomplete": "^0.18.2", "npm-asset/textcomplete": "^0.18.2",
"npm-asset/typeahead.js": "^0.11.1" "npm-asset/typeahead.js": "^0.11.1"
}, },
"suggest": {
"ext-imagick": "For faster image processing",
"ext-redis": "To use Redis as a locking or caching provider",
"ext-pdo": "To use PDO as a database driver, has priority over mysqli unless database.disable_pdo is set",
"ext-mysqli": "To use mysqli as a databse driver"
},
"repositories": [ "repositories": [
{ {
"type": "vcs", "type": "vcs",

View file

@ -1,6 +1,6 @@
-- ------------------------------------------ -- ------------------------------------------
-- Friendica 2023.09-dev (Giant Rhubarb) -- Friendica 2023.09-dev (Giant Rhubarb)
-- DB_UPDATE_VERSION 1523 -- DB_UPDATE_VERSION 1524
-- ------------------------------------------ -- ------------------------------------------
@ -1834,8 +1834,8 @@ CREATE TABLE IF NOT EXISTS `user-contact` (
`rel` tinyint unsigned COMMENT 'The kind of the relation between the user and the contact', `rel` tinyint unsigned COMMENT 'The kind of the relation between the user and the contact',
`info` mediumtext COMMENT '', `info` mediumtext COMMENT '',
`notify_new_posts` boolean COMMENT '', `notify_new_posts` boolean COMMENT '',
`remote_self` boolean COMMENT '', `remote_self` tinyint unsigned COMMENT '0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare',
`fetch_further_information` tinyint unsigned COMMENT '', `fetch_further_information` tinyint unsigned COMMENT '0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both',
`ffi_keyword_denylist` text COMMENT '', `ffi_keyword_denylist` text COMMENT '',
`subhub` boolean COMMENT '', `subhub` boolean COMMENT '',
`hub-verify` varbinary(383) COMMENT '', `hub-verify` varbinary(383) COMMENT '',

View file

@ -10,9 +10,9 @@ This type of hook is based on the [Strategy Design Pattern](https://refactoring.
A strategy class defines a possible implementation of a given interface based on a unique name. A strategy class defines a possible implementation of a given interface based on a unique name.
Every name is possible as long as it's unique and not `null`. Every name is possible as long as it's unique and not `null`.
Using an empty name (`''`) is possible as well and should be used as the "default" implementation. Using an empty name (`''`) is possible as well and should be used as the "default" implementation.
To register a strategy, use the [`ICanRegisterInstance`](../src/Core/Hooks/Capabilities/ICanRegisterInstances.php) interface. To register a strategy, use the [`ICanRegisterInstance`](../src/Core/Hooks/Capability/ICanRegisterInstances.php) interface.
After registration, a caller can automatically create this instance with the [`ICanCreateInstances`](../src/Core/Hooks/Capabilities/ICanCreateInstances.php) interface and the chosen name. After registration, a caller can automatically create this instance with the [`ICanCreateInstances`](../src/Core/Hooks/Capability/ICanCreateInstances.php) interface and the chosen name.
This is useful in case there are different, possible implementations for the same purpose, like for logging, locking, caching, ... This is useful in case there are different, possible implementations for the same purpose, like for logging, locking, caching, ...
@ -43,11 +43,11 @@ public class ConcreteClassB implements ExampleInterface
} }
} }
/** @var \Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies $instanceRegister */ /** @var \Friendica\Core\Hooks\Capability\ICanRegisterStrategies $instanceRegister */
$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassA::class, 'A'); $instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassA::class, 'A');
$instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassB::class, 'B'); $instanceRegister->registerStrategy(ExampleInterface::class, ConcreteClassB::class, 'B');
/** @var \Friendica\Core\Hooks\Capabilities\ICanCreateInstances $instanceManager */ /** @var \Friendica\Core\Hooks\Capability\ICanCreateInstances $instanceManager */
/** @var ConcreteClassA $concreteClass */ /** @var ConcreteClassA $concreteClass */
$concreteClass = $instanceManager->create(ExampleInterface::class, 'A'); $concreteClass = $instanceManager->create(ExampleInterface::class, 'A');
@ -62,14 +62,14 @@ To avoid registering all strategies manually inside the code, Friendica introduc
There, you can register all kind of strategies in one file. There, you can register all kind of strategies in one file.
### [`HookType::STRATEGY`](../src/Core/Hooks/Capabilities/HookType.php) ### [`HookType::STRATEGY`](../src/Core/Hooks/Capability/HookType.php)
For each given interface, a list of key-value pairs can be set, where the key is the concrete implementation class and the value is an array of unique names. For each given interface, a list of key-value pairs can be set, where the key is the concrete implementation class and the value is an array of unique names.
### Example ### Example
```php ```php
use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H; use Friendica\Core\Hooks\Capability\BehavioralHookType as H;
return [ return [
H::STRATEGY => [ H::STRATEGY => [

View file

@ -30,8 +30,8 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/vendor/autoload.php';
$dice = (new Dice())->addRules(include __DIR__ . '/static/dependencies.config.php'); $dice = (new Dice())->addRules(include __DIR__ . '/static/dependencies.config.php');
/** @var \Friendica\Core\Addon\Capabilities\ICanLoadAddons $addonLoader */ /** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $dice->create(\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class); $addonLoader = $dice->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
$dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies')); $dice = $dice->addRules($addonLoader->getActiveAddonConfig('dependencies'));
$dice = $dice->addRule(Friendica\App\Mode::class, ['call' => [['determineRunMode', [false, $_SERVER], Dice::CHAIN_CALL]]]); $dice = $dice->addRule(Friendica\App\Mode::class, ['call' => [['determineRunMode', [false, $_SERVER], Dice::CHAIN_CALL]]]);

View file

@ -266,6 +266,7 @@ function item_process(array $post, array $request, bool $preview, string $return
$post['uri-id'] = -1; $post['uri-id'] = -1;
$post['author-network'] = Protocol::DFRN; $post['author-network'] = Protocol::DFRN;
$post['author-updated'] = ''; $post['author-updated'] = '';
$post['author-alias'] = '';
$post['author-gsid'] = 0; $post['author-gsid'] = 0;
$post['author-uri-id'] = ItemURI::getIdByURI($post['author-link']); $post['author-uri-id'] = ItemURI::getIdByURI($post['author-link']);
$post['owner-updated'] = ''; $post['owner-updated'] = '';

View file

@ -127,4 +127,14 @@ class BaseURL extends Uri implements UriInterface
$redirectTo = $this->__toString() . '/' . ltrim($toUrl, '/'); $redirectTo = $this->__toString() . '/' . ltrim($toUrl, '/');
System::externalRedirect($redirectTo); System::externalRedirect($redirectTo);
} }
public function isLocalUrl(string $url): bool
{
return strpos(Strings::normaliseLink($url), Strings::normaliseLink((string)$this)) === 0;
}
public function isLocalUri(UriInterface $uri): bool
{
return $this->isLocalUrl((string)$uri);
}
} }

View file

@ -22,7 +22,7 @@
namespace Friendica\Console; namespace Friendica\Console;
use Friendica\App; use Friendica\App;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Update; use Friendica\Core\Update;

View file

@ -23,8 +23,8 @@ namespace Friendica\Console;
use Asika\SimpleConsole\CommandArgsException; use Asika\SimpleConsole\CommandArgsException;
use Friendica\Model\APContact; use Friendica\Model\APContact;
use Friendica\Model\Contact;
use Friendica\Protocol\ActivityPub\Transmitter; use Friendica\Protocol\ActivityPub\Transmitter;
use Friendica\Protocol\Relay as ProtocolRelay;
/** /**
* tool to control the list of ActivityPub relay servers from the CLI * tool to control the list of ActivityPub relay servers from the CLI
@ -90,13 +90,9 @@ HELP;
} }
if ((count($this->args) == 1) && ($this->getArgument(0) == 'list')) { if ((count($this->args) == 1) && ($this->getArgument(0) == 'list')) {
$contacts = $this->dba->select('apcontact', ['url'], foreach (ProtocolRelay::getList(['url']) as $contact) {
["`type` IN (?, ?) AND `url` IN (SELECT `url` FROM `contact` WHERE `uid` = ? AND `rel` = ?)",
'Application', 'Service', 0, Contact::FRIEND]);
while ($contact = $this->dba->fetch($contacts)) {
$this->out($contact['url']); $this->out($contact['url']);
} }
$this->dba->close($contacts);
} elseif (count($this->args) == 0) { } elseif (count($this->args) == 0) {
throw new CommandArgsException('too few arguments'); throw new CommandArgsException('too few arguments');
} elseif (count($this->args) == 1) { } elseif (count($this->args) == 1) {

View file

@ -36,7 +36,7 @@ use Friendica\Model\Contact;
* @property-read int $rel * @property-read int $rel
* @property-read string $info * @property-read string $info
* @property-read bool $notifyNewPosts * @property-read bool $notifyNewPosts
* @property-read bool $isRemoteSelf * @property-read int $remoteSelf
* @property-read int $fetchFurtherInformation * @property-read int $fetchFurtherInformation
* @property-read string $ffiKeywordDenylist * @property-read string $ffiKeywordDenylist
* @property-read bool $subhub * @property-read bool $subhub
@ -47,6 +47,16 @@ use Friendica\Model\Contact;
*/ */
class LocalRelationship extends \Friendica\BaseEntity class LocalRelationship extends \Friendica\BaseEntity
{ {
// Fetch Further Information options, not a binary flag
const FFI_NONE = 0;
const FFI_INFORMATION = 1;
const FFI_KEYWORD = 3;
const FFI_BOTH = 2;
const MIRROR_DEACTIVATED = 0;
const MIRROR_OWN_POST = 2;
const MIRROR_NATIVE_RESHARE = 3;
/** @var int */ /** @var int */
protected $userId; protected $userId;
/** @var int */ /** @var int */
@ -67,9 +77,9 @@ class LocalRelationship extends \Friendica\BaseEntity
protected $info; protected $info;
/** @var bool */ /** @var bool */
protected $notifyNewPosts; protected $notifyNewPosts;
/** @var bool */ /** @var int One of MIRROR_* */
protected $isRemoteSelf; protected $remoteSelf;
/** @var int */ /** @var int One of FFI_* */
protected $fetchFurtherInformation; protected $fetchFurtherInformation;
/** @var string */ /** @var string */
protected $ffiKeywordDenylist; protected $ffiKeywordDenylist;
@ -84,7 +94,7 @@ class LocalRelationship extends \Friendica\BaseEntity
/** @var int */ /** @var int */
protected $priority; protected $priority;
public function __construct(int $userId, int $contactId, bool $blocked = false, bool $ignored = false, bool $collapsed = false, bool $hidden = false, bool $pending = false, int $rel = Contact::NOTHING, string $info = '', bool $notifyNewPosts = false, bool $isRemoteSelf = false, int $fetchFurtherInformation = 0, string $ffiKeywordDenylist = '', bool $subhub = false, string $hubVerify = '', string $protocol = Protocol::PHANTOM, ?int $rating = null, ?int $priority = null) public function __construct(int $userId, int $contactId, bool $blocked = false, bool $ignored = false, bool $collapsed = false, bool $hidden = false, bool $pending = false, int $rel = Contact::NOTHING, string $info = '', bool $notifyNewPosts = false, int $remoteSelf = self::MIRROR_DEACTIVATED, int $fetchFurtherInformation = self::FFI_NONE, string $ffiKeywordDenylist = '', bool $subhub = false, string $hubVerify = '', string $protocol = Protocol::PHANTOM, ?int $rating = null, ?int $priority = null)
{ {
$this->userId = $userId; $this->userId = $userId;
$this->contactId = $contactId; $this->contactId = $contactId;
@ -96,7 +106,7 @@ class LocalRelationship extends \Friendica\BaseEntity
$this->rel = $rel; $this->rel = $rel;
$this->info = $info; $this->info = $info;
$this->notifyNewPosts = $notifyNewPosts; $this->notifyNewPosts = $notifyNewPosts;
$this->isRemoteSelf = $isRemoteSelf; $this->remoteSelf = $remoteSelf;
$this->fetchFurtherInformation = $fetchFurtherInformation; $this->fetchFurtherInformation = $fetchFurtherInformation;
$this->ffiKeywordDenylist = $ffiKeywordDenylist; $this->ffiKeywordDenylist = $ffiKeywordDenylist;
$this->subhub = $subhub; $this->subhub = $subhub;

View file

@ -45,8 +45,8 @@ class LocalRelationship extends BaseFactory implements ICanCreateFromTableRow
$row['rel'] ?? Contact::NOTHING, $row['rel'] ?? Contact::NOTHING,
$row['info'] ?? '', $row['info'] ?? '',
$row['notify_new_posts'] ?? false, $row['notify_new_posts'] ?? false,
$row['remote_self'] ?? false, $row['remote_self'] ?? Entity\LocalRelationship::MIRROR_DEACTIVATED,
$row['fetch_further_information'] ?? 0, $row['fetch_further_information'] ?? Entity\LocalRelationship::FFI_NONE,
$row['ffi_keyword_denylist'] ?? '', $row['ffi_keyword_denylist'] ?? '',
$row['subhub'] ?? false, $row['subhub'] ?? false,
$row['hub-verify'] ?? '', $row['hub-verify'] ?? '',

View file

@ -100,7 +100,7 @@ class LocalRelationship extends \Friendica\BaseRepository
'rel' => $localRelationship->rel, 'rel' => $localRelationship->rel,
'info' => $localRelationship->info, 'info' => $localRelationship->info,
'notify_new_posts' => $localRelationship->notifyNewPosts, 'notify_new_posts' => $localRelationship->notifyNewPosts,
'remote_self' => $localRelationship->isRemoteSelf, 'remote_self' => $localRelationship->remoteSelf,
'fetch_further_information' => $localRelationship->fetchFurtherInformation, 'fetch_further_information' => $localRelationship->fetchFurtherInformation,
'ffi_keyword_denylist' => $localRelationship->ffiKeywordDenylist, 'ffi_keyword_denylist' => $localRelationship->ffiKeywordDenylist,
'subhub' => $localRelationship->subhub, 'subhub' => $localRelationship->subhub,

View file

@ -220,7 +220,8 @@ class ContactSelector
'GNU Social' => 'gnu-social', 'gnusocial' => 'gnu-social', 'hubzilla' => 'hubzilla', 'GNU Social' => 'gnu-social', 'gnusocial' => 'gnu-social', 'hubzilla' => 'hubzilla',
'mastodon' => 'mastodon', 'peertube' => 'peertube', 'pixelfed' => 'pixelfed', 'mastodon' => 'mastodon', 'peertube' => 'peertube', 'pixelfed' => 'pixelfed',
'pleroma' => 'pleroma', 'red' => 'hubzilla', 'redmatrix' => 'hubzilla', 'pleroma' => 'pleroma', 'red' => 'hubzilla', 'redmatrix' => 'hubzilla',
'socialhome' => 'social-home', 'wordpress' => 'wordpress', 'lemmy' => 'users']; 'socialhome' => 'social-home', 'wordpress' => 'wordpress', 'lemmy' => 'users',
'firefish' => 'fire', 'calckey' => 'calculator', 'kbin' => 'check'];
$search = array_keys($nets); $search = array_keys($nets);
$replace = array_values($nets); $replace = array_values($nets);

View file

@ -1158,6 +1158,40 @@ class BBCode
return $match[1] . '[url=' . $data['url'] . ']' . $data['nick'] . '[/url]'; return $match[1] . '[url=' . $data['url'] . ']' . $data['nick'] . '[/url]';
} }
/**
* Normalize links to Youtube and Vimeo to a unified format.
*
* @param string $text
* @return string
*/
private static function normalizeVideoLinks(string $text): string
{
$text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
$text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/embed\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
$text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/shorts\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
$text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
$text = preg_replace("/\[vimeo\]https?:\/\/player.vimeo.com\/video\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $text);
$text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $text);
return $text;
}
/**
* Expand Youtube and Vimeo links to
*
* @param string $text
* @return string
*/
public static function expandVideoLinks(string $text): string
{
$text = self::normalizeVideoLinks($text);
$text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '[url=https://www.youtube.com/watch?v=$1]https://www.youtube.com/watch?v=$1[/url]', $text);
$text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '[url=https://vimeo.com/$1]https://vimeo.com/$1[/url]', $text);
return $text;
}
/** /**
* Converts a BBCode message for a given URI-ID to a HTML message * Converts a BBCode message for a given URI-ID to a HTML message
* *
@ -1655,12 +1689,9 @@ class BBCode
// Backward compatibility, [iframe] support has been removed in version 2020.12 // Backward compatibility, [iframe] support has been removed in version 2020.12
$text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<a href="$1">$1</a>', $text); $text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<a href="$1">$1</a>', $text);
// Youtube extensions $text = self::normalizeVideoLinks($text);
$text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
$text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/embed\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
$text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/shorts\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
$text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $text);
// Youtube extensions
if ($try_oembed) { if ($try_oembed) {
$text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->getThemeInfoValue('videowidth') . '" height="' . $a->getThemeInfoValue('videoheight') . '" src="https://www.youtube.com/embed/$1" frameborder="0" ></iframe>', $text); $text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->getThemeInfoValue('videowidth') . '" height="' . $a->getThemeInfoValue('videoheight') . '" src="https://www.youtube.com/embed/$1" frameborder="0" ></iframe>', $text);
} else { } else {
@ -1671,9 +1702,7 @@ class BBCode
); );
} }
$text = preg_replace("/\[vimeo\]https?:\/\/player.vimeo.com\/video\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $text); // Vimeo extensions
$text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $text);
if ($try_oembed) { if ($try_oembed) {
$text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->getThemeInfoValue('videowidth') . '" height="' . $a->getThemeInfoValue('videoheight') . '" src="https://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $text); $text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->getThemeInfoValue('videowidth') . '" height="' . $a->getThemeInfoValue('videoheight') . '" src="https://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $text);
} else { } else {

View file

@ -102,7 +102,7 @@ class Widget
public static function unavailableNetworks(): array public static function unavailableNetworks(): array
{ {
// Always hide content from these networks // Always hide content from these networks
$networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET, Protocol::ZOT]; $networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET, Protocol::TWITTER, Protocol::ZOT];
if (!Addon::isEnabled("discourse")) { if (!Addon::isEnabled("discourse")) {
$networks[] = Protocol::DISCOURSE; $networks[] = Protocol::DISCOURSE;
@ -116,10 +116,6 @@ class Widget
$networks[] = Protocol::PUMPIO; $networks[] = Protocol::PUMPIO;
} }
if (!Addon::isEnabled("twitter")) {
$networks[] = Protocol::TWITTER;
}
if (!Addon::isEnabled("tumblr")) { if (!Addon::isEnabled("tumblr")) {
$networks[] = Protocol::TUMBLR; $networks[] = Protocol::TUMBLR;
} }

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\Addon\Capabilities; namespace Friendica\Core\Addon\Capability;
/** /**
* Interface for loading Addons specific content * Interface for loading Addons specific content

View file

@ -21,7 +21,7 @@
namespace Friendica\Core\Addon\Model; namespace Friendica\Core\Addon\Model;
use Friendica\Core\Addon\Capabilities\ICanLoadAddons; use Friendica\Core\Addon\Capability\ICanLoadAddons;
use Friendica\Core\Addon\Exception\AddonInvalidConfigFileException; use Friendica\Core\Addon\Exception\AddonInvalidConfigFileException;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Util\Strings; use Friendica\Util\Strings;

View file

@ -21,16 +21,13 @@
namespace Friendica\Core\Cache\Factory; namespace Friendica\Core\Cache\Factory;
use Friendica\App\BaseURL;
use Friendica\Core\Cache\Enum;
use Friendica\Core\Cache\Capability\ICanCache; use Friendica\Core\Cache\Capability\ICanCache;
use Friendica\Core\Cache\Exception\CachePersistenceException; use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException; use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Cache\Type; use Friendica\Core\Cache\Type;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Database\Database; use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Util\Profiler; use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
/** /**
* Class CacheFactory * Class CacheFactory
@ -44,59 +41,32 @@ class Cache
/** /**
* @var string The default cache if nothing set * @var string The default cache if nothing set
*/ */
const DEFAULT_TYPE = Enum\Type::DATABASE; const DEFAULT_TYPE = Type\DatabaseCache::NAME;
/** @var ICanCreateInstances */
protected $instanceCreator;
/** @var IManageConfigValues */
protected $config;
/** @var Profiler */
protected $profiler;
/** public function __construct(ICanCreateInstances $instanceCreator, IManageConfigValues $config, Profiler $profiler)
* @var IManageConfigValues The IConfiguration to read parameters out of the config
*/
private $config;
/**
* @var Database The database connection in case that the cache is used the dba connection
*/
private $dba;
/**
* @var string The hostname, used as Prefix for Caching
*/
private $hostname;
/**
* @var Profiler The optional profiler if the cached should be profiled
*/
private $profiler;
/**
* @var LoggerInterface The Friendica Logger
*/
private $logger;
public function __construct(BaseURL $baseURL, IManageConfigValues $config, Database $dba, Profiler $profiler, LoggerInterface $logger)
{ {
$this->hostname = $baseURL->getHost();
$this->config = $config; $this->config = $config;
$this->dba = $dba; $this->instanceCreator = $instanceCreator;
$this->profiler = $profiler; $this->profiler = $profiler;
$this->logger = $logger;
} }
/** /**
* This method creates a CacheDriver for distributed caching with the given cache driver name * This method creates a CacheDriver for distributed caching
*
* @param string|null $type The cache type to create (default is per config)
* *
* @return ICanCache The instance of the CacheDriver * @return ICanCache The instance of the CacheDriver
* *
* @throws InvalidCacheDriverException In case the underlying cache driver isn't valid or not configured properly * @throws InvalidCacheDriverException In case the underlying cache driver isn't valid or not configured properly
* @throws CachePersistenceException In case the underlying cache has errors during persistence * @throws CachePersistenceException In case the underlying cache has errors during persistence
*/ */
public function createDistributed(string $type = null): ICanCache public function createDistributed(): ICanCache
{ {
if ($type === Enum\Type::APCU) { return $this->create($this->config->get('system', 'distributed_cache_driver', self::DEFAULT_TYPE));
throw new InvalidCacheDriverException('apcu doesn\'t support distributed caching.');
}
return $this->create($type ?? $this->config->get('system', 'distributed_cache_driver', self::DEFAULT_TYPE));
} }
/** /**
@ -117,31 +87,17 @@ class Cache
/** /**
* Creates a new Cache instance * Creates a new Cache instance
* *
* @param string $type The type of cache * @param string $strategy The strategy, which cache instance should be used
* *
* @return ICanCache * @return ICanCache
* *
* @throws InvalidCacheDriverException In case the underlying cache driver isn't valid or not configured properly * @throws InvalidCacheDriverException In case the underlying cache driver isn't valid or not configured properly
* @throws CachePersistenceException In case the underlying cache has errors during persistence * @throws CachePersistenceException In case the underlying cache has errors during persistence
*/ */
protected function create(string $type): ICanCache protected function create(string $strategy): ICanCache
{ {
switch ($type) { /** @var ICanCache $cache */
case Enum\Type::MEMCACHE: $cache = $this->instanceCreator->create(ICanCache::class, $strategy);
$cache = new Type\MemcacheCache($this->hostname, $this->config);
break;
case Enum\Type::MEMCACHED:
$cache = new Type\MemcachedCache($this->hostname, $this->config, $this->logger);
break;
case Enum\Type::REDIS:
$cache = new Type\RedisCache($this->hostname, $this->config);
break;
case Enum\Type::APCU:
$cache = new Type\APCuCache($this->hostname);
break;
default:
$cache = new Type\DatabaseCache($this->hostname, $this->dba);
}
$profiling = $this->config->get('system', 'profiling', false); $profiling = $this->config->get('system', 'profiling', false);

View file

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory; use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException; use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
/** /**
@ -31,12 +30,12 @@ use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
*/ */
class APCuCache extends AbstractCache implements ICanCacheInMemory class APCuCache extends AbstractCache implements ICanCacheInMemory
{ {
const NAME = 'apcu';
use CompareSetTrait; use CompareSetTrait;
use CompareDeleteTrait; use CompareDeleteTrait;
/** /**
* @param string $hostname
*
* @throws InvalidCacheDriverException * @throws InvalidCacheDriverException
*/ */
public function __construct(string $hostname) public function __construct(string $hostname)
@ -173,12 +172,4 @@ class APCuCache extends AbstractCache implements ICanCacheInMemory
return true; return true;
} }
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::APCU;
}
} }

View file

@ -28,6 +28,8 @@ use Friendica\Core\Cache\Capability\ICanCache;
*/ */
abstract class AbstractCache implements ICanCache abstract class AbstractCache implements ICanCache
{ {
const NAME = '';
/** /**
* @var string The hostname * @var string The hostname
*/ */
@ -105,4 +107,10 @@ abstract class AbstractCache implements ICanCache
return $result; return $result;
} }
} }
/** {@inheritDoc} */
public function getName(): string
{
return static::NAME;
}
} }

View file

@ -29,6 +29,8 @@ use Friendica\Core\Cache\Enum;
*/ */
class ArrayCache extends AbstractCache implements ICanCacheInMemory class ArrayCache extends AbstractCache implements ICanCacheInMemory
{ {
const NAME = 'array';
use CompareDeleteTrait; use CompareDeleteTrait;
/** @var array Array with the cached data */ /** @var array Array with the cached data */
@ -108,12 +110,4 @@ class ArrayCache extends AbstractCache implements ICanCacheInMemory
return false; return false;
} }
} }
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Enum\Type::ARRAY;
}
} }

View file

@ -32,6 +32,8 @@ use Friendica\Util\DateTimeFormat;
*/ */
class DatabaseCache extends AbstractCache implements ICanCache class DatabaseCache extends AbstractCache implements ICanCache
{ {
const NAME = 'database';
/** /**
* @var Database * @var Database
*/ */
@ -154,12 +156,4 @@ class DatabaseCache extends AbstractCache implements ICanCache
throw new CachePersistenceException('Cannot clear cache', $exception); throw new CachePersistenceException('Cannot clear cache', $exception);
} }
} }
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Enum\Type::DATABASE;
}
} }

View file

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory; use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException; use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException; use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
@ -34,6 +33,8 @@ use Memcache;
*/ */
class MemcacheCache extends AbstractCache implements ICanCacheInMemory class MemcacheCache extends AbstractCache implements ICanCacheInMemory
{ {
const NAME = 'memcache';
use CompareSetTrait; use CompareSetTrait;
use CompareDeleteTrait; use CompareDeleteTrait;
use MemcacheCommandTrait; use MemcacheCommandTrait;
@ -169,12 +170,4 @@ class MemcacheCache extends AbstractCache implements ICanCacheInMemory
$cacheKey = $this->getCacheKey($key); $cacheKey = $this->getCacheKey($key);
return $this->memcache->add($cacheKey, serialize($value), MEMCACHE_COMPRESSED, $ttl); return $this->memcache->add($cacheKey, serialize($value), MEMCACHE_COMPRESSED, $ttl);
} }
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::MEMCACHE;
}
} }

View file

@ -23,7 +23,6 @@ namespace Friendica\Core\Cache\Type;
use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory; use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException; use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException; use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
@ -35,6 +34,8 @@ use Psr\Log\LoggerInterface;
*/ */
class MemcachedCache extends AbstractCache implements ICanCacheInMemory class MemcachedCache extends AbstractCache implements ICanCacheInMemory
{ {
const NAME = 'memcached';
use CompareSetTrait; use CompareSetTrait;
use CompareDeleteTrait; use CompareDeleteTrait;
use MemcacheCommandTrait; use MemcacheCommandTrait;
@ -185,12 +186,4 @@ class MemcachedCache extends AbstractCache implements ICanCacheInMemory
$cacheKey = $this->getCacheKey($key); $cacheKey = $this->getCacheKey($key);
return $this->memcached->add($cacheKey, $value, $ttl); return $this->memcached->add($cacheKey, $value, $ttl);
} }
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::MEMCACHED;
}
} }

View file

@ -21,10 +21,8 @@
namespace Friendica\Core\Cache\Type; namespace Friendica\Core\Cache\Type;
use Exception;
use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Cache\Capability\ICanCacheInMemory; use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum\Type;
use Friendica\Core\Cache\Exception\CachePersistenceException; use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Cache\Exception\InvalidCacheDriverException; use Friendica\Core\Cache\Exception\InvalidCacheDriverException;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
@ -35,6 +33,8 @@ use Redis;
*/ */
class RedisCache extends AbstractCache implements ICanCacheInMemory class RedisCache extends AbstractCache implements ICanCacheInMemory
{ {
const NAME = 'redis';
/** /**
* @var Redis * @var Redis
*/ */
@ -57,20 +57,30 @@ class RedisCache extends AbstractCache implements ICanCacheInMemory
$redis_host = $config->get('system', 'redis_host'); $redis_host = $config->get('system', 'redis_host');
$redis_port = $config->get('system', 'redis_port'); $redis_port = $config->get('system', 'redis_port');
$redis_pw = $config->get('system', 'redis_password'); $redis_pw = $config->get('system', 'redis_password');
$redis_db = $config->get('system', 'redis_db', 0); $redis_db = (int)$config->get('system', 'redis_db', 0);
if (!empty($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) { try {
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available'); if (is_numeric($redis_port) && $redis_port > -1) {
} elseif (!@$this->redis->connect($redis_host)) { $connection_string = $redis_host . ':' . $redis_port;
throw new CachePersistenceException('Expected Redis server at ' . $redis_host . ' isn\'t available'); if (!@$this->redis->connect($redis_host, $redis_port)) {
throw new CachePersistenceException('Expected Redis server at ' . $connection_string . " isn't available");
}
} else {
$connection_string = $redis_host;
if (!@$this->redis->connect($redis_host)) {
throw new CachePersistenceException('Expected Redis server at ' . $connection_string . ' isn\'t available');
}
} }
if (!empty($redis_pw) && !$this->redis->auth($redis_pw)) { if (!empty($redis_pw) && !$this->redis->auth($redis_pw)) {
throw new CachePersistenceException('Cannot authenticate redis server at ' . $redis_host . ':' . $redis_port); throw new CachePersistenceException('Cannot authenticate redis server at ' . $connection_string);
} }
if ($redis_db !== 0 && !$this->redis->select($redis_db)) { if ($redis_db !== 0 && !$this->redis->select($redis_db)) {
throw new CachePersistenceException('Cannot switch to redis db ' . $redis_db . ' at ' . $redis_host . ':' . $redis_port); throw new CachePersistenceException('Cannot switch to redis db ' . $redis_db . ' at ' . $connection_string);
}
} catch (\RedisException $exception) {
throw new CachePersistenceException('Redis connection fails unexpectedly', $exception);
} }
} }
@ -211,12 +221,4 @@ class RedisCache extends AbstractCache implements ICanCacheInMemory
$this->redis->unwatch(); $this->redis->unwatch();
return false; return false;
} }
/**
* {@inheritDoc}
*/
public function getName(): string
{
return Type::REDIS;
}
} }

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\Hooks\Capabilities; namespace Friendica\Core\Hooks\Capability;
/** /**
* An enum of hook types, based on behavioral design patterns * An enum of hook types, based on behavioral design patterns

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\Hooks\Capabilities; namespace Friendica\Core\Hooks\Capability;
/** /**
* creates special instances for given classes * creates special instances for given classes

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\Hooks\Capabilities; namespace Friendica\Core\Hooks\Capability;
use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException; use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;

View file

@ -22,8 +22,8 @@
namespace Friendica\Core\Hooks\Model; namespace Friendica\Core\Hooks\Model;
use Dice\Dice; use Dice\Dice;
use Friendica\Core\Hooks\Capabilities\ICanCreateInstances; use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies; use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Exceptions\HookInstanceException; use Friendica\Core\Hooks\Exceptions\HookInstanceException;
use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException; use Friendica\Core\Hooks\Exceptions\HookRegisterArgumentException;
use Friendica\Core\Hooks\Util\StrategiesFileManager; use Friendica\Core\Hooks\Util\StrategiesFileManager;
@ -49,11 +49,11 @@ class DiceInstanceManager implements ICanCreateInstances, ICanRegisterStrategies
/** {@inheritDoc} */ /** {@inheritDoc} */
public function registerStrategy(string $interface, string $class, ?string $name = null): ICanRegisterStrategies public function registerStrategy(string $interface, string $class, ?string $name = null): ICanRegisterStrategies
{ {
if (!empty($this->instance[$interface][$name])) { if (!empty($this->instance[$interface][strtolower($name)])) {
throw new HookRegisterArgumentException(sprintf('A class with the name %s is already set for the interface %s', $name, $interface)); throw new HookRegisterArgumentException(sprintf('A class with the name %s is already set for the interface %s', $name, $interface));
} }
$this->instance[$interface][$name] = $class; $this->instance[$interface][strtolower($name)] = $class;
return $this; return $this;
} }
@ -61,10 +61,10 @@ class DiceInstanceManager implements ICanCreateInstances, ICanRegisterStrategies
/** {@inheritDoc} */ /** {@inheritDoc} */
public function create(string $class, string $strategy, array $arguments = []): object public function create(string $class, string $strategy, array $arguments = []): object
{ {
if (empty($this->instance[$class][$strategy])) { if (empty($this->instance[$class][strtolower($strategy)])) {
throw new HookInstanceException(sprintf('The class with the name %s isn\'t registered for the class or interface %s', $strategy, $class)); throw new HookInstanceException(sprintf('The class with the name %s isn\'t registered for the class or interface %s', $strategy, $class));
} }
return $this->dice->create($this->instance[$class][$strategy], $arguments); return $this->dice->create($this->instance[$class][strtolower($strategy)], $arguments);
} }
} }

View file

@ -21,8 +21,8 @@
namespace Friendica\Core\Hooks\Util; namespace Friendica\Core\Hooks\Util;
use Friendica\Core\Addon\Capabilities\ICanLoadAddons; use Friendica\Core\Addon\Capability\ICanLoadAddons;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies; use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Exceptions\HookConfigException; use Friendica\Core\Hooks\Exceptions\HookConfigException;
/** /**
@ -30,6 +30,11 @@ use Friendica\Core\Hooks\Exceptions\HookConfigException;
*/ */
class StrategiesFileManager class StrategiesFileManager
{ {
/**
* The default hook-file-key of strategies
* -> it's an empty string to cover empty/missing config values
*/
const STRATEGY_DEFAULT_KEY = '';
const STATIC_DIR = 'static'; const STATIC_DIR = 'static';
const CONFIG_NAME = 'strategies'; const CONFIG_NAME = 'strategies';

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\KeyValueStorage\Capabilities; namespace Friendica\Core\KeyValueStorage\Capability;
use Friendica\Core\KeyValueStorage\Exceptions\KeyValueStoragePersistenceException; use Friendica\Core\KeyValueStorage\Exceptions\KeyValueStoragePersistenceException;

View file

@ -19,17 +19,17 @@
* *
*/ */
namespace Friendica\Core\Cache\Enum; namespace Friendica\Core\KeyValueStorage\Factory;
/** use Friendica\Core\Hooks\Capability\ICanCreateInstances;
* Enumeration for cache types use Friendica\Core\Hooks\Util\StrategiesFileManager;
*/ use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
abstract class Type
class KeyValueStorage
{ {
const APCU = 'apcu'; public function create(ICanCreateInstances $instanceCreator): IManageKeyValuePairs
const REDIS = 'redis'; {
const ARRAY = 'array'; /** @var IManageKeyValuePairs */
const MEMCACHE = 'memcache'; return $instanceCreator->create(IManageKeyValuePairs::class, StrategiesFileManager::STRATEGY_DEFAULT_KEY);
const DATABASE = 'database'; }
const MEMCACHED = 'memcached';
} }

View file

@ -21,13 +21,15 @@
namespace Friendica\Core\KeyValueStorage\Type; namespace Friendica\Core\KeyValueStorage\Type;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
/** /**
* An abstract helper class for Key-Value storage classes * An abstract helper class for Key-Value storage classes
*/ */
abstract class AbstractKeyValueStorage implements IManageKeyValuePairs abstract class AbstractKeyValueStorage implements IManageKeyValuePairs
{ {
const NAME = '';
/** {@inheritDoc} */ /** {@inheritDoc} */
public function get(string $key) public function get(string $key)
{ {

View file

@ -30,6 +30,7 @@ use Friendica\Database\Database;
*/ */
class DBKeyValueStorage extends AbstractKeyValueStorage class DBKeyValueStorage extends AbstractKeyValueStorage
{ {
const NAME = 'database';
const DB_KEY_VALUE_TABLE = 'key-value'; const DB_KEY_VALUE_TABLE = 'key-value';
/** @var Database */ /** @var Database */

View file

@ -21,7 +21,7 @@
namespace Friendica\Core\Lock\Enum; namespace Friendica\Core\Lock\Enum;
use Friendica\Core\Cache\Enum\Type as CacheType; use Friendica\Core\Cache\Type\DatabaseCache;
/** /**
* Enumeration for lock types * Enumeration for lock types
@ -30,6 +30,6 @@ use Friendica\Core\Cache\Enum\Type as CacheType;
*/ */
abstract class Type abstract class Type
{ {
const DATABASE = CacheType::DATABASE; const DATABASE = DatabaseCache::NAME;
const SEMAPHORE = 'semaphore'; const SEMAPHORE = 'semaphore';
} }

View file

@ -23,10 +23,10 @@ namespace Friendica\Core\Lock\Factory;
use Friendica\Core\Cache\Factory\Cache; use Friendica\Core\Cache\Factory\Cache;
use Friendica\Core\Cache\Capability\ICanCacheInMemory; use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Enum; use Friendica\Core\Cache\Type as CacheType;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Lock\Capability\ICanLock; use Friendica\Core\Lock\Capability\ICanLock;
use Friendica\Core\Lock\Type; use Friendica\Core\Lock\Type as LockType;
use Friendica\Database\Database; use Friendica\Database\Database;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -78,20 +78,20 @@ class Lock
try { try {
switch ($lock_type) { switch ($lock_type) {
case Enum\Type::MEMCACHE: case CacheType\MemcacheCache::NAME:
case Enum\Type::MEMCACHED: case CacheType\MemcachedCache::NAME:
case Enum\Type::REDIS: case CacheType\RedisCache::NAME:
case Enum\Type::APCU: case CacheType\APCuCache::NAME:
$cache = $this->cacheFactory->createLocal($lock_type); $cache = $this->cacheFactory->createLocal($lock_type);
if ($cache instanceof ICanCacheInMemory) { if ($cache instanceof ICanCacheInMemory) {
return new Type\CacheLock($cache); return new LockType\CacheLock($cache);
} else { } else {
throw new \Exception(sprintf('Incompatible cache driver \'%s\' for lock used', $lock_type)); throw new \Exception(sprintf('Incompatible cache driver \'%s\' for lock used', $lock_type));
} }
case 'database': case 'database':
return new Type\DatabaseLock($this->dba); return new LockType\DatabaseLock($this->dba);
case 'semaphore': case 'semaphore':
return new Type\SemaphoreLock(); return new LockType\SemaphoreLock();
default: default:
return self::useAutoDriver(); return self::useAutoDriver();
} }
@ -116,7 +116,7 @@ class Lock
// 1. Try to use Semaphores for - local - locking // 1. Try to use Semaphores for - local - locking
if (function_exists('sem_get')) { if (function_exists('sem_get')) {
try { try {
return new Type\SemaphoreLock(); return new LockType\SemaphoreLock();
} catch (\Exception $exception) { } catch (\Exception $exception) {
$this->logger->warning('Using Semaphore driver for locking failed.', ['exception' => $exception]); $this->logger->warning('Using Semaphore driver for locking failed.', ['exception' => $exception]);
} }
@ -124,11 +124,11 @@ class Lock
// 2. Try to use Cache Locking (don't use the DB-Cache Locking because it works different!) // 2. Try to use Cache Locking (don't use the DB-Cache Locking because it works different!)
$cache_type = $this->config->get('system', 'cache_driver', 'database'); $cache_type = $this->config->get('system', 'cache_driver', 'database');
if ($cache_type != Enum\Type::DATABASE) { if ($cache_type != CacheType\DatabaseCache::NAME) {
try { try {
$cache = $this->cacheFactory->createLocal($cache_type); $cache = $this->cacheFactory->createLocal($cache_type);
if ($cache instanceof ICanCacheInMemory) { if ($cache instanceof ICanCacheInMemory) {
return new Type\CacheLock($cache); return new LockType\CacheLock($cache);
} }
} catch (\Exception $exception) { } catch (\Exception $exception) {
$this->logger->warning('Using Cache driver for locking failed.', ['exception' => $exception]); $this->logger->warning('Using Cache driver for locking failed.', ['exception' => $exception]);
@ -136,6 +136,6 @@ class Lock
} }
// 3. Use Database Locking as a Fallback // 3. Use Database Locking as a Fallback
return new Type\DatabaseLock($this->dba); return new LockType\DatabaseLock($this->dba);
} }
} }

View file

@ -36,7 +36,7 @@ abstract class AbstractLock implements ICanLock
/** /**
* Check if we've locally acquired a lock * Check if we've locally acquired a lock
* *
* @param string key The Name of the lock * @param string $key The Name of the lock
* *
* @return bool Returns true if the lock is set * @return bool Returns true if the lock is set
*/ */

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\Logger\Capabilities; namespace Friendica\Core\Logger\Capability;
/** /**
* Whenever a logging specific check is necessary, use this interface to encapsulate and centralize this logic * Whenever a logging specific check is necessary, use this interface to encapsulate and centralize this logic

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\Logger\Capabilities; namespace Friendica\Core\Logger\Capability;
interface IHaveCallIntrospections interface IHaveCallIntrospections
{ {

View file

@ -19,7 +19,7 @@
* *
*/ */
namespace Friendica\Core\Logger\Capabilities; namespace Friendica\Core\Logger\Capability;
/** /**
* An enum class for the Log channels * An enum class for the Log channels

View file

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Factory; namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
/** /**

View file

@ -22,8 +22,8 @@
namespace Friendica\Core\Logger\Factory; namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hooks\Capabilities\ICanCreateInstances; use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Logger\Capabilities\LogChannel; use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Type\ProfilerLogger as ProfilerLoggerClass; use Friendica\Core\Logger\Type\ProfilerLogger as ProfilerLoggerClass;
use Friendica\Util\Profiler; use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;

View file

@ -22,7 +22,7 @@
namespace Friendica\Core\Logger\Factory; namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Capabilities\LogChannel; use Friendica\Core\Logger\Capability\LogChannel;
use Friendica\Core\Logger\Exception\LoggerArgumentException; use Friendica\Core\Logger\Exception\LoggerArgumentException;
use Friendica\Core\Logger\Exception\LoggerException; use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Core\Logger\Exception\LogLevelException; use Friendica\Core\Logger\Exception\LogLevelException;

View file

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Type; namespace Friendica\Core\Logger\Type;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LoggerException; use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Util\Strings; use Friendica\Util\Strings;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -38,6 +38,8 @@ use Psr\Log\LogLevel;
*/ */
abstract class AbstractLogger implements LoggerInterface abstract class AbstractLogger implements LoggerInterface
{ {
const NAME = '';
/** /**
* The output channel of this logger * The output channel of this logger
* @var string * @var string

View file

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Type; namespace Friendica\Core\Logger\Type;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LoggerException; use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Core\Logger\Exception\LogLevelException; use Friendica\Core\Logger\Exception\LogLevelException;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
@ -32,6 +32,8 @@ use Psr\Log\LogLevel;
*/ */
class StreamLogger extends AbstractLogger class StreamLogger extends AbstractLogger
{ {
const NAME = 'stream';
/** /**
* The minimum loglevel at which this logger will be triggered * The minimum loglevel at which this logger will be triggered
* @var string * @var string

View file

@ -21,7 +21,7 @@
namespace Friendica\Core\Logger\Type; namespace Friendica\Core\Logger\Type;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Exception\LoggerException; use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Core\Logger\Exception\LogLevelException; use Friendica\Core\Logger\Exception\LogLevelException;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
@ -32,6 +32,8 @@ use Psr\Log\LogLevel;
*/ */
class SyslogLogger extends AbstractLogger class SyslogLogger extends AbstractLogger
{ {
const NAME = 'syslog';
const IDENT = 'Friendica'; const IDENT = 'Friendica';
/** @var int The default syslog flags */ /** @var int The default syslog flags */

View file

@ -22,7 +22,7 @@
namespace Friendica\Core\Logger\Util; namespace Friendica\Core\Logger\Util;
use Friendica\App\Request; use Friendica\App\Request;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
/** /**
* Get Introspection information about the current call * Get Introspection information about the current call

View file

@ -23,7 +23,7 @@ namespace Friendica\Core\Logger\Util;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Logger\Capabilities\ICheckLoggerSettings; use Friendica\Core\Logger\Capability\ICheckLoggerSettings;
use Friendica\Core\Logger\Exception\LoggerUnusableException; use Friendica\Core\Logger\Exception\LoggerUnusableException;
/** {@inheritDoc} */ /** {@inheritDoc} */

View file

@ -22,28 +22,16 @@
namespace Friendica\Core\PConfig\Factory; namespace Friendica\Core\PConfig\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
use Friendica\Core\PConfig\Repository;
use Friendica\Core\PConfig\Type;
use Friendica\Core\PConfig\ValueObject;
class PConfig class PConfig
{ {
/** public function create(ICanCreateInstances $instanceCreator, IManageConfigValues $config): IManagePersonalConfigValues
* @param IManageConfigValues $config The config
* @param ValueObject\Cache $pConfigCache The personal config cache
* @param Repository\PConfig $configRepo The configuration model
*
* @return IManagePersonalConfigValues
*/
public function create(IManageConfigValues $config, ValueObject\Cache $pConfigCache, Repository\PConfig $configRepo): IManagePersonalConfigValues
{ {
if ($config->get('system', 'config_adapter') === 'preload') { $strategy = $config->get('system', 'config_adapter');
$configuration = new Type\PreloadPConfig($pConfigCache, $configRepo);
} else {
$configuration = new Type\JitPConfig($pConfigCache, $configRepo);
}
return $configuration; /** @var IManagePersonalConfigValues */
return $instanceCreator->create(IManagePersonalConfigValues::class, $strategy);
} }
} }

View file

@ -34,6 +34,8 @@ use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
*/ */
abstract class AbstractPConfigValues implements IManagePersonalConfigValues abstract class AbstractPConfigValues implements IManagePersonalConfigValues
{ {
const NAME = '';
/** /**
* @var Cache * @var Cache
*/ */

View file

@ -33,6 +33,8 @@ use Friendica\Core\PConfig\ValueObject;
*/ */
class JitPConfig extends AbstractPConfigValues class JitPConfig extends AbstractPConfigValues
{ {
const NAME = 'jit';
/** /**
* @var array Array of already loaded db values (even if there was no value) * @var array Array of already loaded db values (even if there was no value)
*/ */

View file

@ -32,6 +32,8 @@ use Friendica\Core\PConfig\ValueObject;
*/ */
class PreloadPConfig extends AbstractPConfigValues class PreloadPConfig extends AbstractPConfigValues
{ {
const NAME = 'preload';
/** @var array */ /** @var array */
private $config_loaded; private $config_loaded;

View file

@ -93,6 +93,13 @@ interface IHandleUserSessions extends IHandleSessions
*/ */
public function isSiteAdmin(): bool; public function isSiteAdmin(): bool;
/**
* Check if current user is a moderator.
*
* @return bool true if user is a moderator
*/
public function isModerator(): bool;
/** /**
* Returns User ID of the managed user in case it's a different identity * Returns User ID of the managed user in case it's a different identity
* *

View file

@ -22,8 +22,8 @@
namespace Friendica\Core\Session\Factory; namespace Friendica\Core\Session\Factory;
use Friendica\App; use Friendica\App;
use Friendica\Core\Cache\Enum;
use Friendica\Core\Cache\Factory\Cache; use Friendica\Core\Cache\Factory\Cache;
use Friendica\Core\Cache\Type\DatabaseCache;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Session\Capability\IHandleSessions; use Friendica\Core\Session\Capability\IHandleSessions;
use Friendica\Core\Session\Type; use Friendica\Core\Session\Type;
@ -74,7 +74,7 @@ class Session
$cache = $cacheFactory->createDistributed(); $cache = $cacheFactory->createDistributed();
// In case we're using the db as cache driver, use the native db session, not the cache // In case we're using the db as cache driver, use the native db session, not the cache
if ($config->get('system', 'cache_driver') === Enum\Type::DATABASE) { if ($config->get('system', 'cache_driver') === DatabaseCache::NAME) {
$handler = new Handler\Database($dba, $logger, $server); $handler = new Handler\Database($dba, $logger, $server);
} else { } else {
$handler = new Handler\Cache($cache, $logger); $handler = new Handler\Cache($cache, $logger);

View file

@ -139,6 +139,12 @@ class UserSession implements IHandleUserSessions
return User::isSiteAdmin($this->getLocalUserId()); return User::isSiteAdmin($this->getLocalUserId());
} }
/** {@inheritDoc} */
public function isModerator(): bool
{
return User::isModerator($this->getLocalUserId());
}
/** {@inheritDoc} */ /** {@inheritDoc} */
public function setVisitorsContacts(string $my_url) public function setVisitorsContacts(string $my_url)
{ {

View file

@ -22,7 +22,7 @@
namespace Friendica; namespace Friendica;
use Dice\Dice; use Dice\Dice;
use Friendica\Core\Logger\Capabilities\ICheckLoggerSettings; use Friendica\Core\Logger\Capability\ICheckLoggerSettings;
use Friendica\Core\Logger\Util\LoggerSettingsCheck; use Friendica\Core\Logger\Util\LoggerSettingsCheck;
use Friendica\Core\Session\Capability\IHandleSessions; use Friendica\Core\Session\Capability\IHandleSessions;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
@ -210,9 +210,9 @@ abstract class DI
return self::$dice->create(Core\Config\Util\ConfigFileManager::class); return self::$dice->create(Core\Config\Util\ConfigFileManager::class);
} }
public static function keyValue(): Core\KeyValueStorage\Capabilities\IManageKeyValuePairs public static function keyValue(): Core\KeyValueStorage\Capability\IManageKeyValuePairs
{ {
return self::$dice->create(Core\KeyValueStorage\Capabilities\IManageKeyValuePairs::class); return self::$dice->create(Core\KeyValueStorage\Capability\IManageKeyValuePairs::class);
} }
/** /**

View file

@ -584,6 +584,14 @@ class APContact
*/ */
public static function isRelay(array $apcontact): bool public static function isRelay(array $apcontact): bool
{ {
if (in_array($apcontact['type'], ['Person', 'Organization'])) {
return false;
}
if (($apcontact['type'] == 'Service') && empty($apcontact['outbox']) && empty($apcontact['sharedinbox']) && empty($apcontact['following']) && empty($apcontact['followers']) && empty($apcontact['statuses_count'])) {
return true;
}
if (empty($apcontact['nick']) || $apcontact['nick'] != 'relay') { if (empty($apcontact['nick']) || $apcontact['nick'] != 'relay') {
return false; return false;
} }

View file

@ -23,6 +23,7 @@ namespace Friendica\Model;
use Friendica\Contact\Avatar; use Friendica\Contact\Avatar;
use Friendica\Contact\Introduction\Exception\IntroductionNotFoundException; use Friendica\Contact\Introduction\Exception\IntroductionNotFoundException;
use Friendica\Contact\LocalRelationship\Entity\LocalRelationship;
use Friendica\Content\Conversation as ConversationContent; use Friendica\Content\Conversation as ConversationContent;
use Friendica\Content\Pager; use Friendica\Content\Pager;
use Friendica\Content\Text\HTML; use Friendica\Content\Text\HTML;
@ -111,10 +112,14 @@ class Contact
* @} * @}
*/ */
const MIRROR_DEACTIVATED = 0; /** @deprecated Use Entity\LocalRelationship::MIRROR_DEACTIVATED instead */
const MIRROR_FORWARDED = 1; // Deprecated, now does the same like MIRROR_OWN_POST const MIRROR_DEACTIVATED = LocalRelationship::MIRROR_DEACTIVATED;
const MIRROR_OWN_POST = 2; /** @deprecated Now does the same as MIRROR_OWN_POST */
const MIRROR_NATIVE_RESHARE = 3; const MIRROR_FORWARDED = 1;
/** @deprecated Use Entity\LocalRelationship::MIRROR_OWN_POST instead */
const MIRROR_OWN_POST = LocalRelationship::MIRROR_OWN_POST;
/** @deprecated Use Entity\LocalRelationship::MIRROR_NATIVE_RESHARE instead */
const MIRROR_NATIVE_RESHARE = LocalRelationship::MIRROR_NATIVE_RESHARE;
/** /**
* @param array $fields Array of selected fields, empty for all * @param array $fields Array of selected fields, empty for all
@ -799,7 +804,7 @@ class Contact
return false; return false;
} }
$fields = ['uid', 'nickname', 'page-flags', 'account-type', 'prvkey', 'pubkey']; $fields = ['uid', 'username', 'nickname', 'page-flags', 'account-type', 'prvkey', 'pubkey'];
$user = DBA::selectFirst('user', $fields, ['uid' => $uid, 'account_expired' => false]); $user = DBA::selectFirst('user', $fields, ['uid' => $uid, 'account_expired' => false]);
if (!DBA::isResult($user)) { if (!DBA::isResult($user)) {
return false; return false;
@ -818,7 +823,7 @@ class Contact
$url = DI::baseUrl() . '/profile/' . $user['nickname']; $url = DI::baseUrl() . '/profile/' . $user['nickname'];
$fields = [ $fields = [
'name' => $profile['name'], 'name' => $user['username'],
'nick' => $user['nickname'], 'nick' => $user['nickname'],
'avatar-date' => $self['avatar-date'], 'avatar-date' => $self['avatar-date'],
'location' => Profile::formatLocation($profile), 'location' => Profile::formatLocation($profile),
@ -841,7 +846,6 @@ class Contact
'confirm' => DI::baseUrl() . '/dfrn_confirm/' . $user['nickname'], 'confirm' => DI::baseUrl() . '/dfrn_confirm/' . $user['nickname'],
]; ];
$avatar = Photo::selectFirst(['resource-id', 'type'], ['uid' => $uid, 'profile' => true]); $avatar = Photo::selectFirst(['resource-id', 'type'], ['uid' => $uid, 'profile' => true]);
if (DBA::isResult($avatar)) { if (DBA::isResult($avatar)) {
if ($update_avatar) { if ($update_avatar) {

View file

@ -21,6 +21,7 @@
namespace Friendica\Model; namespace Friendica\Model;
use Friendica\Contact\LocalRelationship\Entity\LocalRelationship;
use Friendica\Content\Text\BBCode; use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML; use Friendica\Content\Text\HTML;
use Friendica\Core\Hook; use Friendica\Core\Hook;
@ -2333,12 +2334,7 @@ class Item
return; return;
} }
$cdata = Contact::getPublicAndUserContactID($item['author-id'], $item['uid']); if (!DBA::exists('contact', ['id' => $cdata['user'], 'remote_self' => LocalRelationship::MIRROR_NATIVE_RESHARE])) {
if (empty($cdata['user']) || ($cdata['user'] != $item['contact-id'])) {
return;
}
if (!DBA::exists('contact', ['id' => $cdata['user'], 'remote_self' => Contact::MIRROR_NATIVE_RESHARE])) {
return; return;
} }
@ -2346,6 +2342,10 @@ class Item
return; return;
} }
if (User::getById($item['uid'], ['blocked'])['blocked'] ?? false) {
return;
}
Logger::info('Automatically reshare item', ['uid' => $item['uid'], 'id' => $item['id'], 'guid' => $item['guid'], 'uri-id' => $item['uri-id']]); Logger::info('Automatically reshare item', ['uid' => $item['uid'], 'id' => $item['id'], 'guid' => $item['guid'], 'uri-id' => $item['uri-id']]);
self::performActivity($item['id'], 'announce', $item['uid']); self::performActivity($item['id'], 'announce', $item['uid']);
@ -2353,7 +2353,7 @@ class Item
public static function isRemoteSelf(array $contact, array &$datarray): bool public static function isRemoteSelf(array $contact, array &$datarray): bool
{ {
if ($contact['remote_self'] != Contact::MIRROR_OWN_POST) { if ($contact['remote_self'] != LocalRelationship::MIRROR_OWN_POST) {
return false; return false;
} }
@ -2380,6 +2380,11 @@ class Item
return false; return false;
} }
if (User::getById($contact['uid'], ['blocked'])['blocked'] ?? false) {
Logger::info('User is blocked', ['contact' => $contact]);
return false;
}
$datarray2 = $datarray; $datarray2 = $datarray;
Logger::info('remote-self start', ['contact' => $contact['url'], 'remote_self' => $contact['remote_self'], 'item' => $datarray]); Logger::info('remote-self start', ['contact' => $contact['url'], 'remote_self' => $contact['remote_self'], 'item' => $datarray]);

View file

@ -109,8 +109,9 @@ class Nodeinfo
'outbound' => [], 'outbound' => [],
]; ];
if (Addon::isEnabled('blogger')) { if (Addon::isEnabled('bluesky')) {
$services['outbound'][] = 'blogger'; $services['inbound'][] = 'bluesky';
$services['outbound'][] = 'bluesky';
} }
if (Addon::isEnabled('dwpost')) { if (Addon::isEnabled('dwpost')) {
$services['outbound'][] = 'dreamwidth'; $services['outbound'][] = 'dreamwidth';
@ -125,18 +126,9 @@ class Nodeinfo
if (Addon::isEnabled('libertree')) { if (Addon::isEnabled('libertree')) {
$services['outbound'][] = 'libertree'; $services['outbound'][] = 'libertree';
} }
if (Addon::isEnabled('buffer')) {
$services['outbound'][] = 'linkedin';
}
if (Addon::isEnabled('ljpost')) { if (Addon::isEnabled('ljpost')) {
$services['outbound'][] = 'livejournal'; $services['outbound'][] = 'livejournal';
} }
if (Addon::isEnabled('buffer')) {
$services['outbound'][] = 'pinterest';
}
if (Addon::isEnabled('posterous')) {
$services['outbound'][] = 'posterous';
}
if (Addon::isEnabled('pumpio')) { if (Addon::isEnabled('pumpio')) {
$services['inbound'][] = 'pumpio'; $services['inbound'][] = 'pumpio';
$services['outbound'][] = 'pumpio'; $services['outbound'][] = 'pumpio';
@ -147,7 +139,7 @@ class Nodeinfo
if (Addon::isEnabled('tumblr')) { if (Addon::isEnabled('tumblr')) {
$services['outbound'][] = 'tumblr'; $services['outbound'][] = 'tumblr';
} }
if (Addon::isEnabled('twitter') || Addon::isEnabled('buffer')) { if (Addon::isEnabled('twitter')) {
$services['outbound'][] = 'twitter'; $services['outbound'][] = 'twitter';
} }
if (Addon::isEnabled('wppost')) { if (Addon::isEnabled('wppost')) {

View file

@ -989,6 +989,35 @@ class Photo
return DBA::exists('photo', ['resource-id' => $guid]); return DBA::exists('photo', ['resource-id' => $guid]);
} }
/**
* Resize to a given maximum file size
*
* @param Image $image
* @param integer $maximagesize
* @return Image
*/
public static function resizeToFileSize(Image $image, int $maximagesize): Image
{
$filesize = strlen($image->asString());
$width = $image->getWidth();
$height = $image->getHeight();
if ($maximagesize && ($filesize > $maximagesize)) {
// Scale down to multiples of 640 until the maximum size isn't exceeded anymore
foreach ([5120, 2560, 1280, 640, 320] as $pixels) {
if (($filesize > $maximagesize) && (max($width, $height) > $pixels)) {
Logger::info('Resize', ['size' => $filesize, 'width' => $width, 'height' => $height, 'max' => $maximagesize, 'pixels' => $pixels]);
$image->scaleDown($pixels);
$filesize = strlen($image->asString());
$width = $image->getWidth();
$height = $image->getHeight();
}
}
}
return $image;
}
/** /**
* Tries to resize image to wanted maximum size * Tries to resize image to wanted maximum size
* *
@ -1003,30 +1032,7 @@ class Photo
Logger::info('File upload: Scaling picture to new size', ['max-length' => $max_length]); Logger::info('File upload: Scaling picture to new size', ['max-length' => $max_length]);
} }
$filesize = strlen($image->asString()); return self::resizeToFileSize($image, Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize')));
$width = $image->getWidth();
$height = $image->getHeight();
$maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
if ($maximagesize && ($filesize > $maximagesize)) {
// Scale down to multiples of 640 until the maximum size isn't exceeded anymore
foreach ([5120, 2560, 1280, 640] as $pixels) {
if (($filesize > $maximagesize) && (max($width, $height) > $pixels)) {
Logger::info('Resize', ['size' => $filesize, 'width' => $width, 'height' => $height, 'max' => $maximagesize, 'pixels' => $pixels]);
$image->scaleDown($pixels);
$filesize = strlen($image->asString());
$width = $image->getWidth();
$height = $image->getHeight();
}
}
if ($filesize > $maximagesize) {
Logger::notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]);
return null;
}
}
return $image;
} }
/** /**
@ -1237,32 +1243,7 @@ class Photo
*/ */
public static function storeWithPreview(Image $image, int $uid, string $resource_id, string $filename, int $filesize, string $album, string $description, string $allow_cid, string $allow_gid, string $deny_cid, string $deny_gid): int public static function storeWithPreview(Image $image, int $uid, string $resource_id, string $filename, int $filesize, string $album, string $description, string $allow_cid, string $allow_gid, string $deny_cid, string $deny_gid): int
{ {
if ($filesize == 0) { $image = self::resizeToFileSize($image, Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize')));
$filesize = strlen($image->asString());
}
$width = $image->getWidth();
$height = $image->getHeight();
$maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
if ($maximagesize && $filesize > $maximagesize) {
// Scale down to multiples of 640 until the maximum size isn't exceeded anymore
foreach ([5120, 2560, 1280, 640, 320] as $pixels) {
if ($filesize > $maximagesize && max($width, $height) > $pixels) {
DI::logger()->info('Resize', ['size' => $filesize, 'width' => $width, 'height' => $height, 'max' => $maximagesize, 'pixels' => $pixels]);
$image->scaleDown($pixels);
$filesize = strlen($image->asString());
$width = $image->getWidth();
$height = $image->getHeight();
}
}
if ($filesize > $maximagesize) {
DI::logger()->notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]);
return -1;
}
}
$width = $image->getWidth(); $width = $image->getWidth();
$height = $image->getHeight(); $height = $image->getHeight();

View file

@ -880,6 +880,20 @@ class User
]); ]);
} }
/**
* Returns if the given uid is valid and a moderator
*
* @param int $uid
*
* @return bool
* @throws Exception
*/
public static function isModerator(int $uid): bool
{
// @todo Replace with a moderator check in the future
return self::isSiteAdmin($uid);
}
/** /**
* Checks if a nickname is in the list of the forbidden nicknames * Checks if a nickname is in the list of the forbidden nicknames
* *

View file

@ -76,16 +76,9 @@ class Statuses extends BaseApi
throw new HTTPException\NotFoundException('Item with URI ID ' . $this->parameters['id'] . ' not found for user ' . $uid . '.'); throw new HTTPException\NotFoundException('Item with URI ID ' . $this->parameters['id'] . ' not found for user ' . $uid . '.');
} }
// The imput is defined as text. So we can use Markdown for some enhancements
$body = Markdown::toBBCode($request['status']);
if (DI::pConfig()->get($uid, 'system', 'api_auto_attach', false) && preg_match("/\[url=[^\[\]]*\](.*)\[\/url\]\z/ism", $body, $matches)) {
$body = preg_replace("/\[url=[^\[\]]*\].*\[\/url\]\z/ism", PageInfo::getFooterFromUrl($matches[1]), $body);
}
$item['title'] = ''; $item['title'] = '';
$item['uid'] = $post['uid']; $item['uid'] = $post['uid'];
$item['body'] = $body; $item['body'] = $this->formatStatus($request['status'], $uid);
$item['network'] = $post['network']; $item['network'] = $post['network'];
$item['gravity'] = $post['gravity']; $item['gravity'] = $post['gravity'];
$item['verb'] = $post['verb']; $item['verb'] = $post['verb'];
@ -190,13 +183,6 @@ class Statuses extends BaseApi
$owner = User::getOwnerDataById($uid); $owner = User::getOwnerDataById($uid);
// The imput is defined as text. So we can use Markdown for some enhancements
$body = Markdown::toBBCode($request['status']);
if (DI::pConfig()->get($uid, 'system', 'api_auto_attach', false) && preg_match("/\[url=[^\[\]]*\](.*)\[\/url\]\z/ism", $body, $matches)) {
$body = preg_replace("/\[url=[^\[\]]*\].*\[\/url\]\z/ism", PageInfo::getFooterFromUrl($matches[1]), $body);
}
$item = []; $item = [];
$item['network'] = Protocol::DFRN; $item['network'] = Protocol::DFRN;
$item['uid'] = $uid; $item['uid'] = $uid;
@ -204,7 +190,7 @@ class Statuses extends BaseApi
$item['contact-id'] = $owner['id']; $item['contact-id'] = $owner['id'];
$item['author-id'] = $item['owner-id'] = Contact::getPublicIdByUserId($uid); $item['author-id'] = $item['owner-id'] = Contact::getPublicIdByUserId($uid);
$item['title'] = ''; $item['title'] = '';
$item['body'] = $body; $item['body'] = $this->formatStatus($request['status'], $uid);
$item['app'] = $this->getApp(); $item['app'] = $this->getApp();
switch ($request['visibility']) { switch ($request['visibility']) {
@ -415,4 +401,28 @@ class Statuses extends BaseApi
} }
return $item; return $item;
} }
/**
* Format the status via Markdown and a link description if enabled for this user
*
* @param string $status
* @param integer $uid
* @return string
*/
private function formatStatus(string $status, int $uid): string
{
// The input is defined as text. So we can use Markdown for some enhancements
$status = Markdown::toBBCode($status);
if (!DI::pConfig()->get($uid, 'system', 'api_auto_attach', false)) {
return $status;
}
$status = BBCode::expandVideoLinks($status);
if (preg_match("/\[url=[^\[\]]*\](.*)\[\/url\]\z/ism", $status, $matches)) {
$status = preg_replace("/\[url=[^\[\]]*\].*\[\/url\]\z/ism", PageInfo::getFooterFromUrl($matches[1]), $status);
}
return $status;
}
} }

View file

@ -82,12 +82,12 @@ abstract class BaseModeration extends BaseModule
} }
} }
if (!$this->app->isSiteAdmin()) { if (!$this->session->isModerator()) {
throw new HTTPException\ForbiddenException($this->t('You don\'t have access to administration pages.')); throw new HTTPException\ForbiddenException($this->t('You don\'t have access to moderation pages.'));
} }
if ($this->session->getSubManagedUserId()) { if ($this->session->getSubManagedUserId()) {
throw new HTTPException\ForbiddenException($this->t('Submanaged account can\'t access the administration pages. Please log back in as the main account.')); throw new HTTPException\ForbiddenException($this->t('Submanaged account can\'t access the moderation pages. Please log back in as the main account.'));
} }
} }

View file

@ -283,10 +283,10 @@ class Profile extends BaseModule
$localRelationship->fetchFurtherInformation, $localRelationship->fetchFurtherInformation,
$this->t('Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn\'t contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags.'), $this->t('Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn\'t contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags.'),
[ [
'0' => $this->t('Disabled'), Entity\LocalRelationship::FFI_NONE => $this->t('Disabled'),
'1' => $this->t('Fetch information'), Entity\LocalRelationship::FFI_INFORMATION => $this->t('Fetch information'),
'3' => $this->t('Fetch keywords'), Entity\LocalRelationship::FFI_KEYWORD => $this->t('Fetch keywords'),
'2' => $this->t('Fetch information and keywords') Entity\LocalRelationship::FFI_BOTH => $this->t('Fetch information and keywords')
] ]
]; ];
} }
@ -394,7 +394,7 @@ class Profile extends BaseModule
'$remote_self' => [ '$remote_self' => [
'remote_self', 'remote_self',
$this->t('Mirror postings from this contact'), $this->t('Mirror postings from this contact'),
$localRelationship->isRemoteSelf, $localRelationship->remoteSelf,
$this->t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'), $this->t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'),
$remote_self_options $remote_self_options
], ],

View file

@ -26,7 +26,7 @@ use Friendica\BaseModule;
use Friendica\Core\Addon; use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
@ -94,8 +94,7 @@ class Friendica extends BaseModule
$blockList = $this->config->get('system', 'blocklist') ?? []; $blockList = $this->config->get('system', 'blocklist') ?? [];
$register_policy_int = $this->config->get('config', 'register_policy'); if (!empty($blockList) && ($this->config->get('blocklist', 'public') || $this->session->isAuthenticated())) {
if (!empty($blockList) && ($register_policy_int !== Register::CLOSED || $this->session->isAuthenticated())) {
$blocked = [ $blocked = [
'title' => $this->t('On this server the following remote servers are blocked.'), 'title' => $this->t('On this server the following remote servers are blocked.'),
'header' => [ 'header' => [

View file

@ -88,10 +88,6 @@ class NodeInfo110 extends BaseModule
$nodeinfo['metadata']['services'] = $nodeinfo['services']; $nodeinfo['metadata']['services'] = $nodeinfo['services'];
if (Addon::isEnabled('twitter')) {
$nodeinfo['metadata']['services']['inbound'][] = 'twitter';
}
$nodeinfo['metadata']['explicitContent'] = $this->config->get('system', 'explicit_content', false) == true; $nodeinfo['metadata']['explicitContent'] = $this->config->get('system', 'explicit_content', false) == true;
$this->response->setType(ICanCreateResponses::TYPE_JSON); $this->response->setType(ICanCreateResponses::TYPE_JSON);

View file

@ -72,10 +72,6 @@ class NodeInfo120 extends BaseModule
$nodeinfo['protocols'][] = 'ostatus'; $nodeinfo['protocols'][] = 'ostatus';
} }
if (Addon::isEnabled('twitter')) {
$nodeinfo['services']['inbound'][] = 'twitter';
}
$nodeinfo['services']['inbound'][] = 'atom1.0'; $nodeinfo['services']['inbound'][] = 'atom1.0';
$nodeinfo['services']['inbound'][] = 'rss2.0'; $nodeinfo['services']['inbound'][] = 'rss2.0';
$nodeinfo['services']['outbound'][] = 'atom1.0'; $nodeinfo['services']['outbound'][] = 'atom1.0';

View file

@ -71,10 +71,6 @@ class NodeInfo210 extends BaseModule
$nodeinfo['protocols'][] = 'ostatus'; $nodeinfo['protocols'][] = 'ostatus';
} }
if (Addon::isEnabled('twitter')) {
$nodeinfo['services']['inbound'][] = 'twitter';
}
$nodeinfo['services']['inbound'][] = 'atom1.0'; $nodeinfo['services']['inbound'][] = 'atom1.0';
$nodeinfo['services']['inbound'][] = 'rss2.0'; $nodeinfo['services']['inbound'][] = 'rss2.0';
$nodeinfo['services']['outbound'][] = 'atom1.0'; $nodeinfo['services']['outbound'][] = 'atom1.0';

View file

@ -52,6 +52,7 @@ use Friendica\Network\HTTPException;
use Friendica\Protocol\Activity; use Friendica\Protocol\Activity;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Profiler; use Friendica\Util\Profiler;
use Friendica\Util\Strings;
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -174,7 +175,7 @@ class Ping extends BaseModule
$myurl = $this->session->getMyUrl(); $myurl = $this->session->getMyUrl();
$mail_count = $this->database->count('mail', ["`uid` = ? AND NOT `seen` AND `from-url` != ?", $this->session->getLocalUserId(), $myurl]); $mail_count = $this->database->count('mail', ["`uid` = ? AND NOT `seen` AND `from-url` != ?", $this->session->getLocalUserId(), $myurl]);
if (intval($this->config->get('config', 'register_policy')) === Register::APPROVE && $this->app->isSiteAdmin()) { if (intval($this->config->get('config', 'register_policy')) === Register::APPROVE && $this->session->isSiteAdmin()) {
$registrations = \Friendica\Model\Register::getPending(); $registrations = \Friendica\Model\Register::getPending();
$register_count = count($registrations); $register_count = count($registrations);
} }
@ -296,8 +297,8 @@ class Ping extends BaseModule
$data['notifications'] = $navNotifications; $data['notifications'] = $navNotifications;
$data['sysmsgs'] = [ $data['sysmsgs'] = [
'notice' => $this->systemMessages->flushNotices(), 'notice' => array_map([Strings::class, 'escapeHtml'], $this->systemMessages->flushNotices()),
'info' => $this->systemMessages->flushInfos(), 'info' => array_map([Strings::class, 'escapeHtml'], $this->systemMessages->flushInfos()),
]; ];
if (isset($_GET['callback'])) { if (isset($_GET['callback'])) {

View file

@ -103,10 +103,10 @@ class Conversations extends BaseProfile
$this->page['htmlhead'] .= '<meta content="noindex, noarchive" name="robots" />' . "\n"; $this->page['htmlhead'] .= '<meta content="noindex, noarchive" name="robots" />' . "\n";
} }
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/dfrn_poll/' . $this->parameters['nickname'] . '" title="DFRN: ' . $this->t('%s\'s timeline', $profile['name']) . '"/>' . "\n"; $this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/dfrn_poll/' . $this->parameters['nickname'] . '" title="DFRN: ' . $this->t('%s\'s timeline', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/" title="' . $this->t('%s\'s posts', $profile['name']) . '"/>' . "\n"; $this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/" title="' . $this->t('%s\'s posts', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/comments" title="' . $this->t('%s\'s comments', $profile['name']) . '"/>' . "\n"; $this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/comments" title="' . $this->t('%s\'s comments', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
$this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/activity" title="' . $this->t('%s\'s timeline', $profile['name']) . '"/>' . "\n"; $this->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $this->baseUrl . '/feed/' . $this->parameters['nickname'] . '/activity" title="' . $this->t('%s\'s timeline', Strings::escapeHtml($profile['name'])) . '"/>' . "\n";
$category = $datequery = $datequery2 = ''; $category = $datequery = $datequery2 = '';

View file

@ -45,6 +45,11 @@ class RobotsTxt extends BaseModule
foreach ($allDisallowed as $disallowed) { foreach ($allDisallowed as $disallowed) {
echo 'Disallow: ' . $disallowed . PHP_EOL; echo 'Disallow: ' . $disallowed . PHP_EOL;
} }
echo PHP_EOL;
echo 'User-agent: ChatGPT-User' . PHP_EOL;
echo 'Disallow: /' . PHP_EOL;
System::exit(); System::exit();
} }
} }

View file

@ -173,7 +173,7 @@ class Index extends BaseSearch
$pager = new Pager(DI::l10n(), DI::args()->getQueryString(), $itemsPerPage); $pager = new Pager(DI::l10n(), DI::args()->getQueryString(), $itemsPerPage);
if ($tag) { if ($tag) {
Logger::info('Start tag search.', ['q' => $search]); Logger::info('Start tag search.', ['q' => $search, 'start' => $pager->getStart(), 'items' => $pager->getItemsPerPage(), 'last' => $last_uriid]);
$uriids = Tag::getURIIdListByTag($search, DI::userSession()->getLocalUserId(), $pager->getStart(), $pager->getItemsPerPage(), $last_uriid); $uriids = Tag::getURIIdListByTag($search, DI::userSession()->getLocalUserId(), $pager->getStart(), $pager->getItemsPerPage(), $last_uriid);
$count = Tag::countByTag($search, DI::userSession()->getLocalUserId()); $count = Tag::countByTag($search, DI::userSession()->getLocalUserId());
} else { } else {
@ -185,7 +185,7 @@ class Index extends BaseSearch
if (!empty($uriids)) { if (!empty($uriids)) {
$condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`))", 0, DI::userSession()->getLocalUserId()]; $condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`))", 0, DI::userSession()->getLocalUserId()];
$condition = DBA::mergeConditions($condition, ['uri-id' => $uriids]); $condition = DBA::mergeConditions($condition, ['uri-id' => $uriids]);
$params = ['order' => ['id' => true]]; $params = ['order' => ['uri-id' => true]];
$items = Post::toArray(Post::selectForUser(DI::userSession()->getLocalUserId(), Item::DISPLAY_FIELDLIST, $condition, $params)); $items = Post::toArray(Post::selectForUser(DI::userSession()->getLocalUserId(), Item::DISPLAY_FIELDLIST, $condition, $params));
} }

View file

@ -25,7 +25,7 @@ use Friendica\App;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\Addon; use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\NotFoundException;
@ -59,7 +59,7 @@ class Statistics extends BaseModule
/// @todo mark the "service" addons and load them dynamically here /// @todo mark the "service" addons and load them dynamically here
$services = [ $services = [
'appnet' => Addon::isEnabled('appnet'), 'appnet' => Addon::isEnabled('appnet'),
'buffer' => Addon::isEnabled('buffer'), 'bluesky' => Addon::isEnabled('bluesky'),
'dreamwidth' => Addon::isEnabled('dreamwidth'), 'dreamwidth' => Addon::isEnabled('dreamwidth'),
'gnusocial' => Addon::isEnabled('gnusocial'), 'gnusocial' => Addon::isEnabled('gnusocial'),
'libertree' => Addon::isEnabled('libertree'), 'libertree' => Addon::isEnabled('libertree'),

View file

@ -21,32 +21,43 @@
namespace Friendica\Module; namespace Friendica\Module;
use Friendica\App;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\DI; use Friendica\Core\L10n;
use Friendica\Core\Session\Capability\IHandleSessions;
use Friendica\Core\System;
use Friendica\Network\HTTPException\BadRequestException;
use Friendica\Util;
use GuzzleHttp\Psr7\Uri;
use Psr\Log\LoggerInterface;
/** /**
* Toggles the mobile view (on/off) * Toggles the mobile view (on/off)
*/ */
class ToggleMobile extends BaseModule class ToggleMobile extends BaseModule
{ {
protected function content(array $request = []): string /** @var IHandleSessions */
private $session;
public function __construct(IHandleSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Util\Profiler $profiler, Response $response, array $server, array $parameters = [])
{ {
$a = DI::app(); parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
if (isset($_GET['off'])) { $this->session = $session;
$_SESSION['show-mobile'] = false;
} else {
$_SESSION['show-mobile'] = true;
} }
if (isset($_GET['address'])) { protected function rawContent(array $request = [])
$address = $_GET['address']; {
} else { $address = $request['address'] ?? '' ?: $this->baseUrl;
$address = '';
$uri = new Uri($address);
if (!$this->baseUrl->isLocalUri($uri)) {
throw new BadRequestException();
} }
$a->redirect($address); $this->session->set('show-mobile', !isset($request['off']));
return ''; System::externalRedirect((string)$uri);
} }
} }

View file

@ -1658,7 +1658,7 @@ class Processor
$tags = Receiver::processTags(JsonLD::fetchElementArray($activity['as:object'], 'as:tag') ?? []); $tags = Receiver::processTags(JsonLD::fetchElementArray($activity['as:object'], 'as:tag') ?? []);
if (!empty($tags)) { if (!empty($tags)) {
foreach ($tags as $tag) { foreach ($tags as $tag) {
if ($tag['type'] != 'Hashtag') { if (($tag['type'] != 'Hashtag') && !strpos($tag['type'], ':Hashtag')) {
continue; continue;
} }
$messageTags[] = ltrim(mb_strtolower($tag['name']), '#'); $messageTags[] = ltrim(mb_strtolower($tag['name']), '#');

View file

@ -25,6 +25,7 @@ use DOMDocument;
use DOMElement; use DOMElement;
use DOMXPath; use DOMXPath;
use Friendica\App; use Friendica\App;
use Friendica\Contact\LocalRelationship\Entity\LocalRelationship;
use Friendica\Content\PageInfo; use Friendica\Content\PageInfo;
use Friendica\Content\Text\BBCode; use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML; use Friendica\Content\Text\HTML;
@ -566,8 +567,10 @@ class Feed
continue; continue;
} }
$fetch_further_information = $contact['fetch_further_information'] ?? LocalRelationship::FFI_NONE;
$preview = ''; $preview = '';
if (!empty($contact['fetch_further_information']) && ($contact['fetch_further_information'] < 3)) { if (in_array($fetch_further_information, [LocalRelationship::FFI_INFORMATION, LocalRelationship::FFI_BOTH])) {
// Handle enclosures and treat them as preview picture // Handle enclosures and treat them as preview picture
foreach ($attachments as $attachment) { foreach ($attachments as $attachment) {
if ($attachment['mimetype'] == 'image/jpeg') { if ($attachment['mimetype'] == 'image/jpeg') {
@ -611,7 +614,12 @@ class Feed
} }
} }
$data = PageInfo::queryUrl($item['plink'], false, $preview, ($contact['fetch_further_information'] == 2), $contact['ffi_keyword_denylist'] ?? ''); $data = PageInfo::queryUrl(
$item['plink'],
false,
$fetch_further_information == LocalRelationship::FFI_BOTH,
$contact['ffi_keyword_denylist'] ?? ''
);
if (!empty($data)) { if (!empty($data)) {
// Take the data that was provided by the feed if the query is empty // Take the data that was provided by the feed if the query is empty
@ -630,7 +638,7 @@ class Feed
// We always strip the title since it will be added in the page information // We always strip the title since it will be added in the page information
$item['title'] = ''; $item['title'] = '';
$item['body'] = $item['body'] . "\n" . PageInfo::getFooterFromData($data, false); $item['body'] = $item['body'] . "\n" . PageInfo::getFooterFromData($data, false);
$taglist = $contact['fetch_further_information'] == 2 ? PageInfo::getTagsFromUrl($item['plink'], $preview, $contact['ffi_keyword_denylist'] ?? '') : []; $taglist = $fetch_further_information == LocalRelationship::FFI_BOTH ? PageInfo::getTagsFromUrl($item['plink'], $preview, $contact['ffi_keyword_denylist'] ?? '') : [];
$item['object-type'] = Activity\ObjectType::BOOKMARK; $item['object-type'] = Activity\ObjectType::BOOKMARK;
$attachments = []; $attachments = [];
@ -662,7 +670,7 @@ class Feed
$item['body'] = '[abstract]' . HTML::toBBCode($summary, $basepath) . "[/abstract]\n" . $item['body']; $item['body'] = '[abstract]' . HTML::toBBCode($summary, $basepath) . "[/abstract]\n" . $item['body'];
} }
if (!empty($contact['fetch_further_information']) && ($contact['fetch_further_information'] == 3)) { if ($fetch_further_information == LocalRelationship::FFI_KEYWORD) {
if (empty($taglist)) { if (empty($taglist)) {
$taglist = PageInfo::getTagsFromUrl($item['plink'], $preview, $contact['ffi_keyword_denylist'] ?? ''); $taglist = PageInfo::getTagsFromUrl($item['plink'], $preview, $contact['ffi_keyword_denylist'] ?? '');
} }

View file

@ -136,16 +136,16 @@ class Relay
} }
if (!self::isWantedLanguage($body)) { if (!self::isWantedLanguage($body)) {
Logger::info('Unwanted or Undetected language found - rejected', ['network' => $network, 'url' => $url, 'causer' => $causer]); Logger::info('Unwanted or Undetected language found - rejected', ['network' => $network, 'url' => $url, 'causer' => $causer, 'tags' => $tags]);
return false; return false;
} }
if ($scope == self::SCOPE_ALL) { if ($scope == self::SCOPE_ALL) {
Logger::info('Server accept all posts - accepted', ['network' => $network, 'url' => $url, 'causer' => $causer]); Logger::info('Server accept all posts - accepted', ['network' => $network, 'url' => $url, 'causer' => $causer, 'tags' => $tags]);
return true; return true;
} }
Logger::info('No matching hashtags found - rejected', ['network' => $network, 'url' => $url, 'causer' => $causer]); Logger::info('No matching hashtags found - rejected', ['network' => $network, 'url' => $url, 'causer' => $causer, 'tags' => $tags]);
return false; return false;
} }
@ -354,7 +354,7 @@ class Relay
public static function getList(array $fields = []): array public static function getList(array $fields = []): array
{ {
return DBA::selectToArray('apcontact', $fields, return DBA::selectToArray('apcontact', $fields,
["`type` = ? AND `url` IN (SELECT `url` FROM `contact` WHERE `uid` = ? AND `rel` = ?)", 'Application', 0, Contact::FRIEND]); ["`type` IN (?, ?) AND `url` IN (SELECT `url` FROM `contact` WHERE `uid` = ? AND `rel` = ?)", 'Application', 'Service', 0, Contact::FRIEND]);
} }
/** /**

View file

@ -640,10 +640,11 @@ class Network
* @param string $url * @param string $url
* *
* @return bool * @return bool
* @deprecated since 2023.09, please use BaseUrl->isLocalUrl or BaseUrl->isLocalUri instead.
*/ */
public static function isLocalLink(string $url): bool public static function isLocalLink(string $url): bool
{ {
return (strpos(Strings::normaliseLink($url), Strings::normaliseLink(DI::baseUrl())) !== false); return DI::baseUrl()->isLocalUrl($url);
} }
/** /**

View file

@ -45,10 +45,10 @@ class PollContacts
if (!empty($abandon_days)) { if (!empty($abandon_days)) {
$condition = DBA::mergeConditions($condition, $condition = DBA::mergeConditions($condition,
["`uid` != ? AND `uid` IN (SELECT `uid` FROM `user` WHERE NOT `account_expired` AND NOT `account_removed` AND `last-activity` > ?)", 0, DateTimeFormat::utc('now - ' . $abandon_days . ' days')]); ["`uid` != ? AND `uid` IN (SELECT `uid` FROM `user` WHERE NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `last-activity` > ?)", 0, DateTimeFormat::utc('now - ' . $abandon_days . ' days')]);
} else { } else {
$condition = DBA::mergeConditions($condition, $condition = DBA::mergeConditions($condition,
["`uid` != ? AND `uid` IN (SELECT `uid` FROM `user` WHERE NOT `account_expired` AND NOT `account_removed`)", 0]); ["`uid` != ? AND `uid` IN (SELECT `uid` FROM `user` WHERE NOT `blocked` AND NOT `account_expired` AND NOT `account_removed`)", 0]);
} }
$contacts = DBA::select('contact', ['id', 'nick', 'name', 'network', 'archive', 'last-update', 'priority', 'rating'], $condition); $contacts = DBA::select('contact', ['id', 'nick', 'name', 'network', 'archive', 'last-update', 'priority', 'rating'], $condition);

View file

@ -56,7 +56,7 @@ use Friendica\Database\DBA;
// This file is required several times during the test in DbaDefinition which justifies this condition // This file is required several times during the test in DbaDefinition which justifies this condition
if (!defined('DB_UPDATE_VERSION')) { if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1523); define('DB_UPDATE_VERSION', 1524);
} }
return [ return [
@ -1826,8 +1826,8 @@ return [
"rel" => ["type" => "tinyint unsigned", "comment" => "The kind of the relation between the user and the contact"], "rel" => ["type" => "tinyint unsigned", "comment" => "The kind of the relation between the user and the contact"],
"info" => ["type" => "mediumtext", "comment" => ""], "info" => ["type" => "mediumtext", "comment" => ""],
"notify_new_posts" => ["type" => "boolean", "comment" => ""], "notify_new_posts" => ["type" => "boolean", "comment" => ""],
"remote_self" => ["type" => "boolean", "comment" => ""], "remote_self" => ["type" => "tinyint unsigned", "comment" => "0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare"],
"fetch_further_information" => ["type" => "tinyint unsigned", "comment" => ""], "fetch_further_information" => ["type" => "tinyint unsigned", "comment" => "0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both"],
"ffi_keyword_denylist" => ["type" => "text", "comment" => ""], "ffi_keyword_denylist" => ["type" => "text", "comment" => ""],
"subhub" => ["type" => "boolean", "comment" => ""], "subhub" => ["type" => "boolean", "comment" => ""],
"hub-verify" => ["type" => "varbinary(383)", "comment" => ""], "hub-verify" => ["type" => "varbinary(383)", "comment" => ""],

View file

@ -543,11 +543,11 @@ return [
'pushpoll_frequency' => 3, 'pushpoll_frequency' => 3,
// redis_host (String) // redis_host (String)
// Host name of the redis daemon. // Host name or the path to the Unix domain socket of the Redis daemon.
'redis_host' => '127.0.0.1', 'redis_host' => '127.0.0.1',
// redis_port (String) // redis_port (Integer)
// Port number of the redis daemon. // Port number of the Redis daemon, should be -1 for unix domain socket
'redis_port' => 6379, 'redis_port' => 6379,
// redis_db (Integer) // redis_db (Integer)
@ -786,4 +786,9 @@ return [
// Banner for Mastodon API // Banner for Mastodon API
'mastodon_banner' => '/images/friendica-banner.jpg', 'mastodon_banner' => '/images/friendica-banner.jpg',
], ],
'blocklist' => [
// public (Boolean)
// Wether the blocklist is publicly listed under /about (or in any later API)
'public' => true,
],
]; ];

View file

@ -37,8 +37,8 @@ use Dice\Dice;
use Friendica\App; use Friendica\App;
use Friendica\Core\Cache; use Friendica\Core\Cache;
use Friendica\Core\Config; use Friendica\Core\Config;
use Friendica\Core\Hooks\Capabilities\ICanCreateInstances; use Friendica\Core\Hooks\Capability\ICanCreateInstances;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies; use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Model\DiceInstanceManager; use Friendica\Core\Hooks\Model\DiceInstanceManager;
use Friendica\Core\PConfig; use Friendica\Core\PConfig;
use Friendica\Core\L10n; use Friendica\Core\L10n;
@ -63,7 +63,7 @@ return [
// one instance for the whole execution // one instance for the whole execution
'shared' => true, 'shared' => true,
], ],
\Friendica\Core\Addon\Capabilities\ICanLoadAddons::class => [ \Friendica\Core\Addon\Capability\ICanLoadAddons::class => [
'instanceOf' => \Friendica\Core\Addon\Model\AddonLoader::class, 'instanceOf' => \Friendica\Core\Addon\Model\AddonLoader::class,
'constructParams' => [ 'constructParams' => [
[Dice::INSTANCE => '$basepath'], [Dice::INSTANCE => '$basepath'],
@ -178,6 +178,20 @@ return [
$_SERVER, $_SERVER,
], ],
], ],
'$hostname' => [
'instanceOf' => App\BaseURL::class,
'constructParams' => [
$_SERVER,
],
'call' => [
['getHost', [], Dice::CHAIN_CALL],
],
],
Cache\Type\AbstractCache::class => [
'constructParams' => [
[Dice::INSTANCE => '$hostname'],
],
],
App\Page::class => [ App\Page::class => [
'constructParams' => [ 'constructParams' => [
[Dice::INSTANCE => '$basepath'], [Dice::INSTANCE => '$basepath'],
@ -201,10 +215,10 @@ return [
['create', [], Dice::CHAIN_CALL], ['create', [], Dice::CHAIN_CALL],
], ],
], ],
\Friendica\Core\Logger\Capabilities\IHaveCallIntrospections::class => [ \Friendica\Core\Logger\Capability\IHaveCallIntrospections::class => [
'instanceOf' => \Friendica\Core\Logger\Util\Introspection::class, 'instanceOf' => \Friendica\Core\Logger\Util\Introspection::class,
'constructParams' => [ 'constructParams' => [
\Friendica\Core\Logger\Capabilities\IHaveCallIntrospections::IGNORE_CLASS_LIST, \Friendica\Core\Logger\Capability\IHaveCallIntrospections::IGNORE_CLASS_LIST,
], ],
], ],
'$devLogger' => [ '$devLogger' => [
@ -276,8 +290,11 @@ return [
['getBackend', [], Dice::CHAIN_CALL], ['getBackend', [], Dice::CHAIN_CALL],
], ],
], ],
\Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs::class => [ \Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs::class => [
'instanceOf' => \Friendica\Core\KeyValueStorage\Type\DBKeyValueStorage::class, 'instanceOf' => \Friendica\Core\KeyValueStorage\Factory\KeyValueStorage::class,
'call' => [
['create', [], Dice::CHAIN_CALL],
],
], ],
Network\HTTPClient\Capability\ICanSendHttpRequests::class => [ Network\HTTPClient\Capability\ICanSendHttpRequests::class => [
'instanceOf' => Network\HTTPClient\Factory\HttpClient::class, 'instanceOf' => Network\HTTPClient\Factory\HttpClient::class,

View file

@ -19,14 +19,31 @@
* *
*/ */
use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H; use Friendica\Core\Cache;
use Friendica\Core\Hooks\Util\StrategiesFileManager;
use Friendica\Core\Logger\Type; use Friendica\Core\Logger\Type;
use Friendica\Core\KeyValueStorage;
use Friendica\Core\PConfig;
use Psr\Log; use Psr\Log;
return [ return [
Log\LoggerInterface::class => [ Log\LoggerInterface::class => [
Log\NullLogger::class => [''], Log\NullLogger::class => [StrategiesFileManager::STRATEGY_DEFAULT_KEY],
Type\SyslogLogger::class => ['syslog'], Type\SyslogLogger::class => [Type\SyslogLogger::NAME],
Type\StreamLogger::class => ['stream'], Type\StreamLogger::class => [Type\StreamLogger::NAME],
],
Cache\Capability\ICanCache::class => [
Cache\Type\DatabaseCache::class => [Cache\Type\DatabaseCache::NAME, StrategiesFileManager::STRATEGY_DEFAULT_KEY],
Cache\Type\APCuCache::class => [Cache\Type\APCuCache::NAME],
Cache\Type\MemcacheCache::class => [Cache\Type\MemcacheCache::NAME],
Cache\Type\MemcachedCache::class => [Cache\Type\MemcachedCache::NAME],
Cache\Type\RedisCache::class => [Cache\Type\RedisCache::NAME],
],
KeyValueStorage\Capability\IManageKeyValuePairs::class => [
KeyValueStorage\Type\DBKeyValueStorage::class => [KeyValueStorage\Type\DBKeyValueStorage::NAME, StrategiesFileManager::STRATEGY_DEFAULT_KEY],
],
PConfig\Capability\IManagePersonalConfigValues::class => [
PConfig\Type\JitPConfig::class => [PConfig\Type\JitPConfig::NAME],
PConfig\Type\PreloadPConfig::class => [PConfig\Type\PreloadPConfig::NAME, StrategiesFileManager::STRATEGY_DEFAULT_KEY],
], ],
]; ];

24
tests/phpunit-addons.xml Normal file
View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="bootstrap.php"
verbose="true"
timeoutForSmallTests="900"
timeoutForMediumTests="900"
timeoutForLargeTests="900"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<testsuite name="friendica-addons">
<directory suffix=".php">../addon/*/tests/</directory>
</testsuite>
<!-- Filters for Code Coverage -->
<coverage>
<include>
<directory suffix=".php">../addon/</directory>
</include>
<exclude>
<directory suffix=".php">../addon/*/tests/</directory>
<directory suffix=".php">../addon/*/view/</directory>
<directory suffix=".php">../addon/*/vendor/</directory>
</exclude>
</coverage>
</phpunit>

View file

@ -54,7 +54,7 @@ class AddonLoaderTest extends MockedTest
<?php <?php
return [ return [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [ \Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [ \Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''], \Psr\Log\NullLogger::class => [''],
], ],
@ -79,7 +79,7 @@ EOF;
'addon/testaddon1/static/hooks.config.php' => $this->content, 'addon/testaddon1/static/hooks.config.php' => $this->content,
], ],
'assertion' => [ 'assertion' => [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [ \Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [ \Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''], \Psr\Log\NullLogger::class => [''],
], ],
@ -94,7 +94,7 @@ EOF;
'addon/testaddon2/static/hooks.config.php' => $this->content, 'addon/testaddon2/static/hooks.config.php' => $this->content,
], ],
'assertion' => [ 'assertion' => [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [ \Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [ \Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => ['', ''], \Psr\Log\NullLogger::class => ['', ''],
], ],
@ -118,7 +118,7 @@ EOF;
'addon/testaddon2/static/hooks.config.php' => $this->content, 'addon/testaddon2/static/hooks.config.php' => $this->content,
], ],
'assertion' => [ 'assertion' => [
\Friendica\Core\Hooks\Capabilities\BehavioralHookType::STRATEGY => [ \Friendica\Core\Hooks\Capability\BehavioralHookType::STRATEGY => [
\Psr\Log\LoggerInterface::class => [ \Psr\Log\LoggerInterface::class => [
\Psr\Log\NullLogger::class => [''], \Psr\Log\NullLogger::class => [''],
], ],

View file

@ -23,6 +23,7 @@ namespace Friendica\Test\src\Core\Cache;
use Friendica\Core\Cache\Capability\ICanCache; use Friendica\Core\Cache\Capability\ICanCache;
use Friendica\Core\Cache\Capability\ICanCacheInMemory; use Friendica\Core\Cache\Capability\ICanCacheInMemory;
use Friendica\Core\Cache\Type\AbstractCache;
use Friendica\Test\MockedTest; use Friendica\Test\MockedTest;
use Friendica\Util\PidFile; use Friendica\Util\PidFile;
@ -246,4 +247,13 @@ abstract class CacheTest extends MockedTest
self::assertTrue($this->instance->set('key space', 'value')); self::assertTrue($this->instance->set('key space', 'value'));
self::assertEquals('value', $this->instance->get('key space')); self::assertEquals('value', $this->instance->get('key space'));
} }
public function testGetName()
{
if (defined(get_class($this->instance) . '::NAME')) {
self::assertEquals($this->instance::NAME, $this->instance->getName());
} else {
self::expectNotToPerformAssertions();
}
}
} }

View file

@ -21,6 +21,7 @@
namespace Friendica\Test\src\Core\Cache; namespace Friendica\Test\src\Core\Cache;
use Friendica\App\BaseURL;
use Friendica\Core\Cache; use Friendica\Core\Cache;
use Friendica\Test\DatabaseTestTrait; use Friendica\Test\DatabaseTestTrait;
use Friendica\Test\Util\CreateDatabaseTrait; use Friendica\Test\Util\CreateDatabaseTrait;

View file

@ -235,4 +235,24 @@ class InstanceManagerTest extends MockedTest
self::assertEquals($cBool, $getInstanceA->getCBool()); self::assertEquals($cBool, $getInstanceA->getCBool());
self::assertEquals($cBool, $getInstanceB->getCBool()); self::assertEquals($cBool, $getInstanceB->getCBool());
} }
/**
* @see https://github.com/friendica/friendica/issues/13318
*/
public function testCaseInsensitiveNames()
{
$instance = new DiceInstanceManager(new Dice(), $this->hookFileManager);
$instance->registerStrategy(IAmADecoratedInterface::class, FakeInstance::class, 'fake');
// CamelCase
self::assertInstanceOf(FakeInstance::class, $instance->create(IAmADecoratedInterface::class, 'Fake'));
// UPPER CASE
self::assertInstanceOf(FakeInstance::class, $instance->create(IAmADecoratedInterface::class, 'FAKE'));
// lower case
self::assertInstanceOf(FakeInstance::class, $instance->create(IAmADecoratedInterface::class, 'fake'));
// UnKnOwN
self::assertInstanceOf(FakeInstance::class, $instance->create(IAmADecoratedInterface::class, 'fAkE'));
}
} }

View file

@ -21,8 +21,8 @@
namespace Friendica\Test\src\Core\Hooks\Util; namespace Friendica\Test\src\Core\Hooks\Util;
use Friendica\Core\Addon\Capabilities\ICanLoadAddons; use Friendica\Core\Addon\Capability\ICanLoadAddons;
use Friendica\Core\Hooks\Capabilities\ICanRegisterStrategies; use Friendica\Core\Hooks\Capability\ICanRegisterStrategies;
use Friendica\Core\Hooks\Exceptions\HookConfigException; use Friendica\Core\Hooks\Exceptions\HookConfigException;
use Friendica\Core\Hooks\Util\StrategiesFileManager; use Friendica\Core\Hooks\Util\StrategiesFileManager;
use Friendica\Test\MockedTest; use Friendica\Test\MockedTest;

View file

@ -21,7 +21,7 @@
namespace Friendica\Test\src\Core\KeyValueStorage; namespace Friendica\Test\src\Core\KeyValueStorage;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Core\KeyValueStorage\Type\DBKeyValueStorage; use Friendica\Core\KeyValueStorage\Type\DBKeyValueStorage;
use Friendica\Database\Database; use Friendica\Database\Database;
use Friendica\Test\Util\CreateDatabaseTrait; use Friendica\Test\Util\CreateDatabaseTrait;

View file

@ -21,7 +21,7 @@
namespace Friendica\Test\src\Core\KeyValueStorage; namespace Friendica\Test\src\Core\KeyValueStorage;
use Friendica\Core\KeyValueStorage\Capabilities\IManageKeyValuePairs; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
use Friendica\Test\MockedTest; use Friendica\Test\MockedTest;
abstract class KeyValueStorageTest extends MockedTest abstract class KeyValueStorageTest extends MockedTest

View file

@ -21,7 +21,7 @@
namespace Friendica\Test\src\Core\Logger; namespace Friendica\Test\src\Core\Logger;
use Friendica\Core\Logger\Capabilities\IHaveCallIntrospections; use Friendica\Core\Logger\Capability\IHaveCallIntrospections;
use Friendica\Core\Logger\Type\SyslogLogger; use Friendica\Core\Logger\Type\SyslogLogger;
/** /**

View file

@ -1333,3 +1333,19 @@ function update_1520(): int
return Update::SUCCESS; return Update::SUCCESS;
} }
/**
* user-contact.remote_self was wrongly declared as boolean, possibly truncating integer values from contact.remote_self
*
* @return int
* @throws Exception
*/
function update_1524(): int
{
$contacts = DBA::select('contact', ['uid', 'uri-id', 'remote_self'], ["`uid` != ?", 0]);
while ($contact = DBA::fetch($contacts)) {
Contact\User::insertForContactArray($contact);
}
return Update::SUCCESS;
}

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: 2023.09-dev\n" "Project-Id-Version: 2023.09-dev\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-07-16 16:40+0000\n" "POT-Creation-Date: 2023-08-10 21:16+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -45,12 +45,12 @@ msgid "Item not found."
msgstr "" msgstr ""
#: mod/item.php:451 mod/message.php:67 mod/message.php:113 mod/notes.php:45 #: mod/item.php:451 mod/message.php:67 mod/message.php:113 mod/notes.php:45
#: mod/photos.php:152 mod/photos.php:670 src/Model/Event.php:522 #: mod/photos.php:152 mod/photos.php:670 src/Model/Event.php:520
#: src/Module/Attach.php:55 src/Module/BaseApi.php:99 #: src/Module/Attach.php:55 src/Module/BaseApi.php:99
#: src/Module/BaseNotifications.php:98 src/Module/BaseSettings.php:52 #: src/Module/BaseNotifications.php:98 src/Module/BaseSettings.php:52
#: src/Module/Calendar/Event/API.php:88 src/Module/Calendar/Event/Form.php:84 #: src/Module/Calendar/Event/API.php:88 src/Module/Calendar/Event/Form.php:84
#: src/Module/Calendar/Export.php:82 src/Module/Calendar/Show.php:82 #: src/Module/Calendar/Export.php:82 src/Module/Calendar/Show.php:82
#: src/Module/Circle.php:40 src/Module/Circle.php:83 #: src/Module/Circle.php:41 src/Module/Circle.php:84
#: src/Module/Contact/Advanced.php:60 src/Module/Contact/Follow.php:87 #: src/Module/Contact/Advanced.php:60 src/Module/Contact/Follow.php:87
#: src/Module/Contact/Follow.php:160 src/Module/Contact/MatchInterests.php:86 #: src/Module/Contact/Follow.php:160 src/Module/Contact/MatchInterests.php:86
#: src/Module/Contact/Suggestions.php:54 src/Module/Contact/Unfollow.php:66 #: src/Module/Contact/Suggestions.php:54 src/Module/Contact/Unfollow.php:66
@ -388,7 +388,7 @@ msgid "Save"
msgstr "" msgstr ""
#: mod/photos.php:67 mod/photos.php:132 mod/photos.php:578 #: mod/photos.php:67 mod/photos.php:132 mod/photos.php:578
#: src/Model/Event.php:514 src/Model/Profile.php:234 #: src/Model/Event.php:512 src/Model/Profile.php:234
#: src/Module/Calendar/Export.php:74 src/Module/Calendar/Show.php:74 #: src/Module/Calendar/Export.php:74 src/Module/Calendar/Show.php:74
#: src/Module/DFRN/Poll.php:43 src/Module/Feed.php:65 src/Module/HCard.php:51 #: src/Module/DFRN/Poll.php:43 src/Module/Feed.php:65 src/Module/HCard.php:51
#: src/Module/Profile/Common.php:62 src/Module/Profile/Common.php:71 #: src/Module/Profile/Common.php:62 src/Module/Profile/Common.php:71
@ -943,7 +943,7 @@ msgstr ""
msgid "Enter user nickname: " msgid "Enter user nickname: "
msgstr "" msgstr ""
#: src/Console/User.php:182 src/Model/User.php:681 #: src/Console/User.php:182 src/Model/User.php:692
#: src/Module/Api/Twitter/ContactEndpoint.php:74 #: src/Module/Api/Twitter/ContactEndpoint.php:74
#: src/Module/Moderation/Users/Active.php:71 #: src/Module/Moderation/Users/Active.php:71
#: src/Module/Moderation/Users/Blocked.php:71 #: src/Module/Moderation/Users/Blocked.php:71
@ -1608,7 +1608,7 @@ msgstr ""
#: src/Content/GroupManager.php:152 src/Content/Nav.php:276 #: src/Content/GroupManager.php:152 src/Content/Nav.php:276
#: src/Content/Text/HTML.php:880 src/Content/Widget.php:541 #: src/Content/Text/HTML.php:880 src/Content/Widget.php:541
#: src/Model/User.php:1229 #: src/Model/User.php:1254
msgid "Groups" msgid "Groups"
msgstr "" msgstr ""
@ -1651,31 +1651,31 @@ msgstr ""
msgid "Follow Thread" msgid "Follow Thread"
msgstr "" msgstr ""
#: src/Content/Item.php:422 src/Model/Contact.php:1206 #: src/Content/Item.php:422 src/Model/Contact.php:1205
msgid "View Status" msgid "View Status"
msgstr "" msgstr ""
#: src/Content/Item.php:423 src/Content/Item.php:443 src/Model/Contact.php:1155 #: src/Content/Item.php:423 src/Content/Item.php:443 src/Model/Contact.php:1154
#: src/Model/Contact.php:1198 src/Model/Contact.php:1207 #: src/Model/Contact.php:1197 src/Model/Contact.php:1206
#: src/Module/Directory.php:157 src/Module/Settings/Profile/Index.php:233 #: src/Module/Directory.php:157 src/Module/Settings/Profile/Index.php:233
msgid "View Profile" msgid "View Profile"
msgstr "" msgstr ""
#: src/Content/Item.php:424 src/Model/Contact.php:1208 #: src/Content/Item.php:424 src/Model/Contact.php:1207
msgid "View Photos" msgid "View Photos"
msgstr "" msgstr ""
#: src/Content/Item.php:425 src/Model/Contact.php:1199 #: src/Content/Item.php:425 src/Model/Contact.php:1198
#: src/Model/Contact.php:1209 #: src/Model/Contact.php:1208
msgid "Network Posts" msgid "Network Posts"
msgstr "" msgstr ""
#: src/Content/Item.php:426 src/Model/Contact.php:1200 #: src/Content/Item.php:426 src/Model/Contact.php:1199
#: src/Model/Contact.php:1210 #: src/Model/Contact.php:1209
msgid "View Contact" msgid "View Contact"
msgstr "" msgstr ""
#: src/Content/Item.php:427 src/Model/Contact.php:1211 #: src/Content/Item.php:427 src/Model/Contact.php:1210
msgid "Send PM" msgid "Send PM"
msgstr "" msgstr ""
@ -1705,7 +1705,7 @@ msgid "Languages"
msgstr "" msgstr ""
#: src/Content/Item.php:440 src/Content/Widget.php:80 #: src/Content/Item.php:440 src/Content/Widget.php:80
#: src/Model/Contact.php:1201 src/Model/Contact.php:1212 #: src/Model/Contact.php:1200 src/Model/Contact.php:1211
#: src/Module/Contact/Follow.php:167 view/theme/vier/theme.php:195 #: src/Module/Contact/Follow.php:167 view/theme/vier/theme.php:195
msgid "Connect/Follow" msgid "Connect/Follow"
msgstr "" msgstr ""
@ -1895,7 +1895,7 @@ msgstr ""
#: src/Content/Nav.php:299 src/Module/Admin/Tos.php:78 #: src/Content/Nav.php:299 src/Module/Admin/Tos.php:78
#: src/Module/BaseAdmin.php:95 src/Module/Register.php:176 #: src/Module/BaseAdmin.php:95 src/Module/Register.php:176
#: src/Module/Tos.php:100 #: src/Module/Tos.php:101
msgid "Terms of Service" msgid "Terms of Service"
msgstr "" msgstr ""
@ -2008,11 +2008,11 @@ msgstr ""
msgid "Site map" msgid "Site map"
msgstr "" msgstr ""
#: src/Content/OEmbed.php:317 #: src/Content/OEmbed.php:316
msgid "Embedding disabled" msgid "Embedding disabled"
msgstr "" msgstr ""
#: src/Content/OEmbed.php:441 #: src/Content/OEmbed.php:440
msgid "Embedded content" msgid "Embedded content"
msgstr "" msgstr ""
@ -2032,8 +2032,8 @@ msgstr ""
msgid "last" msgid "last"
msgstr "" msgstr ""
#: src/Content/Text/BBCode.php:696 src/Content/Text/BBCode.php:1602 #: src/Content/Text/BBCode.php:696 src/Content/Text/BBCode.php:1636
#: src/Content/Text/BBCode.php:1603 #: src/Content/Text/BBCode.php:1637
msgid "Image/photo" msgid "Image/photo"
msgstr "" msgstr ""
@ -2048,23 +2048,23 @@ msgstr ""
msgid "Link to source" msgid "Link to source"
msgstr "" msgstr ""
#: src/Content/Text/BBCode.php:1509 src/Content/Text/HTML.php:904 #: src/Content/Text/BBCode.php:1543 src/Content/Text/HTML.php:904
msgid "Click to open/close" msgid "Click to open/close"
msgstr "" msgstr ""
#: src/Content/Text/BBCode.php:1542 #: src/Content/Text/BBCode.php:1576
msgid "$1 wrote:" msgid "$1 wrote:"
msgstr "" msgstr ""
#: src/Content/Text/BBCode.php:1607 src/Content/Text/BBCode.php:1608 #: src/Content/Text/BBCode.php:1641 src/Content/Text/BBCode.php:1642
msgid "Encrypted content" msgid "Encrypted content"
msgstr "" msgstr ""
#: src/Content/Text/BBCode.php:1872 #: src/Content/Text/BBCode.php:1901
msgid "Invalid source protocol" msgid "Invalid source protocol"
msgstr "" msgstr ""
#: src/Content/Text/BBCode.php:1891 #: src/Content/Text/BBCode.php:1920
msgid "Invalid link protocol" msgid "Invalid link protocol"
msgstr "" msgstr ""
@ -2147,7 +2147,7 @@ msgstr ""
msgid "Local Directory" msgid "Local Directory"
msgstr "" msgstr ""
#: src/Content/Widget.php:219 src/Model/Circle.php:594 #: src/Content/Widget.php:219 src/Model/Circle.php:600
#: src/Module/Contact.php:401 src/Module/Welcome.php:76 #: src/Module/Contact.php:401 src/Module/Welcome.php:76
msgid "Circles" msgid "Circles"
msgstr "" msgstr ""
@ -2164,7 +2164,7 @@ msgstr ""
msgid "Relationships" msgid "Relationships"
msgstr "" msgstr ""
#: src/Content/Widget.php:253 src/Module/Circle.php:293 #: src/Content/Widget.php:253 src/Module/Circle.php:292
#: src/Module/Contact.php:345 #: src/Module/Contact.php:345
msgid "All Contacts" msgid "All Contacts"
msgstr "" msgstr ""
@ -2212,7 +2212,7 @@ msgstr ""
msgid "Organisations" msgid "Organisations"
msgstr "" msgstr ""
#: src/Content/Widget.php:540 src/Model/Contact.php:1676 #: src/Content/Widget.php:540 src/Model/Contact.php:1675
msgid "News" msgid "News"
msgstr "" msgstr ""
@ -2281,7 +2281,7 @@ msgid "Matrix:"
msgstr "" msgstr ""
#: src/Content/Widget/VCard.php:111 src/Model/Event.php:82 #: src/Content/Widget/VCard.php:111 src/Model/Event.php:82
#: src/Model/Event.php:109 src/Model/Event.php:473 src/Model/Event.php:965 #: src/Model/Event.php:109 src/Model/Event.php:471 src/Model/Event.php:963
#: src/Model/Profile.php:373 src/Module/Contact/Profile.php:379 #: src/Model/Profile.php:373 src/Module/Contact/Profile.php:379
#: src/Module/Directory.php:147 src/Module/Notifications/Introductions.php:187 #: src/Module/Directory.php:147 src/Module/Notifications/Introductions.php:187
#: src/Module/Profile/Profile.php:221 #: src/Module/Profile/Profile.php:221
@ -2293,8 +2293,8 @@ msgstr ""
msgid "Network:" msgid "Network:"
msgstr "" msgstr ""
#: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1202 #: src/Content/Widget/VCard.php:118 src/Model/Contact.php:1201
#: src/Model/Contact.php:1213 src/Model/Profile.php:465 #: src/Model/Contact.php:1212 src/Model/Profile.php:465
#: src/Module/Contact/Profile.php:429 #: src/Module/Contact/Profile.php:429
msgid "Unfollow" msgid "Unfollow"
msgstr "" msgstr ""
@ -2678,142 +2678,142 @@ msgstr ""
msgid "Could not connect to database." msgid "Could not connect to database."
msgstr "" msgstr ""
#: src/Core/L10n.php:408 src/Model/Event.php:432 #: src/Core/L10n.php:408 src/Model/Event.php:430
#: src/Module/Settings/Display.php:222 #: src/Module/Settings/Display.php:222
msgid "Monday" msgid "Monday"
msgstr "" msgstr ""
#: src/Core/L10n.php:408 src/Model/Event.php:433 #: src/Core/L10n.php:408 src/Model/Event.php:431
#: src/Module/Settings/Display.php:223 #: src/Module/Settings/Display.php:223
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
#: src/Core/L10n.php:408 src/Model/Event.php:434 #: src/Core/L10n.php:408 src/Model/Event.php:432
#: src/Module/Settings/Display.php:224 #: src/Module/Settings/Display.php:224
msgid "Wednesday" msgid "Wednesday"
msgstr "" msgstr ""
#: src/Core/L10n.php:408 src/Model/Event.php:435 #: src/Core/L10n.php:408 src/Model/Event.php:433
#: src/Module/Settings/Display.php:225 #: src/Module/Settings/Display.php:225
msgid "Thursday" msgid "Thursday"
msgstr "" msgstr ""
#: src/Core/L10n.php:408 src/Model/Event.php:436 #: src/Core/L10n.php:408 src/Model/Event.php:434
#: src/Module/Settings/Display.php:226 #: src/Module/Settings/Display.php:226
msgid "Friday" msgid "Friday"
msgstr "" msgstr ""
#: src/Core/L10n.php:408 src/Model/Event.php:437 #: src/Core/L10n.php:408 src/Model/Event.php:435
#: src/Module/Settings/Display.php:227 #: src/Module/Settings/Display.php:227
msgid "Saturday" msgid "Saturday"
msgstr "" msgstr ""
#: src/Core/L10n.php:408 src/Model/Event.php:431 #: src/Core/L10n.php:408 src/Model/Event.php:429
#: src/Module/Settings/Display.php:221 #: src/Module/Settings/Display.php:221
msgid "Sunday" msgid "Sunday"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:452 #: src/Core/L10n.php:412 src/Model/Event.php:450
msgid "January" msgid "January"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:453 #: src/Core/L10n.php:412 src/Model/Event.php:451
msgid "February" msgid "February"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:454 #: src/Core/L10n.php:412 src/Model/Event.php:452
msgid "March" msgid "March"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:455 #: src/Core/L10n.php:412 src/Model/Event.php:453
msgid "April" msgid "April"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Core/L10n.php:431 src/Model/Event.php:443 #: src/Core/L10n.php:412 src/Core/L10n.php:431 src/Model/Event.php:441
msgid "May" msgid "May"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:456 #: src/Core/L10n.php:412 src/Model/Event.php:454
msgid "June" msgid "June"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:457 #: src/Core/L10n.php:412 src/Model/Event.php:455
msgid "July" msgid "July"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:458 #: src/Core/L10n.php:412 src/Model/Event.php:456
msgid "August" msgid "August"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:459 #: src/Core/L10n.php:412 src/Model/Event.php:457
msgid "September" msgid "September"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:460 #: src/Core/L10n.php:412 src/Model/Event.php:458
msgid "October" msgid "October"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:461 #: src/Core/L10n.php:412 src/Model/Event.php:459
msgid "November" msgid "November"
msgstr "" msgstr ""
#: src/Core/L10n.php:412 src/Model/Event.php:462 #: src/Core/L10n.php:412 src/Model/Event.php:460
msgid "December" msgid "December"
msgstr "" msgstr ""
#: src/Core/L10n.php:427 src/Model/Event.php:424 #: src/Core/L10n.php:427 src/Model/Event.php:422
msgid "Mon" msgid "Mon"
msgstr "" msgstr ""
#: src/Core/L10n.php:427 src/Model/Event.php:425 #: src/Core/L10n.php:427 src/Model/Event.php:423
msgid "Tue" msgid "Tue"
msgstr "" msgstr ""
#: src/Core/L10n.php:427 src/Model/Event.php:426 #: src/Core/L10n.php:427 src/Model/Event.php:424
msgid "Wed" msgid "Wed"
msgstr "" msgstr ""
#: src/Core/L10n.php:427 src/Model/Event.php:427 #: src/Core/L10n.php:427 src/Model/Event.php:425
msgid "Thu" msgid "Thu"
msgstr "" msgstr ""
#: src/Core/L10n.php:427 src/Model/Event.php:428 #: src/Core/L10n.php:427 src/Model/Event.php:426
msgid "Fri" msgid "Fri"
msgstr "" msgstr ""
#: src/Core/L10n.php:427 src/Model/Event.php:429 #: src/Core/L10n.php:427 src/Model/Event.php:427
msgid "Sat" msgid "Sat"
msgstr "" msgstr ""
#: src/Core/L10n.php:427 src/Model/Event.php:423 #: src/Core/L10n.php:427 src/Model/Event.php:421
msgid "Sun" msgid "Sun"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:439 #: src/Core/L10n.php:431 src/Model/Event.php:437
msgid "Jan" msgid "Jan"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:440 #: src/Core/L10n.php:431 src/Model/Event.php:438
msgid "Feb" msgid "Feb"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:441 #: src/Core/L10n.php:431 src/Model/Event.php:439
msgid "Mar" msgid "Mar"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:442 #: src/Core/L10n.php:431 src/Model/Event.php:440
msgid "Apr" msgid "Apr"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:444 #: src/Core/L10n.php:431 src/Model/Event.php:442
msgid "Jun" msgid "Jun"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:445 #: src/Core/L10n.php:431 src/Model/Event.php:443
msgid "Jul" msgid "Jul"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:446 #: src/Core/L10n.php:431 src/Model/Event.php:444
msgid "Aug" msgid "Aug"
msgstr "" msgstr ""
@ -2821,15 +2821,15 @@ msgstr ""
msgid "Sep" msgid "Sep"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:448 #: src/Core/L10n.php:431 src/Model/Event.php:446
msgid "Oct" msgid "Oct"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:449 #: src/Core/L10n.php:431 src/Model/Event.php:447
msgid "Nov" msgid "Nov"
msgstr "" msgstr ""
#: src/Core/L10n.php:431 src/Model/Event.php:450 #: src/Core/L10n.php:431 src/Model/Event.php:448
msgid "Dec" msgid "Dec"
msgstr "" msgstr ""
@ -3007,122 +3007,122 @@ msgstr ""
msgid "Legacy module file not found: %s" msgid "Legacy module file not found: %s"
msgstr "" msgstr ""
#: src/Model/Circle.php:105 #: src/Model/Circle.php:106
msgid "" msgid ""
"A deleted circle with this name was revived. Existing item permissions " "A deleted circle with this name was revived. Existing item permissions "
"<strong>may</strong> apply to this circle and any future members. If this is " "<strong>may</strong> apply to this circle and any future members. If this is "
"not what you intended, please create another circle with a different name." "not what you intended, please create another circle with a different name."
msgstr "" msgstr ""
#: src/Model/Circle.php:542 #: src/Model/Circle.php:543
msgid "Everybody" msgid "Everybody"
msgstr "" msgstr ""
#: src/Model/Circle.php:561 #: src/Model/Circle.php:562
msgid "edit" msgid "edit"
msgstr "" msgstr ""
#: src/Model/Circle.php:593 #: src/Model/Circle.php:599
msgid "add" msgid "add"
msgstr "" msgstr ""
#: src/Model/Circle.php:598 #: src/Model/Circle.php:604
msgid "Edit circle" msgid "Edit circle"
msgstr "" msgstr ""
#: src/Model/Circle.php:599 src/Module/Circle.php:194 #: src/Model/Circle.php:605 src/Module/Circle.php:193
msgid "Contacts not in any circle" msgid "Contacts not in any circle"
msgstr "" msgstr ""
#: src/Model/Circle.php:601 #: src/Model/Circle.php:607
msgid "Create a new circle" msgid "Create a new circle"
msgstr "" msgstr ""
#: src/Model/Circle.php:602 src/Module/Circle.php:179 src/Module/Circle.php:202 #: src/Model/Circle.php:608 src/Module/Circle.php:178 src/Module/Circle.php:201
#: src/Module/Circle.php:277 #: src/Module/Circle.php:276
msgid "Circle Name: " msgid "Circle Name: "
msgstr "" msgstr ""
#: src/Model/Circle.php:603 #: src/Model/Circle.php:609
msgid "Edit circles" msgid "Edit circles"
msgstr "" msgstr ""
#: src/Model/Contact.php:1219 src/Module/Moderation/Users/Pending.php:102 #: src/Model/Contact.php:1218 src/Module/Moderation/Users/Pending.php:102
#: src/Module/Notifications/Introductions.php:132 #: src/Module/Notifications/Introductions.php:132
#: src/Module/Notifications/Introductions.php:204 #: src/Module/Notifications/Introductions.php:204
msgid "Approve" msgid "Approve"
msgstr "" msgstr ""
#: src/Model/Contact.php:1672 #: src/Model/Contact.php:1671
msgid "Organisation" msgid "Organisation"
msgstr "" msgstr ""
#: src/Model/Contact.php:1680 #: src/Model/Contact.php:1679
msgid "Group" msgid "Group"
msgstr "" msgstr ""
#: src/Model/Contact.php:2989 #: src/Model/Contact.php:2988
msgid "Disallowed profile URL." msgid "Disallowed profile URL."
msgstr "" msgstr ""
#: src/Model/Contact.php:2994 src/Module/Friendica.php:102 #: src/Model/Contact.php:2993 src/Module/Friendica.php:102
msgid "Blocked domain" msgid "Blocked domain"
msgstr "" msgstr ""
#: src/Model/Contact.php:2999 #: src/Model/Contact.php:2998
msgid "Connect URL missing." msgid "Connect URL missing."
msgstr "" msgstr ""
#: src/Model/Contact.php:3008 #: src/Model/Contact.php:3007
msgid "" msgid ""
"The contact could not be added. Please check the relevant network " "The contact could not be added. Please check the relevant network "
"credentials in your Settings -> Social Networks page." "credentials in your Settings -> Social Networks page."
msgstr "" msgstr ""
#: src/Model/Contact.php:3026 #: src/Model/Contact.php:3025
#, php-format #, php-format
msgid "Expected network %s does not match actual network %s" msgid "Expected network %s does not match actual network %s"
msgstr "" msgstr ""
#: src/Model/Contact.php:3043 #: src/Model/Contact.php:3042
msgid "The profile address specified does not provide adequate information." msgid "The profile address specified does not provide adequate information."
msgstr "" msgstr ""
#: src/Model/Contact.php:3045 #: src/Model/Contact.php:3044
msgid "No compatible communication protocols or feeds were discovered." msgid "No compatible communication protocols or feeds were discovered."
msgstr "" msgstr ""
#: src/Model/Contact.php:3048 #: src/Model/Contact.php:3047
msgid "An author or name was not found." msgid "An author or name was not found."
msgstr "" msgstr ""
#: src/Model/Contact.php:3051 #: src/Model/Contact.php:3050
msgid "No browser URL could be matched to this address." msgid "No browser URL could be matched to this address."
msgstr "" msgstr ""
#: src/Model/Contact.php:3054 #: src/Model/Contact.php:3053
msgid "" msgid ""
"Unable to match @-style Identity Address with a known protocol or email " "Unable to match @-style Identity Address with a known protocol or email "
"contact." "contact."
msgstr "" msgstr ""
#: src/Model/Contact.php:3055 #: src/Model/Contact.php:3054
msgid "Use mailto: in front of address to force email check." msgid "Use mailto: in front of address to force email check."
msgstr "" msgstr ""
#: src/Model/Contact.php:3061 #: src/Model/Contact.php:3060
msgid "" msgid ""
"The profile address specified belongs to a network which has been disabled " "The profile address specified belongs to a network which has been disabled "
"on this site." "on this site."
msgstr "" msgstr ""
#: src/Model/Contact.php:3066 #: src/Model/Contact.php:3065
msgid "" msgid ""
"Limited profile. This person will be unable to receive direct/personal " "Limited profile. This person will be unable to receive direct/personal "
"notifications from you." "notifications from you."
msgstr "" msgstr ""
#: src/Model/Contact.php:3132 #: src/Model/Contact.php:3131
msgid "Unable to retrieve contact information." msgid "Unable to retrieve contact information."
msgstr "" msgstr ""
@ -3130,99 +3130,99 @@ msgstr ""
msgid "l F d, Y \\@ g:i A \\G\\M\\TP (e)" msgid "l F d, Y \\@ g:i A \\G\\M\\TP (e)"
msgstr "" msgstr ""
#: src/Model/Event.php:75 src/Model/Event.php:92 src/Model/Event.php:471 #: src/Model/Event.php:75 src/Model/Event.php:92 src/Model/Event.php:469
#: src/Model/Event.php:947 #: src/Model/Event.php:945
msgid "Starts:" msgid "Starts:"
msgstr "" msgstr ""
#: src/Model/Event.php:78 src/Model/Event.php:98 src/Model/Event.php:472 #: src/Model/Event.php:78 src/Model/Event.php:98 src/Model/Event.php:470
#: src/Model/Event.php:951 #: src/Model/Event.php:949
msgid "Finishes:" msgid "Finishes:"
msgstr "" msgstr ""
#: src/Model/Event.php:421 #: src/Model/Event.php:419
msgid "all-day" msgid "all-day"
msgstr "" msgstr ""
#: src/Model/Event.php:447 #: src/Model/Event.php:445
msgid "Sept" msgid "Sept"
msgstr "" msgstr ""
#: src/Model/Event.php:464 src/Module/Calendar/Show.php:128 #: src/Model/Event.php:462 src/Module/Calendar/Show.php:128
#: src/Util/Temporal.php:343 #: src/Util/Temporal.php:343
msgid "today" msgid "today"
msgstr "" msgstr ""
#: src/Model/Event.php:465 src/Module/Calendar/Show.php:129 #: src/Model/Event.php:463 src/Module/Calendar/Show.php:129
#: src/Module/Settings/Display.php:232 src/Util/Temporal.php:353 #: src/Module/Settings/Display.php:232 src/Util/Temporal.php:353
msgid "month" msgid "month"
msgstr "" msgstr ""
#: src/Model/Event.php:466 src/Module/Calendar/Show.php:130 #: src/Model/Event.php:464 src/Module/Calendar/Show.php:130
#: src/Module/Settings/Display.php:233 src/Util/Temporal.php:354 #: src/Module/Settings/Display.php:233 src/Util/Temporal.php:354
msgid "week" msgid "week"
msgstr "" msgstr ""
#: src/Model/Event.php:467 src/Module/Calendar/Show.php:131 #: src/Model/Event.php:465 src/Module/Calendar/Show.php:131
#: src/Module/Settings/Display.php:234 src/Util/Temporal.php:355 #: src/Module/Settings/Display.php:234 src/Util/Temporal.php:355
msgid "day" msgid "day"
msgstr "" msgstr ""
#: src/Model/Event.php:469 #: src/Model/Event.php:467
msgid "No events to display" msgid "No events to display"
msgstr "" msgstr ""
#: src/Model/Event.php:518 src/Module/DFRN/Poll.php:47 src/Module/Feed.php:69 #: src/Model/Event.php:516 src/Module/DFRN/Poll.php:47 src/Module/Feed.php:69
#: src/Module/Update/Profile.php:56 #: src/Module/Update/Profile.php:56
msgid "Access to this profile has been restricted." msgid "Access to this profile has been restricted."
msgstr "" msgstr ""
#: src/Model/Event.php:560 src/Module/Calendar/Event/Show.php:67 #: src/Model/Event.php:558 src/Module/Calendar/Event/Show.php:67
msgid "Event not found." msgid "Event not found."
msgstr "" msgstr ""
#: src/Model/Event.php:639 #: src/Model/Event.php:637
msgid "l, F j" msgid "l, F j"
msgstr "" msgstr ""
#: src/Model/Event.php:666 #: src/Model/Event.php:664
msgid "Edit event" msgid "Edit event"
msgstr "" msgstr ""
#: src/Model/Event.php:667 #: src/Model/Event.php:665
msgid "Duplicate event" msgid "Duplicate event"
msgstr "" msgstr ""
#: src/Model/Event.php:668 #: src/Model/Event.php:666
msgid "Delete event" msgid "Delete event"
msgstr "" msgstr ""
#: src/Model/Event.php:898 src/Module/Debug/Localtime.php:38 #: src/Model/Event.php:896 src/Module/Debug/Localtime.php:38
msgid "l F d, Y \\@ g:i A" msgid "l F d, Y \\@ g:i A"
msgstr "" msgstr ""
#: src/Model/Event.php:899 #: src/Model/Event.php:897
msgid "D g:i A" msgid "D g:i A"
msgstr "" msgstr ""
#: src/Model/Event.php:900 #: src/Model/Event.php:898
msgid "g:i A" msgid "g:i A"
msgstr "" msgstr ""
#: src/Model/Event.php:966 src/Model/Event.php:968 #: src/Model/Event.php:964 src/Model/Event.php:966
msgid "Show map" msgid "Show map"
msgstr "" msgstr ""
#: src/Model/Event.php:967 #: src/Model/Event.php:965
msgid "Hide map" msgid "Hide map"
msgstr "" msgstr ""
#: src/Model/Event.php:1060 #: src/Model/Event.php:1058
#, php-format #, php-format
msgid "%s's birthday" msgid "%s's birthday"
msgstr "" msgstr ""
#: src/Model/Event.php:1061 #: src/Model/Event.php:1059
#, php-format #, php-format
msgid "Happy Birthday %s" msgid "Happy Birthday %s"
msgstr "" msgstr ""
@ -3459,145 +3459,145 @@ msgstr ""
msgid "Contact information and Social Networks" msgid "Contact information and Social Networks"
msgstr "" msgstr ""
#: src/Model/User.php:214 src/Model/User.php:1142 #: src/Model/User.php:225 src/Model/User.php:1167
msgid "SERIOUS ERROR: Generation of security keys failed." msgid "SERIOUS ERROR: Generation of security keys failed."
msgstr "" msgstr ""
#: src/Model/User.php:590 src/Model/User.php:623 #: src/Model/User.php:601 src/Model/User.php:634
msgid "Login failed" msgid "Login failed"
msgstr "" msgstr ""
#: src/Model/User.php:655 #: src/Model/User.php:666
msgid "Not enough information to authenticate" msgid "Not enough information to authenticate"
msgstr "" msgstr ""
#: src/Model/User.php:776 #: src/Model/User.php:787
msgid "Password can't be empty" msgid "Password can't be empty"
msgstr "" msgstr ""
#: src/Model/User.php:818 #: src/Model/User.php:829
msgid "Empty passwords are not allowed." msgid "Empty passwords are not allowed."
msgstr "" msgstr ""
#: src/Model/User.php:822 #: src/Model/User.php:833
msgid "" msgid ""
"The new password has been exposed in a public data dump, please choose " "The new password has been exposed in a public data dump, please choose "
"another." "another."
msgstr "" msgstr ""
#: src/Model/User.php:826 #: src/Model/User.php:837
msgid "The password length is limited to 72 characters." msgid "The password length is limited to 72 characters."
msgstr "" msgstr ""
#: src/Model/User.php:830 #: src/Model/User.php:841
msgid "The password can't contain white spaces nor accentuated letters" msgid "The password can't contain white spaces nor accentuated letters"
msgstr "" msgstr ""
#: src/Model/User.php:1025 #: src/Model/User.php:1050
msgid "Passwords do not match. Password unchanged." msgid "Passwords do not match. Password unchanged."
msgstr "" msgstr ""
#: src/Model/User.php:1032 #: src/Model/User.php:1057
msgid "An invitation is required." msgid "An invitation is required."
msgstr "" msgstr ""
#: src/Model/User.php:1036 #: src/Model/User.php:1061
msgid "Invitation could not be verified." msgid "Invitation could not be verified."
msgstr "" msgstr ""
#: src/Model/User.php:1044 #: src/Model/User.php:1069
msgid "Invalid OpenID url" msgid "Invalid OpenID url"
msgstr "" msgstr ""
#: src/Model/User.php:1057 src/Security/Authentication.php:241 #: src/Model/User.php:1082 src/Security/Authentication.php:241
msgid "" msgid ""
"We encountered a problem while logging in with the OpenID you provided. " "We encountered a problem while logging in with the OpenID you provided. "
"Please check the correct spelling of the ID." "Please check the correct spelling of the ID."
msgstr "" msgstr ""
#: src/Model/User.php:1057 src/Security/Authentication.php:241 #: src/Model/User.php:1082 src/Security/Authentication.php:241
msgid "The error message was:" msgid "The error message was:"
msgstr "" msgstr ""
#: src/Model/User.php:1063 #: src/Model/User.php:1088
msgid "Please enter the required information." msgid "Please enter the required information."
msgstr "" msgstr ""
#: src/Model/User.php:1077 #: src/Model/User.php:1102
#, php-format #, php-format
msgid "" msgid ""
"system.username_min_length (%s) and system.username_max_length (%s) are " "system.username_min_length (%s) and system.username_max_length (%s) are "
"excluding each other, swapping values." "excluding each other, swapping values."
msgstr "" msgstr ""
#: src/Model/User.php:1084 #: src/Model/User.php:1109
#, php-format #, php-format
msgid "Username should be at least %s character." msgid "Username should be at least %s character."
msgid_plural "Username should be at least %s characters." msgid_plural "Username should be at least %s characters."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Model/User.php:1088 #: src/Model/User.php:1113
#, php-format #, php-format
msgid "Username should be at most %s character." msgid "Username should be at most %s character."
msgid_plural "Username should be at most %s characters." msgid_plural "Username should be at most %s characters."
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Model/User.php:1096 #: src/Model/User.php:1121
msgid "That doesn't appear to be your full (First Last) name." msgid "That doesn't appear to be your full (First Last) name."
msgstr "" msgstr ""
#: src/Model/User.php:1101 #: src/Model/User.php:1126
msgid "Your email domain is not among those allowed on this site." msgid "Your email domain is not among those allowed on this site."
msgstr "" msgstr ""
#: src/Model/User.php:1105 #: src/Model/User.php:1130
msgid "Not a valid email address." msgid "Not a valid email address."
msgstr "" msgstr ""
#: src/Model/User.php:1108 #: src/Model/User.php:1133
msgid "The nickname was blocked from registration by the nodes admin." msgid "The nickname was blocked from registration by the nodes admin."
msgstr "" msgstr ""
#: src/Model/User.php:1112 src/Model/User.php:1118 #: src/Model/User.php:1137 src/Model/User.php:1143
msgid "Cannot use that email." msgid "Cannot use that email."
msgstr "" msgstr ""
#: src/Model/User.php:1124 #: src/Model/User.php:1149
msgid "Your nickname can only contain a-z, 0-9 and _." msgid "Your nickname can only contain a-z, 0-9 and _."
msgstr "" msgstr ""
#: src/Model/User.php:1132 src/Model/User.php:1189 #: src/Model/User.php:1157 src/Model/User.php:1214
msgid "Nickname is already registered. Please choose another." msgid "Nickname is already registered. Please choose another."
msgstr "" msgstr ""
#: src/Model/User.php:1176 src/Model/User.php:1180 #: src/Model/User.php:1201 src/Model/User.php:1205
msgid "An error occurred during registration. Please try again." msgid "An error occurred during registration. Please try again."
msgstr "" msgstr ""
#: src/Model/User.php:1203 #: src/Model/User.php:1228
msgid "An error occurred creating your default profile. Please try again." msgid "An error occurred creating your default profile. Please try again."
msgstr "" msgstr ""
#: src/Model/User.php:1210 #: src/Model/User.php:1235
msgid "An error occurred creating your self contact. Please try again." msgid "An error occurred creating your self contact. Please try again."
msgstr "" msgstr ""
#: src/Model/User.php:1215 #: src/Model/User.php:1240
msgid "Friends" msgid "Friends"
msgstr "" msgstr ""
#: src/Model/User.php:1219 #: src/Model/User.php:1244
msgid "" msgid ""
"An error occurred creating your default contact circle. Please try again." "An error occurred creating your default contact circle. Please try again."
msgstr "" msgstr ""
#: src/Model/User.php:1263 #: src/Model/User.php:1288
msgid "Profile Photos" msgid "Profile Photos"
msgstr "" msgstr ""
#: src/Model/User.php:1458 #: src/Model/User.php:1483
#, php-format #, php-format
msgid "" msgid ""
"\n" "\n"
@ -3605,7 +3605,7 @@ msgid ""
"\t\t\tthe administrator of %2$s has set up an account for you." "\t\t\tthe administrator of %2$s has set up an account for you."
msgstr "" msgstr ""
#: src/Model/User.php:1461 #: src/Model/User.php:1486
#, php-format #, php-format
msgid "" msgid ""
"\n" "\n"
@ -3643,12 +3643,12 @@ msgid ""
"\t\tThank you and welcome to %4$s." "\t\tThank you and welcome to %4$s."
msgstr "" msgstr ""
#: src/Model/User.php:1494 src/Model/User.php:1601 #: src/Model/User.php:1519 src/Model/User.php:1626
#, php-format #, php-format
msgid "Registration details for %s" msgid "Registration details for %s"
msgstr "" msgstr ""
#: src/Model/User.php:1514 #: src/Model/User.php:1539
#, php-format #, php-format
msgid "" msgid ""
"\n" "\n"
@ -3664,12 +3664,12 @@ msgid ""
"\t\t" "\t\t"
msgstr "" msgstr ""
#: src/Model/User.php:1533 #: src/Model/User.php:1558
#, php-format #, php-format
msgid "Registration at %s" msgid "Registration at %s"
msgstr "" msgstr ""
#: src/Model/User.php:1557 #: src/Model/User.php:1582
#, php-format #, php-format
msgid "" msgid ""
"\n" "\n"
@ -3678,7 +3678,7 @@ msgid ""
"\t\t\t" "\t\t\t"
msgstr "" msgstr ""
#: src/Model/User.php:1565 #: src/Model/User.php:1590
#, php-format #, php-format
msgid "" msgid ""
"\n" "\n"
@ -3742,7 +3742,7 @@ msgid "Enable"
msgstr "" msgstr ""
#: src/Module/Admin/Addons/Details.php:111 src/Module/Admin/Addons/Index.php:67 #: src/Module/Admin/Addons/Details.php:111 src/Module/Admin/Addons/Index.php:67
#: src/Module/Admin/Federation.php:210 src/Module/Admin/Logs/Settings.php:85 #: src/Module/Admin/Federation.php:214 src/Module/Admin/Logs/Settings.php:85
#: src/Module/Admin/Logs/View.php:83 src/Module/Admin/Queue.php:72 #: src/Module/Admin/Logs/View.php:83 src/Module/Admin/Queue.php:72
#: src/Module/Admin/Site.php:398 src/Module/Admin/Storage.php:138 #: src/Module/Admin/Site.php:398 src/Module/Admin/Storage.php:138
#: src/Module/Admin/Summary.php:196 src/Module/Admin/Themes/Details.php:90 #: src/Module/Admin/Summary.php:196 src/Module/Admin/Themes/Details.php:90
@ -3878,71 +3878,71 @@ msgstr ""
msgid "Other" msgid "Other"
msgstr "" msgstr ""
#: src/Module/Admin/Federation.php:150 src/Module/Admin/Federation.php:399 #: src/Module/Admin/Federation.php:154 src/Module/Admin/Federation.php:403
msgid "unknown" msgid "unknown"
msgstr "" msgstr ""
#: src/Module/Admin/Federation.php:183 #: src/Module/Admin/Federation.php:187
#, php-format #, php-format
msgid "%2$s total system" msgid "%2$s total system"
msgid_plural "%2$s total systems" msgid_plural "%2$s total systems"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/Admin/Federation.php:184 #: src/Module/Admin/Federation.php:188
#, php-format #, php-format
msgid "%2$s active user last month" msgid "%2$s active user last month"
msgid_plural "%2$s active users last month" msgid_plural "%2$s active users last month"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/Admin/Federation.php:185 #: src/Module/Admin/Federation.php:189
#, php-format #, php-format
msgid "%2$s active user last six months" msgid "%2$s active user last six months"
msgid_plural "%2$s active users last six months" msgid_plural "%2$s active users last six months"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/Admin/Federation.php:186 #: src/Module/Admin/Federation.php:190
#, php-format #, php-format
msgid "%2$s registered user" msgid "%2$s registered user"
msgid_plural "%2$s registered users" msgid_plural "%2$s registered users"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/Admin/Federation.php:187 #: src/Module/Admin/Federation.php:191
#, php-format #, php-format
msgid "%2$s locally created post or comment" msgid "%2$s locally created post or comment"
msgid_plural "%2$s locally created posts and comments" msgid_plural "%2$s locally created posts and comments"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/Admin/Federation.php:190 #: src/Module/Admin/Federation.php:194
#, php-format #, php-format
msgid "%2$s post per user" msgid "%2$s post per user"
msgid_plural "%2$s posts per user" msgid_plural "%2$s posts per user"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/Admin/Federation.php:195 #: src/Module/Admin/Federation.php:199
#, php-format #, php-format
msgid "%2$s user per system" msgid "%2$s user per system"
msgid_plural "%2$s users per system" msgid_plural "%2$s users per system"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/Admin/Federation.php:205 #: src/Module/Admin/Federation.php:209
msgid "" msgid ""
"This page offers you some numbers to the known part of the federated social " "This page offers you some numbers to the known part of the federated social "
"network your Friendica node is part of. These numbers are not complete but " "network your Friendica node is part of. These numbers are not complete but "
"only reflect the part of the network your node is aware of." "only reflect the part of the network your node is aware of."
msgstr "" msgstr ""
#: src/Module/Admin/Federation.php:211 src/Module/BaseAdmin.php:87 #: src/Module/Admin/Federation.php:215 src/Module/BaseAdmin.php:87
msgid "Federation Statistics" msgid "Federation Statistics"
msgstr "" msgstr ""
#: src/Module/Admin/Federation.php:215 #: src/Module/Admin/Federation.php:219
#, php-format #, php-format
msgid "" msgid ""
"Currently this node is aware of %2$s node (%3$s active users last month, " "Currently this node is aware of %2$s node (%3$s active users last month, "
@ -5420,11 +5420,11 @@ msgstr ""
msgid "Please login to continue." msgid "Please login to continue."
msgstr "" msgstr ""
#: src/Module/BaseAdmin.php:63 src/Module/BaseModeration.php:86 #: src/Module/BaseAdmin.php:63
msgid "You don't have access to administration pages." msgid "You don't have access to administration pages."
msgstr "" msgstr ""
#: src/Module/BaseAdmin.php:67 src/Module/BaseModeration.php:90 #: src/Module/BaseAdmin.php:67
msgid "" msgid ""
"Submanaged account can't access the administration pages. Please log back in " "Submanaged account can't access the administration pages. Please log back in "
"as the main account." "as the main account."
@ -5517,6 +5517,16 @@ msgid_plural ""
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/Module/BaseModeration.php:86
msgid "You don't have access to moderation pages."
msgstr ""
#: src/Module/BaseModeration.php:90
msgid ""
"Submanaged account can't access the moderation pages. Please log back in as "
"the main account."
msgstr ""
#: src/Module/BaseModeration.php:112 src/Module/Moderation/Users/Index.php:148 #: src/Module/BaseModeration.php:112 src/Module/Moderation/Users/Index.php:148
#: src/Module/Moderation/Users/Index.php:158 #: src/Module/Moderation/Users/Index.php:158
msgid "Users" msgid "Users"
@ -5746,23 +5756,23 @@ msgstr ""
msgid "list" msgid "list"
msgstr "" msgstr ""
#: src/Module/Circle.php:56 #: src/Module/Circle.php:57
msgid "Could not create circle." msgid "Could not create circle."
msgstr "" msgstr ""
#: src/Module/Circle.php:67 src/Module/Circle.php:215 src/Module/Circle.php:239 #: src/Module/Circle.php:68 src/Module/Circle.php:214 src/Module/Circle.php:238
msgid "Circle not found." msgid "Circle not found."
msgstr "" msgstr ""
#: src/Module/Circle.php:73 #: src/Module/Circle.php:74
msgid "Circle name was not changed." msgid "Circle name was not changed."
msgstr "" msgstr ""
#: src/Module/Circle.php:91 #: src/Module/Circle.php:92
msgid "Unknown circle." msgid "Unknown circle."
msgstr "" msgstr ""
#: src/Module/Circle.php:97 src/Module/Circle.php:106 #: src/Module/Circle.php:98 src/Module/Circle.php:107
#: src/Module/Contact/Advanced.php:70 src/Module/Contact/Advanced.php:109 #: src/Module/Contact/Advanced.php:70 src/Module/Contact/Advanced.php:109
#: src/Module/Contact/Contacts.php:71 src/Module/Contact/Conversations.php:84 #: src/Module/Contact/Contacts.php:71 src/Module/Contact/Conversations.php:84
#: src/Module/Contact/Conversations.php:89 #: src/Module/Contact/Conversations.php:89
@ -5775,76 +5785,76 @@ msgstr ""
msgid "Contact not found." msgid "Contact not found."
msgstr "" msgstr ""
#: src/Module/Circle.php:101 src/Module/Contact/Contacts.php:66 #: src/Module/Circle.php:102 src/Module/Contact/Contacts.php:66
#: src/Module/Conversation/Network.php:189 #: src/Module/Conversation/Network.php:189
msgid "Invalid contact." msgid "Invalid contact."
msgstr "" msgstr ""
#: src/Module/Circle.php:110 src/Module/Contact/Revoke.php:73 #: src/Module/Circle.php:111 src/Module/Contact/Revoke.php:73
msgid "Contact is deleted." msgid "Contact is deleted."
msgstr "" msgstr ""
#: src/Module/Circle.php:116 #: src/Module/Circle.php:117
msgid "Unable to add the contact to the circle." msgid "Unable to add the contact to the circle."
msgstr "" msgstr ""
#: src/Module/Circle.php:119 #: src/Module/Circle.php:120
msgid "Contact successfully added to circle." msgid "Contact successfully added to circle."
msgstr "" msgstr ""
#: src/Module/Circle.php:123 #: src/Module/Circle.php:124
msgid "Unable to remove the contact from the circle." msgid "Unable to remove the contact from the circle."
msgstr "" msgstr ""
#: src/Module/Circle.php:126 #: src/Module/Circle.php:127
msgid "Contact successfully removed from circle." msgid "Contact successfully removed from circle."
msgstr "" msgstr ""
#: src/Module/Circle.php:130 #: src/Module/Circle.php:131
msgid "Bad request." msgid "Bad request."
msgstr "" msgstr ""
#: src/Module/Circle.php:171 #: src/Module/Circle.php:170
msgid "Save Circle" msgid "Save Circle"
msgstr "" msgstr ""
#: src/Module/Circle.php:172 #: src/Module/Circle.php:171
msgid "Filter" msgid "Filter"
msgstr "" msgstr ""
#: src/Module/Circle.php:178 #: src/Module/Circle.php:177
msgid "Create a circle of contacts/friends." msgid "Create a circle of contacts/friends."
msgstr "" msgstr ""
#: src/Module/Circle.php:220 #: src/Module/Circle.php:219
msgid "Unable to remove circle." msgid "Unable to remove circle."
msgstr "" msgstr ""
#: src/Module/Circle.php:271 #: src/Module/Circle.php:270
msgid "Delete Circle" msgid "Delete Circle"
msgstr "" msgstr ""
#: src/Module/Circle.php:281 #: src/Module/Circle.php:280
msgid "Edit Circle Name" msgid "Edit Circle Name"
msgstr "" msgstr ""
#: src/Module/Circle.php:291 #: src/Module/Circle.php:290
msgid "Members" msgid "Members"
msgstr "" msgstr ""
#: src/Module/Circle.php:294 #: src/Module/Circle.php:293
msgid "Circle is empty" msgid "Circle is empty"
msgstr "" msgstr ""
#: src/Module/Circle.php:307 #: src/Module/Circle.php:306
msgid "Remove contact from circle" msgid "Remove contact from circle"
msgstr "" msgstr ""
#: src/Module/Circle.php:328 #: src/Module/Circle.php:329
msgid "Click on a contact to add or remove." msgid "Click on a contact to add or remove."
msgstr "" msgstr ""
#: src/Module/Circle.php:342 #: src/Module/Circle.php:343
msgid "Add contact to circle" msgid "Add contact to circle"
msgstr "" msgstr ""
@ -8347,11 +8357,11 @@ msgstr ""
msgid "Show unread" msgid "Show unread"
msgstr "" msgstr ""
#: src/Module/Notifications/Ping.php:245 #: src/Module/Notifications/Ping.php:246
msgid "{0} requested registration" msgid "{0} requested registration"
msgstr "" msgstr ""
#: src/Module/Notifications/Ping.php:254 #: src/Module/Notifications/Ping.php:255
#, php-format #, php-format
msgid "{0} and %d others requested registration" msgid "{0} and %d others requested registration"
msgstr "" msgstr ""
@ -8370,7 +8380,7 @@ msgstr ""
msgid "Unsupported or missing response type" msgid "Unsupported or missing response type"
msgstr "" msgstr ""
#: src/Module/OAuth/Authorize.php:59 src/Module/OAuth/Token.php:77 #: src/Module/OAuth/Authorize.php:59 src/Module/OAuth/Token.php:78
msgid "Incomplete request data" msgid "Incomplete request data"
msgstr "" msgstr ""
@ -8381,11 +8391,11 @@ msgid ""
"close this window: %s" "close this window: %s"
msgstr "" msgstr ""
#: src/Module/OAuth/Token.php:82 #: src/Module/OAuth/Token.php:83
msgid "Invalid data or unknown client" msgid "Invalid data or unknown client"
msgstr "" msgstr ""
#: src/Module/OAuth/Token.php:104 #: src/Module/OAuth/Token.php:108
msgid "Unsupported or missing grant type" msgid "Unsupported or missing grant type"
msgstr "" msgstr ""
@ -10723,7 +10733,7 @@ msgstr ""
msgid "Exception thrown in %s:%d" msgid "Exception thrown in %s:%d"
msgstr "" msgstr ""
#: src/Module/Tos.php:57 src/Module/Tos.php:106 #: src/Module/Tos.php:58 src/Module/Tos.php:107
msgid "" msgid ""
"At the time of registration, and for providing communications between the " "At the time of registration, and for providing communications between the "
"user account and their contacts, the user has to provide a display name (pen " "user account and their contacts, the user has to provide a display name (pen "
@ -10736,14 +10746,14 @@ msgid ""
"settings, it is not necessary for communication." "settings, it is not necessary for communication."
msgstr "" msgstr ""
#: src/Module/Tos.php:58 src/Module/Tos.php:107 #: src/Module/Tos.php:59 src/Module/Tos.php:108
msgid "" msgid ""
"This data is required for communication and is passed on to the nodes of the " "This data is required for communication and is passed on to the nodes of the "
"communication partners and is stored there. Users can enter additional " "communication partners and is stored there. Users can enter additional "
"private data that may be transmitted to the communication partners accounts." "private data that may be transmitted to the communication partners accounts."
msgstr "" msgstr ""
#: src/Module/Tos.php:59 src/Module/Tos.php:108 #: src/Module/Tos.php:60 src/Module/Tos.php:109
#, php-format #, php-format
msgid "" msgid ""
"At any point in time a logged in user can export their account data from the " "At any point in time a logged in user can export their account data from the "
@ -10754,11 +10764,11 @@ msgid ""
"communication partners." "communication partners."
msgstr "" msgstr ""
#: src/Module/Tos.php:62 src/Module/Tos.php:105 #: src/Module/Tos.php:63 src/Module/Tos.php:106
msgid "Privacy Statement" msgid "Privacy Statement"
msgstr "" msgstr ""
#: src/Module/Tos.php:102 #: src/Module/Tos.php:103
msgid "Rules" msgid "Rules"
msgstr "" msgstr ""

View file

@ -1,4 +1,3 @@
<div class='field combobox'> <div class='field combobox'>
<label for='id_{{$field.0}}' id='id_{{$field.0}}_label'>{{$field.1}}</label> <label for='id_{{$field.0}}' id='id_{{$field.0}}_label'>{{$field.1}}</label>
{{* html5 don't work on Chrome, Safari and IE9 {{* html5 don't work on Chrome, Safari and IE9
@ -7,7 +6,7 @@
{{foreach $field.4 as $opt=>$val}}<option value="{{$val}}">{{/foreach}} {{foreach $field.4 as $opt=>$val}}<option value="{{$val}}">{{/foreach}}
</datalist> *}} </datalist> *}}
<input id="id_{{$field.0}}" type="text" value="{{$field.2 nofilter}}" aria-describedby='{{$field.0}}_tip'> <input id="id_{{$field.0}}" type="text" value="{{$field.2}}" aria-describedby='{{$field.0}}_tip'>
<select id="select_{{$field.0}}" onChange="$('#id_{{$field.0}}').val($(this).val())"> <select id="select_{{$field.0}}" onChange="$('#id_{{$field.0}}').val($(this).val())">
<option value="">{{$field.5}}</option> <option value="">{{$field.5}}</option>
{{foreach $field.4 as $opt=>$val}}<option value="{{$val}}">{{$val}}</option>{{/foreach}} {{foreach $field.4 as $opt=>$val}}<option value="{{$val}}">{{$val}}</option>{{/foreach}}

View file

@ -1,7 +1,6 @@
<div class='field input openid' id='wrapper_{{$field.0}}'> <div class='field input openid' id='wrapper_{{$field.0}}'>
<label for='id_{{$field.0}}'>{{$field.1}}</label> <label for='id_{{$field.0}}'>{{$field.1}}</label>
<input name='{{$field.0}}' id='id_{{$field.0}}' type="text" value="{{$field.2 nofilter}}" {{if $field.4}} readonly="readonly" {{/if}} aria-describedby='{{$field.0}}_tip'> <input name='{{$field.0}}' id='id_{{$field.0}}' type="text" value="{{$field.2}}" {{if $field.4}} readonly="readonly" {{/if}} aria-describedby='{{$field.0}}_tip'>
{{if $field.3}} {{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3 nofilter}}</span> <span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3 nofilter}}</span>
{{/if}} {{/if}}

View file

@ -1,7 +1,6 @@
<div class="field password" id="wrapper_{{$field.0}}"> <div class="field password" id="wrapper_{{$field.0}}">
<label for="id_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label> <label for="id_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label>
<input type="password" name="{{$field.0}}" id="id_{{$field.0}}" value="{{$field.2 nofilter}}"{{if $field.4}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5}}{{/if}}{{if $field.6}} pattern="(($field.6}}"{{/if}} aria-describedby="{{$field.0}}_tip"> <input type="password" name="{{$field.0}}" id="id_{{$field.0}}" value="{{$field.2}}"{{if $field.4}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5}}{{/if}}{{if $field.6}} pattern="(($field.6}}"{{/if}} aria-describedby="{{$field.0}}_tip">
{{if $field.3}} {{if $field.3}}
<span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3 nofilter}}</span> <span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3 nofilter}}</span>
{{/if}} {{/if}}

View file

@ -137,12 +137,12 @@ $is_singleuser_class = $is_singleuser ? "is-singleuser" : "is-not-singleuser";
'; ';
} else { } else {
echo ' echo '
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12" id="content" style="margin-top:50px;">'; <section class="col-lg-12 col-md-12 col-sm-12 col-xs-12" id="content" style="margin-top:50px;">';
if (!empty($page['content'])) { if (!empty($page['content'])) {
echo $page['content']; echo $page['content'];
} }
echo ' echo '
</div> </section>
'; ';
} }
?> ?>

View file

@ -1,9 +1,8 @@
<div class="form-group field input color"> <div class="form-group field input color">
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label> <label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label>
<div class="input-group" id="{{$field.0}}"> <div class="input-group" id="{{$field.0}}">
<span class="input-group-addon"><i></i></span> <span class="input-group-addon"><i></i></span>
<input class="form-control color" name="{{$field.0}}" id="id_{{$field.0}}" type="text" value="{{$field.2 nofilter}}"{{if $field.4}} required{{/if}} aria-describedby="{{$field.0}}_tip"> <input class="form-control color" name="{{$field.0}}" id="id_{{$field.0}}" type="text" value="{{$field.2}}"{{if $field.4}} required{{/if}} aria-describedby="{{$field.0}}_tip">
</div> </div>
{{if $field.3}} {{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3 nofilter}}</span> <span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3 nofilter}}</span>

View file

@ -1,8 +1,7 @@
<div class="form-group field input file"> <div class="form-group field input file">
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label> <label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label>
<div class="input-group" id="{{$field.0}}"> <div class="input-group" id="{{$field.0}}">
<input class="form-control file" name="{{$field.0}}" id="id_{{$field.0}}" type="text" value="{{$field.2 nofilter}}"{{if $field.4}} required{{/if}} aria-describedby="{{$field.0}}_tip"> <input class="form-control file" name="{{$field.0}}" id="id_{{$field.0}}" type="text" value="{{$field.2}}"{{if $field.4}} required{{/if}} aria-describedby="{{$field.0}}_tip">
<span class="input-group-addon image-select"><i class="fa fa-picture-o"></i></span> <span class="input-group-addon image-select"><i class="fa fa-picture-o"></i></span>
</div> </div>
{{if $field.3}} {{if $field.3}}

View file

@ -1,7 +1,6 @@
<div id="id_{{$field.0}}_wrapper" class="form-group field input openid"> <div id="id_{{$field.0}}_wrapper" class="form-group field input openid">
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}</label> <label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}</label>
<input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" type="text" value="{{$field.2 nofilter}}" {{if $field.4}} readonly="readonly" {{/if}} aria-describedby="{{$field.0}}_tip"> <input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" type="text" value="{{$field.2}}" {{if $field.4}} readonly="readonly" {{/if}} aria-describedby="{{$field.0}}_tip">
{{if $field.3}} {{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3 nofilter}}</span> <span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3 nofilter}}</span>
{{/if}} {{/if}}

View file

@ -1,7 +1,6 @@
<div id="id_{{$field.0}}_wrapper" class="form-group field input password"> <div id="id_{{$field.0}}_wrapper" class="form-group field input password">
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label> <label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1}}{{if $field.4}} <span class="required" title="{{$field.4}}">*</span>{{/if}}</label>
<input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" type="password" value="{{$field.2 nofilter}}" {{if $field.4}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5}}{{/if}}{{if $field.6}} pattern="{{$field.6}}"{{/if}} aria-describedby="{{$field.0}}_tip"> <input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}" type="password" value="{{$field.2}}" {{if $field.4}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5}}{{/if}}{{if $field.6}} pattern="{{$field.6}}"{{/if}} aria-describedby="{{$field.0}}_tip">
{{if $field.3}} {{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3 nofilter}}</span> <span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3 nofilter}}</span>
{{/if}} {{/if}}

View file

@ -278,7 +278,7 @@
<li role="presentation"> <li role="presentation">
<a role="menuitem" id="nav-about-link" class="nav-link {{$nav.about.2}}" <a role="menuitem" id="nav-about-link" class="nav-link {{$nav.about.2}}"
href="{{$nav.about.0}}" title="{{$nav.about.3}}"> href="{{$nav.about.0}}" title="{{$nav.about.3}}">
<i class="fa fa-info" aria-hidden="true"></i> {{$nav.about.1}} <i class="fa fa-info fa-fw" aria-hidden="true"></i> {{$nav.about.1}}
</a> </a>
</li> </li>
{{if $nav.tos}} {{if $nav.tos}}
@ -411,7 +411,7 @@
<li role="presentation" class="list-group-item"> <li role="presentation" class="list-group-item">
<a role="menuitem" class="nav-link {{$nav.about.2}}" <a role="menuitem" class="nav-link {{$nav.about.2}}"
href="{{$nav.about.0}}" title="{{$nav.about.3}}"> href="{{$nav.about.0}}" title="{{$nav.about.3}}">
<i class="fa fa-info" aria-hidden="true"></i> {{$nav.about.1}} <i class="fa fa-info fa-fw" aria-hidden="true"></i> {{$nav.about.1}}
</a> </a>
</li> </li>
<li role="presentation" class="divider"></li> <li role="presentation" class="divider"></li>

View file

@ -1,4 +1,8 @@
<div id="item-{{$item.guid}}" class="item-{{$item.id}}"> <div id="item-{{$item.guid}}" class="item-{{$item.id}}">
<span class="commented" style="display: none;">{{$item.commented}}</span>
<span class="received" style="display: none;">{{$item.received}}</span>
<span class="created" style="display: none;">{{$item.created_date}}</span>
<span class="uriid" style="display: none;">{{$item.uriid}}</span>
<div class="wall-item-container panel-body{{$item.indent}} {{$item.shiny}} {{$item.previewing}}"> <div class="wall-item-container panel-body{{$item.indent}} {{$item.shiny}} {{$item.previewing}}">
<div class="media"> <div class="media">
{{* Put additional actions in a top-right dropdown menu *}} {{* Put additional actions in a top-right dropdown menu *}}