mirror of
https://git.sekbaer.de/Friendica/friendica.git
synced 2025-06-12 01:54:26 +02:00
Merge remote-tracking branch 'origin/2022.12-rc' into fixes
This commit is contained in:
commit
2f3f41ed9c
714 changed files with 34811 additions and 27839 deletions
|
@ -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, [
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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 [];
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
|
100
src/Core/Session/Capability/IHandleUserSessions.php
Normal file
100
src/Core/Session/Capability/IHandleUserSessions.php
Normal 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();
|
||||
}
|
|
@ -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;
|
||||
|
|
28
src/Core/Session/Handler/AbstractSessionHandler.php
Normal file
28
src/Core/Session/Handler/AbstractSessionHandler.php
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
190
src/Core/Session/Model/UserSession.php
Normal file
190
src/Core/Session/Model/UserSession.php
Normal 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();
|
||||
}
|
||||
}
|
81
src/Core/Session/Type/ArraySession.php
Normal file
81
src/Core/Session/Type/ArraySession.php
Normal 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 = [];
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ use Friendica\DI;
|
|||
use Friendica\Model\Profile;
|
||||
use Friendica\Util\Strings;
|
||||
|
||||
require_once 'boot.php';
|
||||
|
||||
/**
|
||||
* Some functions to handle themes
|
||||
*/
|
||||
|
|
|
@ -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.');
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
|
@ -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]);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue