Merge remote-tracking branch 'origin/2022.12-rc' into fixes

This commit is contained in:
Michael 2022-12-11 19:00:59 +00:00
commit 2f3f41ed9c
714 changed files with 34811 additions and 27839 deletions

View file

@ -62,7 +62,7 @@ class ACL
$page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.css'));
$page->registerStylesheet(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput-typeahead.css'));
$contacts = self::getValidMessageRecipientsForUser(local_user());
$contacts = self::getValidMessageRecipientsForUser(DI::userSession()->getLocalUserId());
$tpl = Renderer::getMarkupTemplate('acl/message_recipient.tpl');
$o = Renderer::replaceMacros($tpl, [

View file

@ -127,7 +127,7 @@ class MemcachedCache extends AbstractCache implements ICanCacheInMemory
if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) {
return $value;
} elseif ($this->memcached->getResultCode() === Memcached::RES_NOTFOUND) {
$this->logger->notice('Try to use unknown key.', ['key' => $key]);
$this->logger->debug('Try to use unknown key.', ['key' => $key]);
return null;
} else {
throw new CachePersistenceException(sprintf('Cannot get cache entry with key %s', $key), new \MemcachedException($this->memcached->getResultMessage(), $this->memcached->getResultCode()));

View file

@ -51,7 +51,7 @@ interface IManageConfigValues
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
* @param mixed $default_value optional, The value to return if key is not set (default: null)
* @param mixed $default_value Deprecated, use `Config->get($cat, $key, null, $refresh) ?? $default_value` instead
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
*
* @return mixed Stored value or null if it does not exist

View file

@ -23,6 +23,7 @@ namespace Friendica\Core;
use Dice\Dice;
use Friendica;
use Friendica\App;
/**
* Description of Console
@ -133,7 +134,7 @@ HELP;
$command = null;
if ($this->getOption('version')) {
$this->out('Friendica Console version ' . FRIENDICA_VERSION);
$this->out('Friendica Console version ' . App::VERSION);
return 0;
} elseif ((count($this->options) === 0 || $this->getOption($this->customHelpOptions) === true || $this->getOption($this->customHelpOptions) === 1) && count($this->args) === 0

View file

@ -197,7 +197,7 @@ class Installer
$result = DBStructure::install();
if ($result) {
$txt = DI::l10n()->t('You may need to import the file "database.sql" manually using phpmyadmin or mysql.') . EOL;
$txt = DI::l10n()->t('You may need to import the file "database.sql" manually using phpmyadmin or mysql.') . '<br />';
$txt .= DI::l10n()->t('Please see the file "doc/INSTALL.md".');
$this->addCheck($txt, false, true, htmlentities($result, ENT_COMPAT, 'UTF-8'));
@ -259,9 +259,9 @@ class Installer
$help = "";
if (!$passed) {
$help .= DI::l10n()->t('Could not find a command line version of PHP in the web server PATH.') . EOL;
$help .= DI::l10n()->t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/stable/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>") . EOL;
$help .= EOL . EOL;
$help .= DI::l10n()->t('Could not find a command line version of PHP in the web server PATH.') . '<br />';
$help .= DI::l10n()->t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/stable/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>") . '<br />';
$help .= '<br /><br />';
$tpl = Renderer::getMarkupTemplate('field_input.tpl');
/// @todo Separate backend Installer class and presentation layer/view
$help .= Renderer::replaceMacros($tpl, [
@ -279,7 +279,7 @@ class Installer
[$result] = explode("\n", $result);
$help = "";
if (!$passed2) {
$help .= DI::l10n()->t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL;
$help .= DI::l10n()->t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . '<br />';
$help .= DI::l10n()->t('Found PHP version: ') . "<tt>$result</tt>";
}
$this->addCheck(DI::l10n()->t('PHP cli binary'), $passed2, true, $help);
@ -295,7 +295,7 @@ class Installer
$passed3 = $result == $str;
$help = "";
if (!$passed3) {
$help .= DI::l10n()->t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL;
$help .= DI::l10n()->t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . '<br />';
$help .= DI::l10n()->t('This is required for message delivery to work.');
} else {
$this->phppath = $phppath;
@ -333,7 +333,7 @@ class Installer
// Get private key
if (!$res) {
$help .= DI::l10n()->t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL;
$help .= DI::l10n()->t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . '<br />';
$help .= DI::l10n()->t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
$status = false;
}
@ -511,10 +511,10 @@ class Installer
(!file_exists('config/local.config.php') && !is_writable('.'))) {
$status = false;
$help = DI::l10n()->t('The web installer needs to be able to create a file called "local.config.php" in the "config" folder of your web server and it is unable to do so.') . EOL;
$help .= DI::l10n()->t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . EOL;
$help .= DI::l10n()->t('At the end of this procedure, we will give you a text to save in a file named local.config.php in your Friendica "config" folder.') . EOL;
$help .= DI::l10n()->t('You can alternatively skip this procedure and perform a manual installation. Please see the file "doc/INSTALL.md" for instructions.') . EOL;
$help = DI::l10n()->t('The web installer needs to be able to create a file called "local.config.php" in the "config" folder of your web server and it is unable to do so.') . '<br />';
$help .= DI::l10n()->t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . '<br />';
$help .= DI::l10n()->t('At the end of this procedure, we will give you a text to save in a file named local.config.php in your Friendica "config" folder.') . '<br />';
$help .= DI::l10n()->t('You can alternatively skip this procedure and perform a manual installation. Please see the file "doc/INSTALL.md" for instructions.') . '<br />';
}
$this->addCheck(DI::l10n()->t('config/local.config.php is writable'), $status, false, $help);
@ -537,10 +537,10 @@ class Installer
if (!is_writable('view/smarty3')) {
$status = false;
$help = DI::l10n()->t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . EOL;
$help .= DI::l10n()->t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . EOL;
$help .= DI::l10n()->t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . EOL;
$help .= DI::l10n()->t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL;
$help = DI::l10n()->t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . '<br />';
$help .= DI::l10n()->t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . '<br />';
$help .= DI::l10n()->t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . '<br />';
$help .= DI::l10n()->t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . '<br />';
}
$this->addCheck(DI::l10n()->t('view/smarty3 is writable'), $status, true, $help);
@ -571,7 +571,7 @@ class Installer
if ($fetchResult->getReturnCode() != 204) {
$status = false;
$help = DI::l10n()->t('Url rewrite in .htaccess seems not working. Make sure you copied .htaccess-dist to .htaccess.') . EOL;
$help = DI::l10n()->t('Url rewrite in .htaccess seems not working. Make sure you copied .htaccess-dist to .htaccess.') . '<br />';
$help .= DI::l10n()->t('In some circumstances (like running inside containers), you can skip this error.');
$error_msg = [];
$error_msg['head'] = DI::l10n()->t('Error message from Curl when fetching');

View file

@ -188,10 +188,10 @@ class L10n
{
$lang_variable = $server['HTTP_ACCEPT_LANGUAGE'] ?? null;
$acceptedLanguages = preg_split('/,\s*/', $lang_variable);
if (empty($acceptedLanguages)) {
if (empty($lang_variable)) {
$acceptedLanguages = [];
} else {
$acceptedLanguages = preg_split('/,\s*/', $lang_variable);
}
// Add get as absolute quality accepted language (except this language isn't valid)

View file

@ -22,19 +22,16 @@
namespace Friendica\Core\Logger\Factory;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\Logger\Exception\LoggerException;
use Friendica\Core;
use Friendica\Core\Logger\Exception\LogLevelException;
use Friendica\Database\Database;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Util\FileSystem;
use Friendica\Core\Logger\Util\Introspection;
use Friendica\Core\Logger\Type\Monolog\DevelopHandler;
use Friendica\Core\Logger\Type\Monolog\IntrospectionProcessor;
use Friendica\Core\Logger\Type\ProfilerLogger;
use Friendica\Core\Logger\Type\StreamLogger;
use Friendica\Core\Logger\Type\SyslogLogger;
use Friendica\Util\Profiler;
use Monolog;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Psr\Log\NullLogger;
@ -60,9 +57,15 @@ class Logger
/** @var string The log-channel (app, worker, ...) */
private $channel;
public function __construct(string $channel)
public function __construct(string $channel, bool $includeAddon = true)
{
$this->channel = $channel;
/// @fixme clean solution = Making Addon & Hook dynamic and load them inside the constructor, so there's no custom load logic necessary anymore
if ($includeAddon) {
Core\Addon::loadAddons();
Core\Hook::loadHooks();
}
}
/**
@ -88,35 +91,9 @@ class Logger
$minLevel = $minLevel ?? $config->get('system', 'loglevel');
$loglevel = self::mapLegacyConfigDebugLevel((string)$minLevel);
switch ($config->get('system', 'logger_config', 'stream')) {
case 'monolog':
$loggerTimeZone = new \DateTimeZone('UTC');
Monolog\Logger::setTimezone($loggerTimeZone);
$logger = new Monolog\Logger($this->channel);
$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
$logger->pushProcessor(new Monolog\Processor\UidProcessor());
$logger->pushProcessor(new IntrospectionProcessor($introspection, LogLevel::DEBUG));
$stream = $config->get('system', 'logfile');
// just add a stream in case it's either writable or not file
if (!is_file($stream) || is_writable($stream)) {
try {
static::addStreamHandler($logger, $stream, $loglevel);
} catch (\Throwable $e) {
// No Logger ..
try {
$logger = new SyslogLogger($this->channel, $introspection, $loglevel);
} catch (\Throwable $e) {
// No logger ...
$logger = new NullLogger();
}
}
}
break;
$name = $config->get('system', 'logger_config', 'stream');
switch ($name) {
case 'syslog':
try {
$logger = new SyslogLogger($this->channel, $introspection, $loglevel, $config->get('system', 'syslog_flags', SyslogLogger::DEFAULT_FLAGS), $config->get('system', 'syslog_facility', SyslogLogger::DEFAULT_FACILITY));
@ -132,29 +109,48 @@ class Logger
case 'stream':
default:
$stream = $config->get('system', 'logfile');
// just add a stream in case it's either writable or not file
if (!is_file($stream) || is_writable($stream)) {
try {
$logger = new StreamLogger($this->channel, $stream, $introspection, $fileSystem, $loglevel);
} catch (LogLevelException $exception) {
// If there's a wrong config value for loglevel, try again with standard
$logger = $this->create($database, $config, $profiler, $fileSystem, LogLevel::NOTICE);
$logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]);
} catch (\Throwable $t) {
// No logger ...
$logger = new NullLogger();
}
} else {
try {
$logger = new SyslogLogger($this->channel, $introspection, $loglevel);
} catch (LogLevelException $exception) {
// If there's a wrong config value for loglevel, try again with standard
$logger = $this->create($database, $config, $profiler, $fileSystem, LogLevel::NOTICE);
$logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]);
} catch (\Throwable $e) {
// No logger ...
$logger = new NullLogger();
$data = [
'name' => $name,
'channel' => $this->channel,
'introspection' => $introspection,
'loglevel' => $loglevel,
'logger' => null,
];
try {
Core\Hook::callAll('logger_instance', $data);
} catch (InternalServerErrorException $exception) {
$data['logger'] = null;
}
if (($data['logger'] ?? null) instanceof LoggerInterface) {
$logger = $data['logger'];
}
if (empty($logger)) {
$stream = $config->get('system', 'logfile');
// just add a stream in case it's either writable or not file
if (!is_file($stream) || is_writable($stream)) {
try {
$logger = new StreamLogger($this->channel, $stream, $introspection, $fileSystem, $loglevel);
} catch (LogLevelException $exception) {
// If there's a wrong config value for loglevel, try again with standard
$logger = $this->create($database, $config, $profiler, $fileSystem, LogLevel::NOTICE);
$logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]);
} catch (\Throwable $t) {
// No logger ...
$logger = new NullLogger();
}
} else {
try {
$logger = new SyslogLogger($this->channel, $introspection, $loglevel);
} catch (LogLevelException $exception) {
// If there's a wrong config value for loglevel, try again with standard
$logger = $this->create($database, $config, $profiler, $fileSystem, LogLevel::NOTICE);
$logger->warning('Invalid loglevel set in config.', ['loglevel' => $loglevel]);
} catch (\Throwable $e) {
// No logger ...
$logger = new NullLogger();
}
}
}
break;
@ -197,27 +193,11 @@ class Logger
return new NullLogger();
}
$loggerTimeZone = new \DateTimeZone('UTC');
Monolog\Logger::setTimezone($loggerTimeZone);
$introspection = new Introspection(self::$ignoreClassList);
switch ($config->get('system', 'logger_config', 'stream')) {
$name = $config->get('system', 'logger_config', 'stream');
case 'monolog':
$loggerTimeZone = new \DateTimeZone('UTC');
Monolog\Logger::setTimezone($loggerTimeZone);
$logger = new Monolog\Logger(self::DEV_CHANNEL);
$logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
$logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
$logger->pushProcessor(new Monolog\Processor\UidProcessor());
$logger->pushProcessor(new IntrospectionProcessor($introspection, LogLevel::DEBUG));
$logger->pushHandler(new DevelopHandler($developerIp));
static::addStreamHandler($logger, $stream, LogLevel::DEBUG);
break;
switch ($name) {
case 'syslog':
$logger = new SyslogLogger(self::DEV_CHANNEL, $introspection, LogLevel::DEBUG);
@ -225,6 +205,23 @@ class Logger
case 'stream':
default:
$data = [
'name' => $name,
'channel' => self::DEV_CHANNEL,
'introspection' => $introspection,
'loglevel' => LogLevel::DEBUG,
'logger' => null,
];
try {
Core\Hook::callAll('logger_instance', $data);
} catch (InternalServerErrorException $exception) {
$data['logger'] = null;
}
if (($data['logger'] ?? null) instanceof LoggerInterface) {
return $data['logger'];
}
$logger = new StreamLogger(self::DEV_CHANNEL, $stream, $introspection, $fileSystem, LogLevel::DEBUG);
break;
}
@ -273,38 +270,4 @@ class Logger
return $level;
}
}
/**
* Adding a handler to a given logger instance
*
* @param LoggerInterface $logger The logger instance
* @param mixed $stream The stream which handles the logger output
* @param string $level The level, for which this handler at least should handle logging
*
* @return void
*
* @throws LoggerException
*/
public static function addStreamHandler(LoggerInterface $logger, $stream, string $level = LogLevel::NOTICE)
{
if ($logger instanceof Monolog\Logger) {
$loglevel = Monolog\Logger::toMonologLevel($level);
// fallback to notice if an invalid loglevel is set
if (!is_int($loglevel)) {
$loglevel = LogLevel::NOTICE;
}
try {
$fileHandler = new Monolog\Handler\StreamHandler($stream, $loglevel);
$formatter = new Monolog\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n");
$fileHandler->setFormatter($formatter);
$logger->pushHandler($fileHandler);
} catch (\Exception $exception) {
throw new LoggerException('Cannot create Monolog Logger.', $exception);
}
}
}
}

View file

@ -1,76 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Logger\Type\Monolog;
use Friendica\App\Request;
use Monolog\Handler;
use Monolog\Logger;
/**
* Simple handler for Friendica developers to use for deeper logging
*
* If you want to debug only interactions from your IP or the IP of a remote server for federation debug,
* you'll use Logger::develop() for the duration of your work, and you clean it up when you're done before submitting your PR.
*/
class DevelopHandler extends Handler\AbstractHandler
{
/**
* @var string The IP of the developer who wants to debug
*/
private $developerIp;
/**
* @var string The IP of the current request
*/
private $remoteAddress;
/**
* @param Request $request The current http request
* @param string $developerIp The IP of the developer who wants to debug
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(Request $request, $developerIp, int $level = Logger::DEBUG, bool $bubble = true)
{
parent::__construct($level, $bubble);
$this->developerIp = $developerIp;
$this->remoteAddress = $request->getRemoteAddress();
}
/**
* {@inheritdoc}
*/
public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
}
/// Just in case the remote IP is the same as the developer IP log the output
if (!is_null($this->developerIp) && $this->remoteAddress != $this->developerIp) {
return false;
}
return false === $this->bubble;
}
}

View file

@ -1,62 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Logger\Type\Monolog;
use Friendica\Core\Logger\Util\Introspection;
use Monolog\Logger;
use Monolog\Processor\ProcessorInterface;
/**
* Injects line/file//function where the log message came from
*/
class IntrospectionProcessor implements ProcessorInterface
{
private $level;
private $introspection;
/**
* @param Introspection $introspection Holds the Introspection of the current call
* @param string|int $level The minimum logging level at which this Processor will be triggered
*/
public function __construct(Introspection $introspection, $level = Logger::DEBUG)
{
$this->level = Logger::toMonologLevel($level);
$introspection->addClasses(['Monolog\\']);
$this->introspection = $introspection;
}
public function __invoke(array $record): array
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
return $record;
}
// we should have the call source now
$record['extra'] = array_merge(
$record['extra'],
$this->introspection->getRecord()
);
return $record;
}
}

View file

@ -5,7 +5,6 @@ This namespace contains the different implementations of a Logger.
### Configuration guideline
The following settings are possible for `logger_config`:
- `monolog`: A Logging framework with lots of additions (see [Monolog](https://github.com/Seldaek/monolog/)). There are just Friendica additions inside the Monolog directory
- [`stream`](StreamLogger.php): A small logger for files or streams
- [`syslog`](SyslogLogger.php): Prints the logging output into the syslog

View file

@ -51,7 +51,7 @@ interface IManagePersonalConfigValues
* @param int $uid The user_id
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
* @param mixed $default_value optional, The value to return if key is not set (default: null)
* @param mixed $default_value Deprecated, use `PConfig->get($uid, $cat, $key, null, $refresh) ?? $default_value` instead
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
*
* @return mixed Stored value or null if it does not exist

View file

@ -22,6 +22,7 @@
namespace Friendica\Core;
use Friendica\Database\DBA;
use Friendica\Model\Item;
use Friendica\Model\User;
use Friendica\Network\HTTPException;
use Friendica\Protocol\Activity;
@ -139,7 +140,7 @@ class Protocol
// create a follow slap
$item = [
'verb' => Activity::FOLLOW,
'gravity' => GRAVITY_ACTIVITY,
'gravity' => Item::GRAVITY_ACTIVITY,
'follow' => $contact['url'],
'body' => '',
'title' => '',
@ -181,7 +182,8 @@ class Protocol
public static function unfollow(array $contact, array $user): ?bool
{
if (empty($contact['network'])) {
throw new \InvalidArgumentException('Missing network key in contact array');
Logger::notice('Contact has got no network, we quit here', ['id' => $contact['id']]);
return null;
}
$protocol = $contact['network'];
@ -191,18 +193,21 @@ class Protocol
if (in_array($protocol, [Protocol::OSTATUS, Protocol::DFRN])) {
// create an unfollow slap
$item = [];
$item['verb'] = Activity::O_UNFOLLOW;
$item['gravity'] = GRAVITY_ACTIVITY;
$item['follow'] = $contact['url'];
$item['body'] = '';
$item['title'] = '';
$item['guid'] = '';
$item['uri-id'] = 0;
$item = [
'verb' => Activity::O_UNFOLLOW,
'gravity' => Item::GRAVITY_ACTIVITY,
'follow' => $contact['url'],
'body' => '',
'title' => '',
'guid' => '',
'uri-id' => 0,
];
$slap = OStatus::salmon($item, $user);
if (empty($contact['notify'])) {
throw new \InvalidArgumentException('Missing expected "notify" key in OStatus/DFRN contact');
Logger::notice('OStatus/DFRN Contact is missing notify, we quit here', ['id' => $contact['id']]);
return null;
}
return Salmon::slapper($user, $contact['notify'], $slap) === 0;

View file

@ -48,19 +48,19 @@ class Renderer
* beyond are used.
*/
public static $theme = [
'videowidth' => 425,
'videoheight' => 350,
'stylesheet' => '',
'videowidth' => 425,
'videoheight' => 350,
'stylesheet' => '',
'template_engine' => 'smarty3',
];
private static $ldelim = [
'internal' => '',
'smarty3' => '{{'
'smarty3' => '{{'
];
private static $rdelim = [
'internal' => '',
'smarty3' => '}}'
'smarty3' => '}}'
];
/**
@ -101,10 +101,10 @@ class Renderer
* @param string $file Template to load.
* @param string $subDir Subdirectory (Optional)
*
* @return string template.
* @return string Template
* @throws ServiceUnavailableException
*/
public static function getMarkupTemplate($file, $subDir = '')
public static function getMarkupTemplate(string $file, string $subDir = ''): string
{
DI::profiler()->startRecording('file');
$t = self::getTemplateEngine();
@ -128,9 +128,11 @@ class Renderer
* Register template engine class
*
* @param string $class
*
* @return void
* @throws ServiceUnavailableException
*/
public static function registerTemplateEngine($class)
public static function registerTemplateEngine(string $class)
{
$v = get_class_vars($class);
@ -156,7 +158,7 @@ class Renderer
* @return TemplateEngine Template Engine instance
* @throws ServiceUnavailableException
*/
public static function getTemplateEngine()
public static function getTemplateEngine(): TemplateEngine
{
$template_engine = (self::$theme['template_engine'] ?? '') ?: 'smarty3';
@ -185,7 +187,7 @@ class Renderer
*
* @return string the active template engine
*/
public static function getActiveTemplateEngine()
public static function getActiveTemplateEngine(): string
{
return self::$theme['template_engine'];
}
@ -194,8 +196,10 @@ class Renderer
* sets the active template engine
*
* @param string $engine the template engine (default is Smarty3)
*
* @return void
*/
public static function setActiveTemplateEngine($engine = 'smarty3')
public static function setActiveTemplateEngine(string $engine = 'smarty3')
{
self::$theme['template_engine'] = $engine;
}
@ -211,7 +215,7 @@ class Renderer
*
* @return string the right delimiter
*/
public static function getTemplateLeftDelimiter($engine = 'smarty3')
public static function getTemplateLeftDelimiter(string $engine = 'smarty3'): string
{
return self::$ldelim[$engine];
}
@ -227,7 +231,7 @@ class Renderer
*
* @return string the left delimiter
*/
public static function getTemplateRightDelimiter($engine = 'smarty3')
public static function getTemplateRightDelimiter(string $engine = 'smarty3'): string
{
return self::$rdelim[$engine];
}

View file

@ -70,7 +70,7 @@ class Search
return $emptyResultList;
}
$contactDetails = Contact::getByURLForUser($user_data['url'] ?? '', local_user());
$contactDetails = Contact::getByURLForUser($user_data['url'] ?? '', DI::userSession()->getLocalUserId());
$result = new ContactResult(
$user_data['name'] ?? '',
@ -136,7 +136,7 @@ class Search
foreach ($profiles as $profile) {
$profile_url = $profile['profile_url'] ?? '';
$contactDetails = Contact::getByURLForUser($profile_url, local_user());
$contactDetails = Contact::getByURLForUser($profile_url, DI::userSession()->getLocalUserId());
$result = new ContactResult(
$profile['name'] ?? '',
@ -192,7 +192,7 @@ class Search
}
// Add found profiles from the global directory to the local directory
Worker::add(PRIORITY_LOW, 'SearchDirectory', $search);
Worker::add(Worker::PRIORITY_LOW, 'SearchDirectory', $search);
return $resultList;
}
@ -211,7 +211,7 @@ class Search
{
Logger::info('Searching', ['search' => $search, 'mode' => $mode, 'page' => $page]);
if (DI::config()->get('system', 'block_public') && !Session::isAuthenticated()) {
if (DI::config()->get('system', 'block_public') && !DI::userSession()->isAuthenticated()) {
return [];
}

View file

@ -1,148 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Util\Strings;
/**
* High-level Session service class
*/
class Session
{
public static $exists = false;
public static $expire = 180000;
public static function exists($name)
{
return DI::session()->exists($name);
}
public static function get($name, $defaults = null)
{
return DI::session()->get($name, $defaults);
}
public static function pop($name, $defaults = null)
{
return DI::session()->pop($name, $defaults);
}
public static function set($name, $value)
{
DI::session()->set($name, $value);
}
public static function setMultiple(array $values)
{
DI::session()->setMultiple($values);
}
public static function remove($name)
{
DI::session()->remove($name);
}
public static function clear()
{
DI::session()->clear();
}
/**
* Return the user contact ID of a visitor for the given user ID they are visiting
*
* @param integer $uid User ID
* @return integer
*/
public static function getRemoteContactID($uid)
{
$session = DI::session();
if (!empty($session->get('remote')[$uid])) {
$remote = $session->get('remote')[$uid];
} else {
$remote = 0;
}
$local_user = !empty($session->get('authenticated')) ? $session->get('uid') : 0;
if (empty($remote) && ($local_user != $uid) && !empty($my_address = $session->get('my_address'))) {
$remote = Contact::getIdForURL($my_address, $uid, false);
}
return $remote;
}
/**
* Returns User ID for given contact ID of the visitor
*
* @param integer $cid Contact ID
* @return integer User ID for given contact ID of the visitor
*/
public static function getUserIDForVisitorContactID($cid)
{
$session = DI::session();
if (empty($session->get('remote'))) {
return false;
}
return array_search($cid, $session->get('remote'));
}
/**
* Set the session variable that contains the contact IDs for the visitor's contact URL
*
* @param string $url Contact URL
*/
public static function setVisitorsContacts()
{
$session = DI::session();
$session->set('remote', []);
$remote = [];
$remote_contacts = DBA::select('contact', ['id', 'uid'], ['nurl' => Strings::normaliseLink($session->get('my_url')), 'rel' => [Contact::FOLLOWER, Contact::FRIEND], 'self' => false]);
while ($contact = DBA::fetch($remote_contacts)) {
if (($contact['uid'] == 0) || Contact\User::isBlocked($contact['id'], $contact['uid'])) {
continue;
}
$remote[$contact['uid']] = $contact['id'];
}
DBA::close($remote_contacts);
$session->set('remote', $remote);
}
/**
* Returns if the current visitor is authenticated
*
* @return boolean "true" when visitor is either a local or remote user
*/
public static function isAuthenticated()
{
$session = DI::session();
return $session->get('authenticated', false);
}
}

View file

@ -48,7 +48,7 @@ interface IHandleSessions
* Handle the case where session_start() hasn't been called and the super global isn't available.
*
* @param string $name
* @param mixed $defaults
* @param mixed $defaults Deprecated, use `Session->get($name) ?? $defaults` instead
*
* @return mixed
*/
@ -58,7 +58,7 @@ interface IHandleSessions
* Retrieves a value from the provided key if it exists and removes it from session
*
* @param string $name
* @param mixed $defaults
* @param mixed $defaults Deprecated, use `Session->pop($name) ?? $defaults` instead
*
* @return mixed
*/

View file

@ -0,0 +1,100 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Session\Capability;
/**
* This interface handles UserSessions, which is directly extended from the global Session interface
*/
interface IHandleUserSessions extends IHandleSessions
{
/**
* Returns the user id of locally logged-in user or false.
*
* @return int|bool user id or false
*/
public function getLocalUserId();
/**
* Returns the public contact id of logged-in user or false.
*
* @return int|bool public contact id or false
*/
public function getPublicContactId();
/**
* Returns public contact id of authenticated site visitor or false
*
* @return int|bool visitor_id or false
*/
public function getRemoteUserId();
/**
* Return the user contact ID of a visitor for the given user ID they are visiting
*
* @param int $uid User ID
*
* @return int
*/
public function getRemoteContactID(int $uid): int;
/**
* Returns User ID for given contact ID of the visitor
*
* @param int $cid Contact ID
*
* @return int User ID for given contact ID of the visitor
*/
public function getUserIDForVisitorContactID(int $cid): int;
/**
* Returns the account URL of the currently logged in user
*
* @return string
*/
public function getMyUrl(): string;
/**
* Returns if the current visitor is authenticated
*
* @return bool "true" when visitor is either a local or remote user
*/
public function isAuthenticated(): bool;
/**
* Returns User ID of the managed user in case it's a different identity
*
* @return int|bool uid of the manager or false
*/
public function getSubManagedUserId();
/**
* Sets the User ID of the managed user in case it's a different identity
*
* @param int $managed_uid The user id of the managing user
*/
public function setSubManagedUserId(int $managed_uid): void;
/**
* Set the session variable that contains the contact IDs for the visitor's contact URL
*/
public function setVisitorsContacts();
}

View file

@ -55,10 +55,8 @@ class Session
* @param LoggerInterface $logger
* @param Profiler $profiler
* @param array $server
*
* @return IHandleSessions
*/
public function createSession(App\Mode $mode, App\BaseURL $baseURL, IManageConfigValues $config, Database $dba, Cache $cacheFactory, LoggerInterface $logger, Profiler $profiler, array $server = [])
public function createSession(App\Mode $mode, App\BaseURL $baseURL, IManageConfigValues $config, Database $dba, Cache $cacheFactory, LoggerInterface $logger, Profiler $profiler, array $server = []): IHandleSessions
{
$profiler->startRecording('session');
$session = null;

View file

@ -0,0 +1,28 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Session\Handler;
abstract class AbstractSessionHandler implements \SessionHandlerInterface
{
/** @var int Duration of the Session */
public const EXPIRE = 180000;
}

View file

@ -23,14 +23,12 @@ namespace Friendica\Core\Session\Handler;
use Friendica\Core\Cache\Capability\ICanCache;
use Friendica\Core\Cache\Exception\CachePersistenceException;
use Friendica\Core\Session;
use Psr\Log\LoggerInterface;
use SessionHandlerInterface;
/**
* SessionHandler using Friendica Cache
*/
class Cache implements SessionHandlerInterface
class Cache extends AbstractSessionHandler
{
/** @var ICanCache */
private $cache;
@ -57,11 +55,10 @@ class Cache implements SessionHandlerInterface
try {
$data = $this->cache->get('session:' . $id);
if (!empty($data)) {
Session::$exists = true;
return $data;
}
} catch (CachePersistenceException $exception) {
$this->logger->warning('Cannot read session.'. ['id' => $id, 'exception' => $exception]);
$this->logger->warning('Cannot read session.', ['id' => $id, 'exception' => $exception]);
return '';
}
@ -91,7 +88,7 @@ class Cache implements SessionHandlerInterface
}
try {
return $this->cache->set('session:' . $id, $data, Session::$expire);
return $this->cache->set('session:' . $id, $data, static::EXPIRE);
} catch (CachePersistenceException $exception) {
$this->logger->warning('Cannot write session', ['id' => $id, 'exception' => $exception]);
return false;

View file

@ -21,15 +21,13 @@
namespace Friendica\Core\Session\Handler;
use Friendica\Core\Session;
use Friendica\Database\Database as DBA;
use Psr\Log\LoggerInterface;
use SessionHandlerInterface;
/**
* SessionHandler using database
*/
class Database implements SessionHandlerInterface
class Database extends AbstractSessionHandler
{
/** @var DBA */
private $dba;
@ -37,6 +35,8 @@ class Database implements SessionHandlerInterface
private $logger;
/** @var array The $_SERVER variable */
private $server;
/** @var bool global check, if the current Session exists */
private $sessionExists = false;
/**
* DatabaseSessionHandler constructor.
@ -57,6 +57,7 @@ class Database implements SessionHandlerInterface
return true;
}
#[\ReturnTypeWillChange]
public function read($id)
{
if (empty($id)) {
@ -66,11 +67,11 @@ class Database implements SessionHandlerInterface
try {
$session = $this->dba->selectFirst('session', ['data'], ['sid' => $id]);
if ($this->dba->isResult($session)) {
Session::$exists = true;
$this->sessionExists = true;
return $session['data'];
}
} catch (\Exception $exception) {
$this->logger->warning('Cannot read session.'. ['id' => $id, 'exception' => $exception]);
$this->logger->warning('Cannot read session.', ['id' => $id, 'exception' => $exception]);
return '';
}
@ -101,11 +102,11 @@ class Database implements SessionHandlerInterface
return $this->destroy($id);
}
$expire = time() + Session::$expire;
$expire = time() + static::EXPIRE;
$default_expire = time() + 300;
try {
if (Session::$exists) {
if ($this->sessionExists) {
$fields = ['data' => $data, 'expire' => $expire];
$condition = ["`sid` = ? AND (`data` != ? OR `expire` != ?)", $id, $data, $expire];
$this->dba->update('session', $fields, $condition);
@ -114,7 +115,7 @@ class Database implements SessionHandlerInterface
$this->dba->insert('session', $fields);
}
} catch (\Exception $exception) {
$this->logger->warning('Cannot write session.'. ['id' => $id, 'exception' => $exception]);
$this->logger->warning('Cannot write session.', ['id' => $id, 'exception' => $exception]);
return false;
}
@ -131,17 +132,18 @@ class Database implements SessionHandlerInterface
try {
return $this->dba->delete('session', ['sid' => $id]);
} catch (\Exception $exception) {
$this->logger->warning('Cannot destroy session.'. ['id' => $id, 'exception' => $exception]);
$this->logger->warning('Cannot destroy session.', ['id' => $id, 'exception' => $exception]);
return false;
}
}
#[\ReturnTypeWillChange]
public function gc($max_lifetime): bool
{
try {
return $this->dba->delete('session', ["`expire` < ?", time()]);
} catch (\Exception $exception) {
$this->logger->warning('Cannot use garbage collector.'. ['exception' => $exception]);
$this->logger->warning('Cannot use garbage collector.', ['exception' => $exception]);
return false;
}
}

View file

@ -0,0 +1,190 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Session\Model;
use Friendica\Core\Session\Capability\IHandleSessions;
use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Model\Contact;
/**
* This class handles user sessions, which is directly extended from regular session
*/
class UserSession implements IHandleUserSessions
{
/** @var IHandleSessions */
private $session;
/** @var int|bool saves the public Contact ID for later usage */
protected $publicContactId = false;
public function __construct(IHandleSessions $session)
{
$this->session = $session;
}
/** {@inheritDoc} */
public function getLocalUserId()
{
if (!empty($this->session->get('authenticated')) && !empty($this->session->get('uid'))) {
return intval($this->session->get('uid'));
}
return false;
}
/** {@inheritDoc} */
public function getPublicContactId()
{
if (empty($this->publicContactId) && !empty($this->session->get('authenticated'))) {
if (!empty($this->session->get('my_address'))) {
// Local user
$this->publicContactId = Contact::getIdForURL($this->session->get('my_address'), 0, false);
} elseif (!empty($this->session->get('visitor_home'))) {
// Remote user
$this->publicContactId = Contact::getIdForURL($this->session->get('visitor_home'), 0, false);
}
} elseif (empty($this->session->get('authenticated'))) {
$this->publicContactId = false;
}
return $this->publicContactId;
}
/** {@inheritDoc} */
public function getRemoteUserId()
{
if (empty($this->session->get('authenticated'))) {
return false;
}
if (!empty($this->session->get('visitor_id'))) {
return (int)$this->session->get('visitor_id');
}
return false;
}
/** {@inheritDoc} */
public function getRemoteContactID(int $uid): int
{
if (!empty($this->session->get('remote')[$uid])) {
$remote = $this->session->get('remote')[$uid];
} else {
$remote = 0;
}
$local_user = !empty($this->session->get('authenticated')) ? $this->session->get('uid') : 0;
if (empty($remote) && ($local_user != $uid) && !empty($my_address = $this->session->get('my_address'))) {
$remote = Contact::getIdForURL($my_address, $uid, false);
}
return $remote;
}
/** {@inheritDoc} */
public function getUserIDForVisitorContactID(int $cid): int
{
if (empty($this->session->get('remote'))) {
return false;
}
return array_search($cid, $this->session->get('remote'));
}
/** {@inheritDoc} */
public function getMyUrl(): string
{
return $this->session->get('my_url', '');
}
/** {@inheritDoc} */
public function isAuthenticated(): bool
{
return $this->session->get('authenticated', false);
}
/** {@inheritDoc} */
public function setVisitorsContacts()
{
$this->session->set('remote', Contact::getVisitorByUrl($this->session->get('my_url')));
}
/** {@inheritDoc} */
public function getSubManagedUserId()
{
return $this->session->get('submanage') ?? false;
}
/** {@inheritDoc} */
public function setSubManagedUserId(int $managed_uid): void
{
$this->session->set('submanage', $managed_uid);
}
/** {@inheritDoc} */
public function start(): IHandleSessions
{
return $this;
}
/** {@inheritDoc} */
public function exists(string $name): bool
{
return $this->session->exists($name);
}
/** {@inheritDoc} */
public function get(string $name, $defaults = null)
{
return $this->session->get($name, $defaults);
}
/** {@inheritDoc} */
public function pop(string $name, $defaults = null)
{
return $this->session->pop($name, $defaults);
}
/** {@inheritDoc} */
public function set(string $name, $value)
{
$this->session->set($name, $value);
}
/** {@inheritDoc} */
public function setMultiple(array $values)
{
$this->session->setMultiple($values);
}
/** {@inheritDoc} */
public function remove(string $name)
{
$this->session->remove($name);
}
/** {@inheritDoc} */
public function clear()
{
$this->session->clear();
}
}

View file

@ -0,0 +1,81 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core\Session\Type;
use Friendica\Core\Session\Capability\IHandleSessions;
class ArraySession implements IHandleSessions
{
/** @var array */
protected $data = [];
public function __construct(array $data = [])
{
$this->data = $data;
}
public function start(): IHandleSessions
{
return $this;
}
public function exists(string $name): bool
{
return !empty($this->data[$name]);
}
public function get(string $name, $defaults = null)
{
return $this->data[$name] ?? $defaults;
}
public function pop(string $name, $defaults = null)
{
$value = $defaults;
if ($this->exists($name)) {
$value = $this->get($name);
$this->remove($name);
}
return $value;
}
public function set(string $name, $value)
{
$this->data[$name] = $value;
}
public function setMultiple(array $values)
{
$this->data = array_merge($values, $this->data);
}
public function remove(string $name)
{
unset($this->data[$name]);
}
public function clear()
{
$this->data = [];
}
}

View file

@ -21,6 +21,8 @@
namespace Friendica\Core;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\DI;
use Friendica\Module\Response;
@ -438,14 +440,18 @@ class System
/**
* Fetch the load and number of processes
*
* @param bool $get_processes
* @return array
*/
public static function getLoadAvg(): array
public static function getLoadAvg(bool $get_processes = true): array
{
$content = @file_get_contents('/proc/loadavg');
if (empty($content)) {
$content = shell_exec('cat /proc/loadavg');
if ($get_processes && @is_readable('/proc/loadavg')) {
$content = @file_get_contents('/proc/loadavg');
if (empty($content)) {
$content = shell_exec('uptime | sed "s/.*averages*: //" | sed "s/,//g"');
}
}
if (empty($content) || !preg_match("#([.\d]+)\s([.\d]+)\s([.\d]+)\s(\d+)/(\d+)#", $content, $matches)) {
$load_arr = sys_getloadavg();
if (empty($load_arr)) {
@ -656,4 +662,30 @@ class System
// Reaching this point means that the operating system is configured badly.
return "";
}
/**
* Fetch the system rules
*
* @return array
*/
public static function getRules(): array
{
$rules = [];
$id = 0;
if (DI::config()->get('system', 'tosdisplay')) {
$rulelist = DI::config()->get('system', 'tosrules') ?: DI::config()->get('system', 'tostext');
$html = BBCode::convert($rulelist, false, BBCode::EXTERNAL);
$msg = HTML::toPlaintext($html, 0, true);
foreach (explode("\n", $msg) as $line) {
$line = trim($line);
if ($line) {
$rules[] = ['id' => (string)++$id, 'text' => $line];
}
}
}
return $rules;
}
}

View file

@ -25,8 +25,6 @@ use Friendica\DI;
use Friendica\Model\Profile;
use Friendica\Util\Strings;
require_once 'boot.php';
/**
* Some functions to handle themes
*/

View file

@ -26,6 +26,7 @@ use Friendica\App\Mode;
use Friendica\Database\DBA;
use Friendica\Database\DBStructure;
use Friendica\DI;
use Friendica\Model\User;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings;
@ -35,6 +36,8 @@ class Update
const SUCCESS = 0;
const FAILED = 1;
const NEW_TABLE_STRUCTURE_VERSION = 1288;
/**
* Function to check if the Database structure needs an update.
*
@ -63,7 +66,7 @@ class Update
}
// We don't support upgrading from very old versions anymore
if ($build < NEW_TABLE_STRUCTURE_VERSION) {
if ($build < self::NEW_TABLE_STRUCTURE_VERSION) {
$error = DI::l10n()->t('Updates from version %s are not supported. Please update at least to version 2021.01 and wait until the postupdate finished version 1383.', $build);
if (DI::mode()->getExecutor() == Mode::INDEX) {
die($error);
@ -73,8 +76,8 @@ class Update
}
// The postupdate has to completed version 1288 for the new post views to take over
$postupdate = DI::config()->get('system', 'post_update_version', NEW_TABLE_STRUCTURE_VERSION);
if ($postupdate < NEW_TABLE_STRUCTURE_VERSION) {
$postupdate = DI::config()->get('system', 'post_update_version', self::NEW_TABLE_STRUCTURE_VERSION);
if ($postupdate < self::NEW_TABLE_STRUCTURE_VERSION) {
$error = DI::l10n()->t('Updates from postupdate version %s are not supported. Please update at least to version 2021.01 and wait until the postupdate finished version 1383.', $postupdate);
if (DI::mode()->getExecutor() == Mode::INDEX) {
die($error);
@ -92,7 +95,7 @@ class Update
*/
self::run($basePath);
} else {
Worker::add(PRIORITY_CRITICAL, 'DBUpdate');
Worker::add(Worker::PRIORITY_CRITICAL, 'DBUpdate');
}
}
}
@ -146,7 +149,7 @@ class Update
}
DI::config()->set('system', 'maintenance', 1);
// run the pre_update_nnnn functions in update.php
for ($version = $stored + 1; $version <= $current; $version++) {
Logger::notice('Execute pre update.', ['version' => $version]);
@ -287,30 +290,16 @@ class Update
* @return void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function updateFailed(int $update_id, string $error_message) {
//send the administrators an e-mail
$condition = ['email' => explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0];
$adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]);
// No valid result?
if (!DBA::isResult($adminlist)) {
private static function updateFailed(int $update_id, string $error_message)
{
$adminEmails = User::getAdminListForEmailing(['uid', 'language', 'email']);
if (!$adminEmails) {
Logger::warning('Cannot notify administrators .', ['update' => $update_id, 'message' => $error_message]);
// Don't continue
return;
}
$sent = [];
// every admin could had different language
while ($admin = DBA::fetch($adminlist)) {
if (in_array($admin['email'], $sent)) {
continue;
}
$sent[] = $admin['email'];
$lang = $admin['language'] ?? 'en';
$l10n = DI::l10n()->withLang($lang);
foreach($adminEmails as $admin) {
$l10n = DI::l10n()->withLang($admin['language'] ?: 'en');
$preamble = Strings::deindent($l10n->t("
The friendica developers released update %s recently,
@ -341,35 +330,20 @@ class Update
*/
private static function updateSuccessful(int $from_build, int $to_build)
{
//send the administrators an e-mail
$condition = ['email' => explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0];
$adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]);
foreach(User::getAdminListForEmailing(['uid', 'language', 'email']) as $admin) {
$l10n = DI::l10n()->withLang($admin['language'] ?: 'en');
if (DBA::isResult($adminlist)) {
$sent = [];
$preamble = Strings::deindent($l10n->t('
The friendica database was successfully updated from %s to %s.',
$from_build, $to_build));
// every admin could had different language
while ($admin = DBA::fetch($adminlist)) {
if (in_array($admin['email'], $sent)) {
continue;
}
$sent[] = $admin['email'];
$lang = (($admin['language']) ? $admin['language'] : 'en');
$l10n = DI::l10n()->withLang($lang);
$preamble = Strings::deindent($l10n->t('
The friendica database was successfully updated from %s to %s.',
$from_build, $to_build));
$email = DI::emailer()
->newSystemMail()
->withMessage($l10n->t('[Friendica Notify] Database update'), $preamble)
->forUser($admin)
->withRecipient($admin['email'])
->build();
DI::emailer()->send($email);
}
$email = DI::emailer()
->newSystemMail()
->withMessage($l10n->t('[Friendica Notify] Database update'), $preamble)
->forUser($admin)
->withRecipient($admin['email'])
->build();
DI::emailer()->send($email);
}
Logger::debug('Database structure update successful.');

View file

@ -1,330 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Core;
use Friendica\Database\DBA;
use Friendica\Database\DBStructure;
use Friendica\DI;
use Friendica\Model\Photo;
use Friendica\Model\Profile;
use Friendica\Object\Image;
use Friendica\Security\PermissionSet\Repository\PermissionSet;
use Friendica\Util\Strings;
use Friendica\Worker\Delivery;
/**
* UserImport class
*/
class UserImport
{
const IMPORT_DEBUG = false;
private static function lastInsertId()
{
if (self::IMPORT_DEBUG) {
return 1;
}
return DBA::lastInsertId();
}
/**
* Remove columns from array $arr that aren't in table $table
*
* @param string $table Table name
* @param array &$arr Column=>Value array from json (by ref)
* @throws \Exception
*/
private static function checkCols($table, &$arr)
{
$tableColumns = DBStructure::getColumns($table);
$tcols = [];
$ttype = [];
// get a plain array of column names
foreach ($tableColumns as $tcol) {
$tcols[] = $tcol['Field'];
$ttype[$tcol['Field']] = $tcol['Type'];
}
// remove inexistent columns
foreach ($arr as $icol => $ival) {
if (!in_array($icol, $tcols)) {
unset($arr[$icol]);
continue;
}
if ($ttype[$icol] === 'datetime') {
$arr[$icol] = $ival ?? DBA::NULL_DATETIME;
}
}
}
/**
* Import data into table $table
*
* @param string $table Table name
* @param array $arr Column=>Value array from json
* @return array|bool
* @throws \Exception
*/
private static function dbImportAssoc(string $table, array $arr)
{
if (isset($arr['id'])) {
unset($arr['id']);
}
self::checkCols($table, $arr);
if (self::IMPORT_DEBUG) {
return true;
}
return DBA::insert($table, $arr);
}
/**
* Import account file exported from mod/uexport
*
* @param array $file array from $_FILES
* @return void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function importAccount(array $file)
{
Logger::notice("Start user import from " . $file['tmp_name']);
/*
STEPS
1. checks
2. replace old baseurl with new baseurl
3. import data (look at user id and contacts id)
4. archive non-dfrn contacts
5. send message to dfrn contacts
*/
$account = json_decode(file_get_contents($file['tmp_name']), true);
if ($account === null) {
notice(DI::l10n()->t("Error decoding account file"));
return;
}
if (empty($account['version'])) {
notice(DI::l10n()->t("Error! No version data in file! This is not a Friendica account file?"));
return;
}
// check for username
// check if username matches deleted account
if (DBA::exists('user', ['nickname' => $account['user']['nickname']])
|| DBA::exists('userd', ['username' => $account['user']['nickname']])) {
notice(DI::l10n()->t("User '%s' already exists on this server!", $account['user']['nickname']));
return;
}
$oldbaseurl = $account['baseurl'];
$newbaseurl = DI::baseUrl();
$oldaddr = str_replace('http://', '@', Strings::normaliseLink($oldbaseurl));
$newaddr = str_replace('http://', '@', Strings::normaliseLink($newbaseurl));
if (!empty($account['profile']['addr'])) {
$old_handle = $account['profile']['addr'];
} else {
$old_handle = $account['user']['nickname'].$oldaddr;
}
// Creating a new guid to avoid problems with Diaspora
$account['user']['guid'] = System::createUUID();
$olduid = $account['user']['uid'];
unset($account['user']['uid']);
unset($account['user']['account_expired']);
unset($account['user']['account_expires_on']);
unset($account['user']['expire_notification_sent']);
$callback = function (&$value) use ($oldbaseurl, $oldaddr, $newbaseurl, $newaddr) {
$value = str_replace([$oldbaseurl, $oldaddr], [$newbaseurl, $newaddr], $value);
};
array_walk($account['user'], $callback);
// import user
$r = self::dbImportAssoc('user', $account['user']);
if ($r === false) {
Logger::warning("uimport:insert user : ERROR : " . DBA::errorMessage());
notice(DI::l10n()->t("User creation error"));
return;
}
$newuid = self::lastInsertId();
DI::pConfig()->set($newuid, 'system', 'previous_addr', $old_handle);
$errorcount = 0;
foreach ($account['contact'] as &$contact) {
if ($contact['uid'] == $olduid && $contact['self'] == '1') {
foreach ($contact as $k => &$v) {
$v = str_replace([$oldbaseurl, $oldaddr], [$newbaseurl, $newaddr], $v);
foreach (["profile", "avatar", "micro"] as $k) {
$v = str_replace($oldbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
}
}
}
if ($contact['uid'] == $olduid && $contact['self'] == '0') {
// set contacts 'avatar-date' to NULL_DATE to let worker to update urls
$contact["avatar-date"] = DBA::NULL_DATETIME;
switch ($contact['network']) {
case Protocol::DFRN:
case Protocol::DIASPORA:
// send relocate message (below)
break;
case Protocol::FEED:
case Protocol::MAIL:
// Nothing to do
break;
default:
// archive other contacts
$contact['archive'] = "1";
}
}
$contact['uid'] = $newuid;
$r = self::dbImportAssoc('contact', $contact);
if ($r === false) {
Logger::warning("uimport:insert contact " . $contact['nick'] . "," . $contact['network'] . " : ERROR : " . DBA::errorMessage());
$errorcount++;
} else {
$contact['newid'] = self::lastInsertId();
}
}
if ($errorcount > 0) {
notice(DI::l10n()->tt("%d contact not imported", "%d contacts not imported", $errorcount));
}
foreach ($account['group'] as &$group) {
$group['uid'] = $newuid;
$r = self::dbImportAssoc('group', $group);
if ($r === false) {
Logger::warning("uimport:insert group " . $group['name'] . " : ERROR : " . DBA::errorMessage());
} else {
$group['newid'] = self::lastInsertId();
}
}
foreach ($account['group_member'] as &$group_member) {
$import = 0;
foreach ($account['group'] as $group) {
if ($group['id'] == $group_member['gid'] && isset($group['newid'])) {
$group_member['gid'] = $group['newid'];
$import++;
break;
}
}
foreach ($account['contact'] as $contact) {
if ($contact['id'] == $group_member['contact-id'] && isset($contact['newid'])) {
$group_member['contact-id'] = $contact['newid'];
$import++;
break;
}
}
if ($import == 2) {
$r = self::dbImportAssoc('group_member', $group_member);
if ($r === false) {
Logger::warning("uimport:insert group member " . $group_member['id'] . " : ERROR : " . DBA::errorMessage());
}
}
}
foreach ($account['profile'] as &$profile) {
unset($profile['id']);
$profile['uid'] = $newuid;
foreach ($profile as $k => &$v) {
$v = str_replace([$oldbaseurl, $oldaddr], [$newbaseurl, $newaddr], $v);
foreach (["profile", "avatar"] as $k) {
$v = str_replace($oldbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
}
}
if (count($account['profile']) === 1 || $profile['is-default']) {
$r = self::dbImportAssoc('profile', $profile);
if ($r === false) {
Logger::warning("uimport:insert profile: ERROR : " . DBA::errorMessage());
notice(DI::l10n()->t("User profile creation error"));
DBA::delete('user', ['uid' => $newuid]);
DBA::delete('profile_field', ['uid' => $newuid]);
return;
}
$profile['id'] = DBA::lastInsertId();
}
Profile::migrate($profile);
}
$permissionSet = DI::permissionSet()->selectDefaultForUser($newuid);
foreach ($account['profile_fields'] ?? [] as $profile_field) {
$profile_field['uid'] = $newuid;
///@TODO Replace with permissionset import
$profile_field['psid'] = $profile_field['psid'] ? $permissionSet->uid : PermissionSet::PUBLIC;
if (self::dbImportAssoc('profile_field', $profile_field) === false) {
Logger::info("uimport:insert profile field " . $profile_field['id'] . " : ERROR : " . DBA::errorMessage());
}
}
foreach ($account['photo'] as &$photo) {
$photo['uid'] = $newuid;
$photo['data'] = hex2bin($photo['data']);
$Image = new Image($photo['data'], $photo['type']);
$r = Photo::store(
$Image,
$photo['uid'], $photo['contact-id'], //0
$photo['resource-id'], $photo['filename'], $photo['album'], $photo['scale'], $photo['profile'], //1
$photo['allow_cid'], $photo['allow_gid'], $photo['deny_cid'], $photo['deny_gid']
);
if ($r === false) {
Logger::warning("uimport:insert photo " . $photo['resource-id'] . "," . $photo['scale'] . " : ERROR : " . DBA::errorMessage());
}
}
foreach ($account['pconfig'] as &$pconfig) {
$pconfig['uid'] = $newuid;
$r = self::dbImportAssoc('pconfig', $pconfig);
if ($r === false) {
Logger::warning("uimport:insert pconfig " . $pconfig['id'] . " : ERROR : " . DBA::errorMessage());
}
}
// send relocate messages
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, $newuid);
info(DI::l10n()->t("Done. You can now login with your username and password"));
DI::baseUrl()->redirect('login');
}
}

View file

@ -31,12 +31,20 @@ use Friendica\Util\DateTimeFormat;
*/
class Worker
{
const PRIORITY_UNDEFINED = PRIORITY_UNDEFINED;
const PRIORITY_CRITICAL = PRIORITY_CRITICAL;
const PRIORITY_HIGH = PRIORITY_HIGH;
const PRIORITY_MEDIUM = PRIORITY_MEDIUM;
const PRIORITY_LOW = PRIORITY_LOW;
const PRIORITY_NEGLIGIBLE = PRIORITY_NEGLIGIBLE;
/**
* @name Priority
*
* Process priority for the worker
* @{
*/
const PRIORITY_UNDEFINED = 0;
const PRIORITY_CRITICAL = 10;
const PRIORITY_HIGH = 20;
const PRIORITY_MEDIUM = 30;
const PRIORITY_LOW = 40;
const PRIORITY_NEGLIGIBLE = 50;
const PRIORITIES = [self::PRIORITY_CRITICAL, self::PRIORITY_HIGH, self::PRIORITY_MEDIUM, self::PRIORITY_LOW, self::PRIORITY_NEGLIGIBLE];
/* @}*/
const STATE_STARTUP = 1; // Worker is in startup. This takes most time.
const STATE_LONG_LOOP = 2; // Worker is processing the whole - long - loop.
@ -307,17 +315,7 @@ class Worker
return false;
}
$valid = false;
if (strpos($file, 'include/') === 0) {
$valid = true;
}
if (strpos($file, 'addon/') === 0) {
$valid = true;
}
// Simply return flag
return $valid;
return (strpos($file, 'addon/') === 0);
}
/**
@ -398,11 +396,6 @@ class Worker
return true;
}
// The script could be provided as full path or only with the function name
if ($include == basename($include)) {
$include = 'include/' . $include . '.php';
}
if (!self::validateInclude($include)) {
Logger::warning('Include file is not valid', ['file' => $argv[0]]);
$stamp = (float)microtime(true);
@ -461,11 +454,15 @@ class Worker
$load_cooldown = DI::config()->get('system', 'worker_load_cooldown');
$processes_cooldown = DI::config()->get('system', 'worker_processes_cooldown');
if ($load_cooldown == 0) {
$load_cooldown = DI::config()->get('system', 'maxloadavg');
}
if (($load_cooldown == 0) && ($processes_cooldown == 0)) {
return false;
}
$load = System::getLoadAvg();
$load = System::getLoadAvg($processes_cooldown != 0);
if (empty($load)) {
return false;
}
@ -501,13 +498,17 @@ class Worker
$load_cooldown = DI::config()->get('system', 'worker_load_cooldown');
$processes_cooldown = DI::config()->get('system', 'worker_processes_cooldown');
if ($load_cooldown == 0) {
$load_cooldown = DI::config()->get('system', 'maxloadavg');
}
if (($load_cooldown == 0) && ($processes_cooldown == 0)) {
return;
}
$sleeping = false;
while ($load = System::getLoadAvg()) {
while ($load = System::getLoadAvg($processes_cooldown != 0)) {
if (($load_cooldown > 0) && ($load['average1'] > $load_cooldown)) {
if (!$sleeping) {
Logger::notice('Load induced pre execution cooldown.', ['max' => $load_cooldown, 'load' => $load, 'called-by' => System::callstack(1)]);
@ -567,7 +568,15 @@ class Worker
// Set the workerLogger as new default logger
if ($method_call) {
call_user_func_array(sprintf('Friendica\Worker\%s::execute', $funcname), $argv);
try {
call_user_func_array(sprintf('Friendica\Worker\%s::execute', $funcname), $argv);
} catch (\TypeError $e) {
// No need to defer a worker queue entry if the arguments are invalid
Logger::notice('Wrong worker arguments', ['class' => $funcname, 'argv' => $argv, 'queue' => $queue, 'message' => $e->getMessage()]);
} catch (\Throwable $e) {
Logger::error('Uncaught exception in worker execution', ['class' => get_class($e), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine(), 'trace' => $e->getTraceAsString()]);
Worker::defer();
}
} else {
$funcname($argv, count($argv));
}
@ -799,7 +808,7 @@ class Worker
$top_priority = self::highestPriority();
$high_running = self::processWithPriorityActive($top_priority);
if (!$high_running && ($top_priority > PRIORITY_UNDEFINED) && ($top_priority < PRIORITY_NEGLIGIBLE)) {
if (!$high_running && ($top_priority > self::PRIORITY_UNDEFINED) && ($top_priority < self::PRIORITY_NEGLIGIBLE)) {
Logger::info('Jobs with a higher priority are waiting but none is executed. Open a fastlane.', ['priority' => $top_priority]);
$queues = $active + 1;
}
@ -931,7 +940,7 @@ class Worker
private static function nextPriority()
{
$waiting = [];
$priorities = [PRIORITY_CRITICAL, PRIORITY_HIGH, PRIORITY_MEDIUM, PRIORITY_LOW, PRIORITY_NEGLIGIBLE];
$priorities = [self::PRIORITY_CRITICAL, self::PRIORITY_HIGH, self::PRIORITY_MEDIUM, self::PRIORITY_LOW, self::PRIORITY_NEGLIGIBLE];
foreach ($priorities as $priority) {
$stamp = (float)microtime(true);
if (DBA::exists('workerqueue', ["`priority` = ? AND `pid` = 0 AND NOT `done` AND `next_try` < ?", $priority, DateTimeFormat::utcNow()])) {
@ -940,8 +949,8 @@ class Worker
self::$db_duration += (microtime(true) - $stamp);
}
if (!empty($waiting[PRIORITY_CRITICAL])) {
return PRIORITY_CRITICAL;
if (!empty($waiting[self::PRIORITY_CRITICAL])) {
return self::PRIORITY_CRITICAL;
}
$running = [];
@ -1198,8 +1207,8 @@ class Worker
* @param (integer|array) priority or parameter array, strings are deprecated and are ignored
*
* next args are passed as $cmd command line
* or: Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::DELETION, $drop_id);
* or: Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'Delivery', $post_id);
* or: Worker::add(Worker::PRIORITY_HIGH, 'Notifier', Delivery::DELETION, $drop_id);
* or: Worker::add(array('priority' => Worker::PRIORITY_HIGH, 'dont_fork' => true), 'Delivery', $post_id);
*
* @return int '0' if worker queue entry already existed or there had been an error, otherwise the ID of the worker task
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
@ -1222,7 +1231,7 @@ class Worker
return 1;
}
$priority = PRIORITY_MEDIUM;
$priority = self::PRIORITY_MEDIUM;
// Don't fork from frontend tasks by default
$dont_fork = DI::config()->get('system', 'worker_dont_fork', false) || !DI::mode()->isBackend();
$created = DateTimeFormat::utcNow();
@ -1258,9 +1267,9 @@ class Worker
$found = DBA::exists('workerqueue', ['command' => $command, 'parameter' => $parameters, 'done' => false]);
$added = 0;
if (!is_int($priority) || !in_array($priority, PRIORITIES)) {
if (!is_int($priority) || !in_array($priority, self::PRIORITIES)) {
Logger::warning('Invalid priority', ['priority' => $priority, 'command' => $command, 'callstack' => System::callstack(20)]);
$priority = PRIORITY_MEDIUM;
$priority = self::PRIORITY_MEDIUM;
}
// Quit if there was a database error - a precaution for the update process to 3.5.3
@ -1375,12 +1384,12 @@ class Worker
$delay = (($new_retrial + 2) ** 4) + (rand(1, 30) * ($new_retrial));
$next = DateTimeFormat::utc('now + ' . $delay . ' seconds');
if (($priority < PRIORITY_MEDIUM) && ($new_retrial > 3)) {
$priority = PRIORITY_MEDIUM;
} elseif (($priority < PRIORITY_LOW) && ($new_retrial > 6)) {
$priority = PRIORITY_LOW;
} elseif (($priority < PRIORITY_NEGLIGIBLE) && ($new_retrial > 8)) {
$priority = PRIORITY_NEGLIGIBLE;
if (($priority < self::PRIORITY_MEDIUM) && ($new_retrial > 3)) {
$priority = self::PRIORITY_MEDIUM;
} elseif (($priority < self::PRIORITY_LOW) && ($new_retrial > 6)) {
$priority = self::PRIORITY_LOW;
} elseif (($priority < self::PRIORITY_NEGLIGIBLE) && ($new_retrial > 8)) {
$priority = self::PRIORITY_NEGLIGIBLE;
}
Logger::info('Deferred task', ['id' => $id, 'retrial' => $new_retrial, 'created' => $queue['created'], 'next_execution' => $next, 'old_prio' => $queue['priority'], 'new_prio' => $priority]);

View file

@ -47,10 +47,10 @@ class Cron
Logger::info('Add cron entries');
// Check for spooled items
Worker::add(['priority' => PRIORITY_HIGH, 'force_priority' => true], 'SpoolPost');
Worker::add(['priority' => Worker::PRIORITY_HIGH, 'force_priority' => true], 'SpoolPost');
// Run the cron job that calls all other jobs
Worker::add(['priority' => PRIORITY_MEDIUM, 'force_priority' => true], 'Cron');
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'Cron');
// Cleaning dead processes
self::killStaleWorkers();
@ -112,12 +112,12 @@ class Cron
// To avoid a blocking situation we reschedule the process at the beginning of the queue.
// Additionally we are lowering the priority. (But not PRIORITY_CRITICAL)
$new_priority = $entry['priority'];
if ($entry['priority'] == PRIORITY_HIGH) {
$new_priority = PRIORITY_MEDIUM;
} elseif ($entry['priority'] == PRIORITY_MEDIUM) {
$new_priority = PRIORITY_LOW;
} elseif ($entry['priority'] != PRIORITY_CRITICAL) {
$new_priority = PRIORITY_NEGLIGIBLE;
if ($entry['priority'] == Worker::PRIORITY_HIGH) {
$new_priority = Worker::PRIORITY_MEDIUM;
} elseif ($entry['priority'] == Worker::PRIORITY_MEDIUM) {
$new_priority = Worker::PRIORITY_LOW;
} elseif ($entry['priority'] != Worker::PRIORITY_CRITICAL) {
$new_priority = Worker::PRIORITY_NEGLIGIBLE;
}
DBA::update('workerqueue', ['executed' => DBA::NULL_DATETIME, 'created' => DateTimeFormat::utcNow(), 'priority' => $new_priority, 'pid' => 0], ['id' => $entry["id"]]
);
@ -171,19 +171,26 @@ class Cron
Logger::info('Directly deliver inbox', ['inbox' => $delivery['inbox'], 'result' => $result['success']]);
continue;
} elseif ($delivery['failed'] < 3) {
$priority = PRIORITY_HIGH;
$priority = Worker::PRIORITY_HIGH;
} elseif ($delivery['failed'] < 6) {
$priority = PRIORITY_MEDIUM;
$priority = Worker::PRIORITY_MEDIUM;
} elseif ($delivery['failed'] < 8) {
$priority = PRIORITY_LOW;
$priority = Worker::PRIORITY_LOW;
} else {
$priority = PRIORITY_NEGLIGIBLE;
$priority = Worker::PRIORITY_NEGLIGIBLE;
}
if (Worker::add(['priority' => $priority, 'force_priority' => true], 'APDelivery', '', 0, $delivery['inbox'], 0)) {
Logger::info('Missing APDelivery worker added for inbox', ['inbox' => $delivery['inbox'], 'failed' => $delivery['failed'], 'priority' => $priority]);
}
}
// Optimizing this table only last seconds
if (DI::config()->get('system', 'optimize_tables')) {
Logger::info('Optimize start');
DBA::e("OPTIMIZE TABLE `post-delivery`");
Logger::info('Optimize end');
}
}
/**