diff --git a/.editorconfig b/.editorconfig
index 8565b274..ef6e90b2 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -27,3 +27,6 @@ indent_size = 2
[*.json]
indent_style = space
indent_size = 2
+
+[composer.json]
+indent_size = 4
diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml
index 9d59dc08..8e0f7dc7 100644
--- a/.woodpecker/.code_standards_check.yml
+++ b/.woodpecker/.code_standards_check.yml
@@ -13,7 +13,7 @@ pipeline:
commands:
- git config --global user.email "no-reply@friendi.ca"
- git config --global user.name "Friendica"
- - git clone $CI_REPO_LINK addon
+ - git clone $CI_REPO_CLONE_URL addon
- cd addon/
- git checkout $CI_COMMIT_BRANCH
- git fetch origin $CI_COMMIT_REF
diff --git a/.woodpecker/.continuous-deployment.yml b/.woodpecker/.continuous-deployment.yml
index ab6e07e9..d1202978 100644
--- a/.woodpecker/.continuous-deployment.yml
+++ b/.woodpecker/.continuous-deployment.yml
@@ -20,7 +20,7 @@ pipeline:
commands:
- git config --global user.email "no-reply@friendi.ca"
- git config --global user.name "Friendica"
- - git clone $CI_REPO_LINK addon
+ - git clone $CI_REPO_CLONE_URL addon
- cd addon/
- git checkout $CI_COMMIT_BRANCH
- git fetch origin $CI_COMMIT_REF
@@ -45,7 +45,7 @@ pipeline:
branch: [ develop, '*-rc' ]
event: push
composer_install:
- image: friendicaci/php7.4:php7.4.33
+ image: friendicaci/php8.2:php8.2.16
commands:
- export COMPOSER_HOME=.composer
- composer validate
diff --git a/.woodpecker/.messages.po_check.yml b/.woodpecker/.messages.po_check.yml
index f5691e00..ea9fa4d5 100644
--- a/.woodpecker/.messages.po_check.yml
+++ b/.woodpecker/.messages.po_check.yml
@@ -13,7 +13,7 @@ pipeline:
commands:
- git config --global user.email "no-reply@friendi.ca"
- git config --global user.name "Friendica"
- - git clone $CI_REPO_LINK addon
+ - git clone $CI_REPO_CLONE_URL addon
- cd addon/
- git checkout $CI_COMMIT_BRANCH
- git fetch origin $CI_COMMIT_REF
diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml
new file mode 100644
index 00000000..0c25a2bd
--- /dev/null
+++ b/.woodpecker/.phpunit.yml
@@ -0,0 +1,115 @@
+matrix:
+ include:
+ - PHP_MAJOR_VERSION: 7.4
+ PHP_VERSION: 7.4.33
+ - PHP_MAJOR_VERSION: 8.0
+ PHP_VERSION: 8.0.30
+ - PHP_MAJOR_VERSION: 8.1
+ PHP_VERSION: 8.1.27
+ - PHP_MAJOR_VERSION: 8.2
+ PHP_VERSION: 8.2.16
+ - PHP_MAJOR_VERSION: 8.3
+ PHP_VERSION: 8.3.3
+
+# This forces PHP Unit executions at the "opensocial" labeled location (because of much more power...)
+labels:
+ location: opensocial
+
+skip_clone: true
+
+pipeline:
+ clone_friendica_base:
+ image: alpine/git
+ commands:
+ - git clone https://github.com/friendica/friendica.git .
+ - git checkout $CI_COMMIT_BRANCH
+ clone_friendica_addon:
+ image: alpine/git
+ commands:
+ - git config --global user.email "no-reply@friendi.ca"
+ - git config --global user.name "Friendica"
+ - git clone $CI_REPO_CLONE_URL addon
+ - cd addon/
+ - git checkout $CI_COMMIT_BRANCH
+ - git fetch origin $CI_COMMIT_REF
+ - git merge $CI_COMMIT_SHA
+ restore_cache:
+ image: meltwater/drone-cache:dev
+ settings:
+ backend: "filesystem"
+ restore: true
+ cache_key: "{{ .Repo.Name }}_php${PHP_MAJOR_VERSION}_{{ arch }}_{{ os }}"
+ archive_format: "gzip"
+ mount:
+ - '.composer'
+ volumes:
+ - /tmp/drone-cache:/tmp/cache
+ composer_install:
+ image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION}
+ commands:
+ - export COMPOSER_HOME=.composer
+ - ./bin/composer.phar validate
+ - ./bin/composer.phar install --prefer-dist
+ volumes:
+ - /etc/hosts:/etc/hosts
+ rebuild_cache:
+ image: meltwater/drone-cache:dev
+ settings:
+ backend: "filesystem"
+ rebuild: true
+ cache_key: "{{ .Repo.Name }}_php${PHP_MAJOR_VERSION}_{{ arch }}_{{ os }}"
+ archive_format: "gzip"
+ mount:
+ - '.composer'
+ volumes:
+ - /tmp/drone-cache:/tmp/cache
+ test:
+ image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION}
+ environment:
+ MYSQL_HOST: "mariadb"
+ MYSQL_PORT: "3306"
+ MYSQL_DATABASE: "test"
+ MYSQL_PASSWORD: "test"
+ MYSQL_USER: "test"
+ REDIS_HOST: "redis"
+ MEMCACHED_HOST: "memcached"
+ MEMCACHE_HOST: "memcached"
+ commands:
+ - cp config/local-sample.config.php config/local.config.php
+ - if ! bin/wait-for-connection $MYSQL_HOST $MYSQL_PORT 300; then echo "[ERROR] Waited 300 seconds, no response" >&2; exit 1; fi
+ - mysql -h$MYSQL_HOST -P$MYSQL_PORT -p$MYSQL_PASSWORD -u$MYSQL_USER $MYSQL_DATABASE < database.sql
+ - if [ "${PHP_MAJOR_VERSION}" = "8.2" -a "${CI_REPO}" = "friendica/friendica-addons" ]; then
+ phpenmod xdebug;
+ export XDEBUG_MODE=coverage;
+ phpunit --configuration tests/phpunit-addons.xml --coverage-clover clover.xml;
+ else
+ phpunit --configuration tests/phpunit-addons.xml;
+ fi
+ codecov:
+ image: friendicaci/codecov
+ when:
+ matrix:
+ PHP_MAJOR_VERSION: 8.2
+ PHP_VERSION: 8.2.16
+ repo:
+ - friendica/friendica-addons
+ commands:
+ - codecov -R '.' -Z -f 'clover.xml'
+ secrets:
+ - source: codecov-token
+ target: codecov_token
+
+services:
+ mariadb:
+ image: mariadb:latest
+ environment:
+ MYSQL_ALLOW_EMPTY_PASSWORD: "true"
+ MYSQL_DATABASE: "test"
+ MYSQL_PASSWORD: "test"
+ MYSQL_USER: "test"
+
+ memcached:
+ image: memcached
+
+ redis:
+ image: redis
diff --git a/.woodpecker/.releaser.yml b/.woodpecker/.releaser.yml
index 4a661937..68bdfb21 100644
--- a/.woodpecker/.releaser.yml
+++ b/.woodpecker/.releaser.yml
@@ -19,7 +19,7 @@ pipeline:
commands:
- git config --global user.email "no-reply@friendi.ca"
- git config --global user.name "Friendica"
- - git clone $CI_REPO_LINK addon
+ - git clone $CI_REPO_CLONE_URL addon
- cd addon/
- git checkout $CI_COMMIT_BRANCH
- git fetch origin $CI_COMMIT_REF
@@ -42,7 +42,7 @@ pipeline:
repo: friendica/friendica-addons
event: tag
composer_install:
- image: friendicaci/php7.4:php7.4.33
+ image: friendicaci/php8.2:php8.2.16
commands:
- export COMPOSER_HOME=.composer
- composer validate
diff --git a/advancedcontentfilter/advancedcontentfilter.js b/advancedcontentfilter/advancedcontentfilter.js
index fcf7b096..a8fc1c65 100644
--- a/advancedcontentfilter/advancedcontentfilter.js
+++ b/advancedcontentfilter/advancedcontentfilter.js
@@ -54,7 +54,7 @@ new Vue({
self.rules.push(responseJSON.rule);
self.resetForm();
}, function (response) {
- self.errorMessage = response.responseJSON.message;
+ self.errorMessage = response.responseJSON.exception[0].message;
});
}
},
@@ -74,7 +74,7 @@ new Vue({
self.rules[self.editedIndex] = rule;
self.resetForm();
}, function (response) {
- self.errorMessage = response.responseJSON.message;
+ self.errorMessage = response.responseJSON.exception[0].message;
});
},
diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php
index 2254e587..418b253e 100644
--- a/advancedcontentfilter/advancedcontentfilter.php
+++ b/advancedcontentfilter/advancedcontentfilter.php
@@ -190,7 +190,7 @@ function advancedcontentfilter_module() {}
function advancedcontentfilter_init()
{
if (DI::args()->getArgc() > 1 && DI::args()->getArgv()[1] == 'api') {
- $slim = new \Slim\App();
+ $slim = \Slim\Factory\AppFactory::create();
require __DIR__ . '/src/middlewares.php';
@@ -253,7 +253,7 @@ function advancedcontentfilter_content()
'cancel' => DI::l10n()->t('Cancel'),
],
'$current_theme' => DI::app()->getCurrentTheme(),
- '$rules' => advancedcontentfilter_get_rules(),
+ '$rules' => DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])),
'$form_security_token' => BaseModule::getFormSecurityToken()
]);
}
@@ -305,7 +305,7 @@ function advancedcontentfilter_build_fields($data)
* API
*/
-function advancedcontentfilter_get_rules()
+function advancedcontentfilter_get_rules(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
if (!DI::userSession()->getLocalUserId()) {
throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method'));
@@ -313,7 +313,8 @@ function advancedcontentfilter_get_rules()
$rules = DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()]));
- return json_encode($rules);
+ $response->getBody()->write(json_encode($rules));
+ return $response->withHeader('Content-Type', 'application/json');
}
function advancedcontentfilter_get_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args)
@@ -324,10 +325,11 @@ function advancedcontentfilter_get_rules_id(ServerRequestInterface $request, Res
$rule = DBA::selectFirst('advancedcontentfilter_rules', [], ['id' => $args['id'], 'uid' => DI::userSession()->getLocalUserId()]);
- return json_encode($rule);
+ $response->getBody()->write(json_encode($rule));
+ return $response->withHeader('Content-Type', 'application/json');
}
-function advancedcontentfilter_post_rules(ServerRequestInterface $request)
+function advancedcontentfilter_post_rules(ServerRequestInterface $request, ResponseInterface $response)
{
if (!DI::userSession()->getLocalUserId()) {
throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method'));
@@ -360,7 +362,8 @@ function advancedcontentfilter_post_rules(ServerRequestInterface $request)
DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId());
- return json_encode(['message' => DI::l10n()->t('Rule successfully added'), 'rule' => $rule]);
+ $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully added'), 'rule' => $rule]));
+ return $response->withHeader('Content-Type', 'application/json');
}
function advancedcontentfilter_put_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args)
@@ -391,7 +394,8 @@ function advancedcontentfilter_put_rules_id(ServerRequestInterface $request, Res
DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId());
- return json_encode(['message' => DI::l10n()->t('Rule successfully updated')]);
+ $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully updated')]));
+ return $response->withHeader('Content-Type', 'application/json');
}
function advancedcontentfilter_delete_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args)
@@ -414,7 +418,8 @@ function advancedcontentfilter_delete_rules_id(ServerRequestInterface $request,
DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId());
- return json_encode(['message' => DI::l10n()->t('Rule successfully deleted')]);
+ $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully deleted')]));
+ return $response->withHeader('Content-Type', 'application/json');
}
function advancedcontentfilter_get_variables_guid(ServerRequestInterface $request, ResponseInterface $response, $args)
@@ -437,7 +442,8 @@ function advancedcontentfilter_get_variables_guid(ServerRequestInterface $reques
$return = advancedcontentfilter_get_filter_fields(advancedcontentfilter_prepare_item_row($item_row));
- return json_encode(['variables' => str_replace('\\\'', '\'', var_export($return, true))]);
+ $response->getBody()->write(json_encode(['variables' => str_replace('\\\'', '\'', var_export($return, true))]));
+ return $response->withHeader('Content-Type', 'application/json');
}
/**
@@ -455,7 +461,7 @@ function advancedcontentfilter_prepare_item_row(array $item_row): array
$item_row['tags'] = $tags['tags'];
$item_row['hashtags'] = $tags['hashtags'];
$item_row['mentions'] = $tags['mentions'];
- $item_row['attachments'] = Post\Media::splitAttachments($item_row['uri-id']);
+ $item_row['attachments'] = DI::postMediaRepository()->splitAttachments($item_row['uri-id']);
return $item_row;
}
diff --git a/advancedcontentfilter/composer.json b/advancedcontentfilter/composer.json
index 93b19cd5..b9ab1900 100644
--- a/advancedcontentfilter/composer.json
+++ b/advancedcontentfilter/composer.json
@@ -1,25 +1,27 @@
{
- "name": "friendica-addons/advancedcontentfilter",
- "description": "Advanced Content Filter addon for Friendica",
- "type": "friendica-addon",
- "authors": [
- {
- "name": "Hypolite Petovan",
- "email": "hypolite@mrpetovan.com",
- "homepage": "https://friendica.mrpetovan.com/profile/hypolite",
- "role": "Developer"
- }
- ],
- "require": {
- "php": ">=5.6.0",
- "slim/slim": "^3.1",
- "symfony/expression-language": "^3.4"
- },
- "license": "3-clause BSD license",
- "minimum-stability": "stable",
- "config": {
- "optimize-autoloader": true,
- "autoloader-suffix": "AdvancedContentFilterAddon",
- "preferred-install": "dist"
- }
+ "name": "friendica-addons/advancedcontentfilter",
+ "description": "Advanced Content Filter addon for Friendica",
+ "type": "friendica-addon",
+ "authors": [
+ {
+ "name": "Hypolite Petovan",
+ "email": "hypolite@mrpetovan.com",
+ "homepage": "https://friendica.mrpetovan.com/profile/hypolite",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "slim/slim": "^4",
+ "symfony/expression-language": "^3.4"
+ },
+ "license": "3-clause BSD license",
+ "minimum-stability": "stable",
+ "config": {
+ "platform": {
+ "php": "7.4"
+ },
+ "optimize-autoloader": true,
+ "autoloader-suffix": "AdvancedContentFilterAddon",
+ "preferred-install": "dist"
+ }
}
diff --git a/advancedcontentfilter/composer.lock b/advancedcontentfilter/composer.lock
index 774b5ec8..6dbd17ba 100644
--- a/advancedcontentfilter/composer.lock
+++ b/advancedcontentfilter/composer.lock
@@ -4,40 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "d0e3662dd9d910ffe4f71d325bc39319",
+ "content-hash": "a7276eb2d2108a26699f69c750d02d27",
"packages": [
- {
- "name": "container-interop/container-interop",
- "version": "1.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/container-interop/container-interop.git",
- "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
- "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
- "shasum": ""
- },
- "require": {
- "psr/container": "^1.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Interop\\Container\\": "src/Interop/Container/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
- "homepage": "https://github.com/container-interop/container-interop",
- "abandoned": "psr/container",
- "time": "2017-02-14T19:40:03+00:00"
- },
{
"name": "nikic/fast-route",
"version": "v1.3.0",
@@ -84,56 +52,6 @@
],
"time": "2018-02-13T20:26:39+00:00"
},
- {
- "name": "pimple/pimple",
- "version": "v3.2.3",
- "source": {
- "type": "git",
- "url": "https://github.com/silexphp/Pimple.git",
- "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32",
- "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0",
- "psr/container": "^1.0"
- },
- "require-dev": {
- "symfony/phpunit-bridge": "^3.2"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.2.x-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Pimple": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- }
- ],
- "description": "Pimple, a simple Dependency Injection Container",
- "homepage": "http://pimple.sensiolabs.org",
- "keywords": [
- "container",
- "dependency injection"
- ],
- "time": "2018-01-21T07:42:36+00:00"
- },
{
"name": "psr/cache",
"version": "1.0.1",
@@ -182,27 +100,22 @@
},
{
"name": "psr/container",
- "version": "1.0.0",
+ "version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
- "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+ "reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
- "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
+ "reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": ">=7.4.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
@@ -215,7 +128,7 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
@@ -227,24 +140,25 @@
"container-interop",
"psr"
],
- "time": "2017-02-14T16:28:37+00:00"
+ "time": "2021-11-05T16:50:12+00:00"
},
{
- "name": "psr/http-message",
- "version": "1.0.1",
+ "name": "psr/http-factory",
+ "version": "1.0.2",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/http-message.git",
- "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "e616d01114759c4c489f93b099585439f795fe35"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
- "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35",
+ "reference": "e616d01114759c4c489f93b099585439f795fe35",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": ">=7.0.0",
+ "psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
@@ -264,7 +178,58 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "time": "2023-04-10T20:10:41+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
@@ -277,20 +242,126 @@
"request",
"response"
],
- "time": "2016-08-06T14:39:51+00:00"
+ "time": "2023-04-04T09:54:51+00:00"
},
{
- "name": "psr/log",
- "version": "1.1.2",
+ "name": "psr/http-server-handler",
+ "version": "1.0.2",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/log.git",
- "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
+ "url": "https://github.com/php-fig/http-server-handler.git",
+ "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
- "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
+ "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4",
+ "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Server\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP server-side request handler",
+ "keywords": [
+ "handler",
+ "http",
+ "http-interop",
+ "psr",
+ "psr-15",
+ "psr-7",
+ "request",
+ "response",
+ "server"
+ ],
+ "time": "2023-04-10T20:06:20+00:00"
+ },
+ {
+ "name": "psr/http-server-middleware",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-server-middleware.git",
+ "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829",
+ "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0",
+ "psr/http-message": "^1.0 || ^2.0",
+ "psr/http-server-handler": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Server\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP server-side middleware",
+ "keywords": [
+ "http",
+ "http-interop",
+ "middleware",
+ "psr",
+ "psr-15",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "time": "2023-04-11T06:14:47+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
@@ -314,7 +385,7 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
@@ -324,84 +395,55 @@
"psr",
"psr-3"
],
- "time": "2019-11-01T11:05:21+00:00"
- },
- {
- "name": "psr/simple-cache",
- "version": "1.0.1",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/simple-cache.git",
- "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
- "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Psr\\SimpleCache\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
- }
- ],
- "description": "Common interfaces for simple caching",
- "keywords": [
- "cache",
- "caching",
- "psr",
- "psr-16",
- "simple-cache"
- ],
- "time": "2017-10-23T01:57:42+00:00"
+ "time": "2021-05-03T11:20:27+00:00"
},
{
"name": "slim/slim",
- "version": "3.9.2",
+ "version": "4.13.0",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim.git",
- "reference": "4086d0106cf5a7135c69fce4161fe355a8feb118"
+ "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slimphp/Slim/zipball/4086d0106cf5a7135c69fce4161fe355a8feb118",
- "reference": "4086d0106cf5a7135c69fce4161fe355a8feb118",
+ "url": "https://api.github.com/repos/slimphp/Slim/zipball/038fd5713d5a41636fdff0e8dcceedecdd17fc17",
+ "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17",
"shasum": ""
},
"require": {
- "container-interop/container-interop": "^1.2",
- "nikic/fast-route": "^1.0",
- "php": ">=5.5.0",
- "pimple/pimple": "^3.0",
- "psr/container": "^1.0",
- "psr/http-message": "^1.0"
- },
- "provide": {
- "psr/http-message-implementation": "1.0"
+ "ext-json": "*",
+ "nikic/fast-route": "^1.3",
+ "php": "^7.4 || ^8.0",
+ "psr/container": "^1.0 || ^2.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "psr/http-server-handler": "^1.0",
+ "psr/http-server-middleware": "^1.0",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.0",
- "squizlabs/php_codesniffer": "^2.5"
+ "adriansuter/php-autoload-override": "^1.4",
+ "ext-simplexml": "*",
+ "guzzlehttp/psr7": "^2.6",
+ "httpsoft/http-message": "^1.1",
+ "httpsoft/http-server-request": "^1.1",
+ "laminas/laminas-diactoros": "^2.17 || ^3",
+ "nyholm/psr7": "^1.8",
+ "nyholm/psr7-server": "^1.1",
+ "phpspec/prophecy": "^1.19",
+ "phpspec/prophecy-phpunit": "^2.1",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^9.6",
+ "slim/http": "^1.3",
+ "slim/psr7": "^1.6",
+ "squizlabs/php_codesniffer": "^3.9"
+ },
+ "suggest": {
+ "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware",
+ "ext-xml": "Needed to support XML format in BodyParsingMiddleware",
+ "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim",
+ "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information."
},
"type": "library",
"autoload": {
@@ -414,77 +456,100 @@
"MIT"
],
"authors": [
- {
- "name": "Rob Allen",
- "email": "rob@akrabat.com",
- "homepage": "http://akrabat.com"
- },
{
"name": "Josh Lockhart",
"email": "hello@joshlockhart.com",
"homepage": "https://joshlockhart.com"
},
- {
- "name": "Gabriel Manricks",
- "email": "gmanricks@me.com",
- "homepage": "http://gabrielmanricks.com"
- },
{
"name": "Andrew Smith",
"email": "a.smith@silentworks.co.uk",
"homepage": "http://silentworks.co.uk"
+ },
+ {
+ "name": "Rob Allen",
+ "email": "rob@akrabat.com",
+ "homepage": "http://akrabat.com"
+ },
+ {
+ "name": "Pierre Berube",
+ "email": "pierre@lgse.com",
+ "homepage": "http://www.lgse.com"
+ },
+ {
+ "name": "Gabriel Manricks",
+ "email": "gmanricks@me.com",
+ "homepage": "http://gabrielmanricks.com"
}
],
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
- "homepage": "https://slimframework.com",
+ "homepage": "https://www.slimframework.com",
"keywords": [
"api",
"framework",
"micro",
"router"
],
- "time": "2017-11-26T19:13:09+00:00"
+ "funding": [
+ {
+ "url": "https://opencollective.com/slimphp",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/slim/slim",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-03-03T21:25:30+00:00"
},
{
"name": "symfony/cache",
- "version": "v3.4.36",
+ "version": "v4.4.48",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
- "reference": "3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3"
+ "reference": "3b98ed664887ad197b8ede3da2432787212eb915"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache/zipball/3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3",
- "reference": "3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/3b98ed664887ad197b8ede3da2432787212eb915",
+ "reference": "3b98ed664887ad197b8ede3da2432787212eb915",
"shasum": ""
},
"require": {
- "php": "^5.5.9|>=7.0.8",
- "psr/cache": "~1.0",
- "psr/log": "~1.0",
- "psr/simple-cache": "^1.0",
- "symfony/polyfill-apcu": "~1.1"
+ "php": ">=7.1.3",
+ "psr/cache": "^1.0|^2.0",
+ "psr/log": "^1|^2|^3",
+ "symfony/cache-contracts": "^1.1.7|^2",
+ "symfony/polyfill-php73": "^1.9",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/service-contracts": "^1.1|^2",
+ "symfony/var-exporter": "^4.2|^5.0"
},
"conflict": {
- "symfony/var-dumper": "<3.3"
+ "doctrine/dbal": "<2.7",
+ "symfony/dependency-injection": "<3.4",
+ "symfony/http-kernel": "<4.4|>=5.0",
+ "symfony/var-dumper": "<4.4"
},
"provide": {
- "psr/cache-implementation": "1.0",
- "psr/simple-cache-implementation": "1.0"
+ "psr/cache-implementation": "1.0|2.0",
+ "psr/simple-cache-implementation": "1.0|2.0",
+ "symfony/cache-implementation": "1.0|2.0"
},
"require-dev": {
"cache/integration-tests": "dev-master",
- "doctrine/cache": "~1.6",
- "doctrine/dbal": "~2.4",
- "predis/predis": "~1.0"
+ "doctrine/cache": "^1.6|^2.0",
+ "doctrine/dbal": "^2.7|^3.0",
+ "predis/predis": "^1.1",
+ "psr/simple-cache": "^1.0|^2.0",
+ "symfony/config": "^4.2|^5.0",
+ "symfony/dependency-injection": "^3.4|^4.1|^5.0",
+ "symfony/filesystem": "^4.4|^5.0",
+ "symfony/http-kernel": "^4.4",
+ "symfony/var-dumper": "^4.4|^5.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.4-dev"
- }
- },
"autoload": {
"psr-4": {
"Symfony\\Component\\Cache\\": ""
@@ -507,38 +572,188 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony Cache component with PSR-6, PSR-16, and tags",
+ "description": "Provides extended PSR-6, PSR-16 (and tags) implementations",
"homepage": "https://symfony.com",
"keywords": [
"caching",
"psr6"
],
- "time": "2019-12-01T10:45:41+00:00"
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-10-17T20:21:54+00:00"
},
{
- "name": "symfony/expression-language",
- "version": "v3.4.8",
+ "name": "symfony/cache-contracts",
+ "version": "v2.5.2",
"source": {
"type": "git",
- "url": "https://github.com/symfony/expression-language.git",
- "reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241"
+ "url": "https://github.com/symfony/cache-contracts.git",
+ "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/expression-language/zipball/867e4d1f5d4e52435a8ffff6b24fd6a801582241",
- "reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241",
+ "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc",
+ "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc",
"shasum": ""
},
"require": {
- "php": "^5.5.9|>=7.0.8",
- "symfony/cache": "~3.1|~4.0"
+ "php": ">=7.2.5",
+ "psr/cache": "^1.0|^2.0|^3.0"
+ },
+ "suggest": {
+ "symfony/cache-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.4-dev"
+ "dev-main": "2.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
}
},
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Cache\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to caching",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-01-02T09:53:40+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v2.5.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
+ "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-01-02T09:53:40+00:00"
+ },
+ {
+ "name": "symfony/expression-language",
+ "version": "v3.4.47",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/expression-language.git",
+ "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/expression-language/zipball/de38e66398fca1fcb9c48e80279910e6889cb28f",
+ "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/cache": "~3.1|~4.0",
+ "symfony/polyfill-php70": "~1.6"
+ },
+ "type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\ExpressionLanguage\\": ""
@@ -563,37 +778,120 @@
],
"description": "Symfony ExpressionLanguage Component",
"homepage": "https://symfony.com",
- "time": "2018-01-03T07:37:34+00:00"
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-10-24T10:57:07+00:00"
},
{
- "name": "symfony/polyfill-apcu",
- "version": "v1.13.1",
+ "name": "symfony/polyfill-php70",
+ "version": "v1.20.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-apcu.git",
- "reference": "a8e961c841b9ec52927a87914f8820a1ad8f8116"
+ "url": "https://github.com/symfony/polyfill-php70.git",
+ "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/a8e961c841b9ec52927a87914f8820a1ad8f8116",
- "reference": "a8e961c841b9ec52927a87914f8820a1ad8f8116",
+ "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644",
+ "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=7.1"
+ },
+ "type": "metapackage",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.20-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-10-23T14:02:19+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php73",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php73.git",
+ "reference": "21bd091060673a1177ae842c0ef8fe30893114d2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2",
+ "reference": "21bd091060673a1177ae842c0ef8fe30893114d2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "1.13-dev"
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Apcu\\": ""
- },
"files": [
"bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php73\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -610,16 +908,256 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting apcu_* functions to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
- "apcu",
"compatibility",
"polyfill",
"portable",
"shim"
],
- "time": "2019-11-27T13:56:44+00:00"
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
+ "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v2.5.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
+ "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "psr/container": "^1.1",
+ "symfony/deprecation-contracts": "^2.1|^3"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "suggest": {
+ "symfony/service-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-05-30T19:17:29+00:00"
+ },
+ {
+ "name": "symfony/var-exporter",
+ "version": "v5.4.35",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-exporter.git",
+ "reference": "abb0a151b62d6b07e816487e20040464af96cae7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7",
+ "reference": "abb0a151b62d6b07e816487e20040464af96cae7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "require-dev": {
+ "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\VarExporter\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Allows exporting any serializable PHP data structure to plain PHP code",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "clone",
+ "construct",
+ "export",
+ "hydrate",
+ "instantiate",
+ "serialize"
+ ],
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-01-23T13:51:25+00:00"
}
],
"packages-dev": [],
@@ -628,8 +1166,10 @@
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
- "platform": {
- "php": ">=5.6.0"
+ "platform": [],
+ "platform-dev": [],
+ "platform-overrides": {
+ "php": "7.4"
},
- "platform-dev": []
+ "plugin-api-version": "1.1.0"
}
diff --git a/advancedcontentfilter/src/middlewares.php b/advancedcontentfilter/src/middlewares.php
index dffb9363..2b831473 100644
--- a/advancedcontentfilter/src/middlewares.php
+++ b/advancedcontentfilter/src/middlewares.php
@@ -21,31 +21,12 @@
use Friendica\DI;
-$container = $slim->getContainer();
+/** @var $slim \Slim\App */
-// Error handler based off https://stackoverflow.com/a/48135009/757392
-$container['errorHandler'] = function () {
- return function(Psr\Http\Message\RequestInterface $request, Psr\Http\Message\ResponseInterface $response, Exception $exception)
- {
- $responseCode = 500;
+/**
+ * The routing middleware should be added before the ErrorMiddleware
+ * Otherwise exceptions thrown from it will not be handled
+ */
+$slim->addRoutingMiddleware();
- if (is_a($exception, 'Friendica\Network\HTTPException')) {
- $responseCode = $exception->getCode();
- }
-
- $errors['message'] = $exception->getMessage();
-
- $errors['responseCode'] = $responseCode;
-
- return $response
- ->withStatus($responseCode)
- ->withJson($errors);
- };
-};
-
-$container['notFoundHandler'] = function () {
- return function ()
- {
- throw new \Friendica\Network\HTTPException\NotFoundException(DI::l10n()->t('Method not found'));
- };
-};
+$errorMiddleware = $slim->addErrorMiddleware(true, true, true, DI::logger());
diff --git a/advancedcontentfilter/src/routes.php b/advancedcontentfilter/src/routes.php
index 09077bda..a46f1b4b 100644
--- a/advancedcontentfilter/src/routes.php
+++ b/advancedcontentfilter/src/routes.php
@@ -20,20 +20,17 @@
*/
/* @var $slim Slim\App */
-$slim->group('/advancedcontentfilter/api', function () {
- /* @var $this Slim\App */
- $this->group('/rules', function () {
- /* @var $this Slim\App */
- $this->get('', 'advancedcontentfilter_get_rules');
- $this->post('', 'advancedcontentfilter_post_rules');
+$slim->group('/advancedcontentfilter/api', function (\Slim\Routing\RouteCollectorProxy $app) {
+ $app->group('/rules', function (\Slim\Routing\RouteCollectorProxy $app) {
+ $app->get('', 'advancedcontentfilter_get_rules');
+ $app->post('', 'advancedcontentfilter_post_rules');
- $this->get('/{id}', 'advancedcontentfilter_get_rules_id');
- $this->put('/{id}', 'advancedcontentfilter_put_rules_id');
- $this->delete('/{id}', 'advancedcontentfilter_delete_rules_id');
+ $app->get('/{id}', 'advancedcontentfilter_get_rules_id');
+ $app->put('/{id}', 'advancedcontentfilter_put_rules_id');
+ $app->delete('/{id}', 'advancedcontentfilter_delete_rules_id');
});
- $this->group('/variables', function () {
- /* @var $this Slim\App */
- $this->get('/{guid}', 'advancedcontentfilter_get_variables_guid');
+ $app->group('/variables', function (\Slim\Routing\RouteCollectorProxy $app) {
+ $app->get('/{guid}', 'advancedcontentfilter_get_variables_guid');
});
});
diff --git a/advancedcontentfilter/templates/settings.tpl b/advancedcontentfilter/templates/settings.tpl
index c9dfbe3a..8b82e595 100644
--- a/advancedcontentfilter/templates/settings.tpl
+++ b/advancedcontentfilter/templates/settings.tpl
@@ -3,7 +3,7 @@
-
-EOT;
-}
-
-function blockem_item_photo_menu(array &$b)
-{
- global $blockem_words;
-
- if (!DI::userSession()->getLocalUserId() || $b['item']['self']) {
- return;
- }
-
- $blocked = false;
- $author = $b['item']['author-link'];
-
- if (!empty($blockem_words)) {
- foreach($blockem_words as $bloke) {
- if (Strings::compareLink($bloke,$author)) {
- $blocked = true;
- break;
- }
- }
- }
- if ($blocked) {
- $b['menu'][DI::l10n()->t('Unblock Author')] = 'javascript:blockemUnblock(\'' . $author . '\');';
- } else {
- $b['menu'][DI::l10n()->t('Block Author')] = 'javascript:blockemBlock(\'' . $author . '\');';
- }
-}
-
-/**
- * This is a statement rather than an actual function definition. The simple
- * existence of this method is checked to figure out if the addon offers a
- * module.
- */
-function blockem_module() {}
-
-function blockem_init()
-{
- if (!DI::userSession()->getLocalUserId()) {
- return;
- }
-
- $words = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'blockem', 'words');
-
- if (array_key_exists('block', $_GET) && $_GET['block']) {
- if (strlen($words)) {
- $words .= ',';
- }
-
- $words .= trim($_GET['block']);
- }
-
- if (array_key_exists('unblock', $_GET) && $_GET['unblock']) {
- $arr = explode(',',$words);
- $newarr = [];
-
- if (count($arr)) {
- foreach ($arr as $x) {
- if (!Strings::compareLink(trim($x), trim($_GET['unblock']))) {
- $newarr[] = $x;
- }
- }
- }
-
- $words = implode(',', $newarr);
- }
-
- DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'blockem', 'words', $words);
- exit();
-}
diff --git a/blockem/lang/C/messages.po b/blockem/lang/C/messages.po
deleted file mode 100644
index 64bb3fc4..00000000
--- a/blockem/lang/C/messages.po
+++ /dev/null
@@ -1,45 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: \n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:13-0500\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"Language: \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: blockem.php:39
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr ""
-
-#: blockem.php:40
-msgid "Comma separated profile URLS:"
-msgstr ""
-
-#: blockem.php:45
-msgid "Blockem"
-msgstr ""
-
-#: blockem.php:120
-#, php-format
-msgid "Filtered user: %s"
-msgstr ""
-
-#: blockem.php:183
-msgid "Unblock Author"
-msgstr ""
-
-#: blockem.php:185
-msgid "Block Author"
-msgstr ""
diff --git a/blockem/lang/ar/messages.po b/blockem/lang/ar/messages.po
deleted file mode 100644
index c9d6d5f9..00000000
--- a/blockem/lang/ar/messages.po
+++ /dev/null
@@ -1,52 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# abidin toumi , 2021
-# Farida Khalaf , 2021
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-02-01 18:15+0100\n"
-"PO-Revision-Date: 2021-10-29 08:15+0000\n"
-"Last-Translator: abidin toumi \n"
-"Language-Team: Arabic (http://www.transifex.com/Friendica/friendica/language/ar/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ar\n"
-"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
-
-#: blockem.php:42 blockem.php:46
-msgid "Blockem"
-msgstr "احجبه "
-
-#: blockem.php:50
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "إخفاء محتوى المستخدم عن طريق تصغير المشاركات. و استبدال الصورة الرمزية الخاصة بهم بصورة عامة."
-
-#: blockem.php:51
-msgid "Comma separated profile URLS:"
-msgstr "عناوين الملفات الشخصية مفصولة بفواصل:"
-
-#: blockem.php:55
-msgid "Save Settings"
-msgstr "احفظ الإعدادات"
-
-#: blockem.php:131
-#, php-format
-msgid "Filtered user: %s"
-msgstr "ترشيح المستخدم :1%s"
-
-#: blockem.php:190
-msgid "Unblock Author"
-msgstr "ألغ الحجب عن المدون"
-
-#: blockem.php:192
-msgid "Block Author"
-msgstr "احجب المدون"
diff --git a/blockem/lang/ar/strings.php b/blockem/lang/ar/strings.php
deleted file mode 100644
index 0f58fa22..00000000
--- a/blockem/lang/ar/strings.php
+++ /dev/null
@@ -1,14 +0,0 @@
-=3 && $n%100<=10) { return 3; } else if ($n%100>=11 && $n%100<=99) { return 4; } else { return 5; }
-}}
-$a->strings['Blockem'] = 'احجبه ';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'إخفاء محتوى المستخدم عن طريق تصغير المشاركات. و استبدال الصورة الرمزية الخاصة بهم بصورة عامة.';
-$a->strings['Comma separated profile URLS:'] = 'عناوين الملفات الشخصية مفصولة بفواصل:';
-$a->strings['Save Settings'] = 'احفظ الإعدادات';
-$a->strings['Filtered user: %s'] = 'ترشيح المستخدم :1%s';
-$a->strings['Unblock Author'] = 'ألغ الحجب عن المدون';
-$a->strings['Block Author'] = 'احجب المدون';
diff --git a/blockem/lang/ca/messages.po b/blockem/lang/ca/messages.po
deleted file mode 100644
index 6d4c3468..00000000
--- a/blockem/lang/ca/messages.po
+++ /dev/null
@@ -1,59 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Joan Bar , 2019
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-17 10:23+0200\n"
-"PO-Revision-Date: 2019-10-14 11:50+0000\n"
-"Last-Translator: Joan Bar \n"
-"Language-Team: Catalan (http://www.transifex.com/Friendica/friendica/language/ca/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ca\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:54 blockem.php:58
-msgid "Blockem"
-msgstr "Blockem"
-
-#: blockem.php:62
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Amaga el contingut de l'usuari mitjançant la publicació col·lapsada. També substitueix el seu avatar per una imatge genèrica"
-
-#: blockem.php:63
-msgid "Comma separated profile URLS:"
-msgstr "URL de perfil separats per comes:"
-
-#: blockem.php:67
-msgid "Save Settings"
-msgstr "Desa la configuració"
-
-#: blockem.php:81
-msgid "BLOCKEM Settings saved."
-msgstr "S'ha desat la configuració de BLOCKEM."
-
-#: blockem.php:143
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Usuari filtrat:%s"
-
-#: blockem.php:202
-msgid "Unblock Author"
-msgstr "Desbloca l'autor"
-
-#: blockem.php:204
-msgid "Block Author"
-msgstr "Autor de bloc"
-
-#: blockem.php:244
-msgid "blockem settings updated"
-msgstr "S'ha actualitzat la configuració de blockem"
diff --git a/blockem/lang/ca/strings.php b/blockem/lang/ca/strings.php
deleted file mode 100644
index be4deede..00000000
--- a/blockem/lang/ca/strings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-strings['Blockem'] = 'Blockem';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Amaga el contingut de l\'usuari mitjançant la publicació col·lapsada. També substitueix el seu avatar per una imatge genèrica';
-$a->strings['Comma separated profile URLS:'] = 'URL de perfil separats per comes:';
-$a->strings['Save Settings'] = 'Desa la configuració';
-$a->strings['BLOCKEM Settings saved.'] = 'S\'ha desat la configuració de BLOCKEM.';
-$a->strings['Filtered user: %s'] = 'Usuari filtrat:%s';
-$a->strings['Unblock Author'] = 'Desbloca l\'autor';
-$a->strings['Block Author'] = 'Autor de bloc';
-$a->strings['blockem settings updated'] = 'S\'ha actualitzat la configuració de blockem';
diff --git a/blockem/lang/cs/messages.po b/blockem/lang/cs/messages.po
deleted file mode 100644
index fb90a2ca..00000000
--- a/blockem/lang/cs/messages.po
+++ /dev/null
@@ -1,60 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Aditoo, 2018
-# michal_s , 2014
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-17 10:23+0200\n"
-"PO-Revision-Date: 2018-08-18 12:25+0000\n"
-"Last-Translator: Aditoo\n"
-"Language-Team: Czech (http://www.transifex.com/Friendica/friendica/language/cs/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: cs\n"
-"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
-
-#: blockem.php:54 blockem.php:58
-msgid "Blockem"
-msgstr "Blockem"
-
-#: blockem.php:62
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Skrývá uživatelský obsah zabalením příspěvků. Navíc nahrazuje avatar generickým obrázkem."
-
-#: blockem.php:63
-msgid "Comma separated profile URLS:"
-msgstr "URL adresy profilů, oddělené čárkami:"
-
-#: blockem.php:67
-msgid "Save Settings"
-msgstr "Uložit nastavení"
-
-#: blockem.php:81
-msgid "BLOCKEM Settings saved."
-msgstr "Nastavení BLOCKEM uložena."
-
-#: blockem.php:143
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Filtrovaný uživatel: %s"
-
-#: blockem.php:202
-msgid "Unblock Author"
-msgstr "Odblokovat autora"
-
-#: blockem.php:204
-msgid "Block Author"
-msgstr "Zablokovat autora"
-
-#: blockem.php:244
-msgid "blockem settings updated"
-msgstr "nastavení blockem aktualizována"
diff --git a/blockem/lang/cs/strings.php b/blockem/lang/cs/strings.php
deleted file mode 100644
index ac32d78f..00000000
--- a/blockem/lang/cs/strings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; }
-}}
-$a->strings['Blockem'] = 'Blockem';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Skrývá uživatelský obsah zabalením příspěvků. Navíc nahrazuje avatar generickým obrázkem.';
-$a->strings['Comma separated profile URLS:'] = 'URL adresy profilů, oddělené čárkami:';
-$a->strings['Save Settings'] = 'Uložit nastavení';
-$a->strings['BLOCKEM Settings saved.'] = 'Nastavení BLOCKEM uložena.';
-$a->strings['Filtered user: %s'] = 'Filtrovaný uživatel: %s';
-$a->strings['Unblock Author'] = 'Odblokovat autora';
-$a->strings['Block Author'] = 'Zablokovat autora';
-$a->strings['blockem settings updated'] = 'nastavení blockem aktualizována';
diff --git a/blockem/lang/da-dk/messages.po b/blockem/lang/da-dk/messages.po
deleted file mode 100644
index e4a80bff..00000000
--- a/blockem/lang/da-dk/messages.po
+++ /dev/null
@@ -1,47 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Anton , 2022
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:13-0500\n"
-"PO-Revision-Date: 2014-06-22 11:20+0000\n"
-"Last-Translator: Anton , 2022\n"
-"Language-Team: Danish (Denmark) (http://www.transifex.com/Friendica/friendica/language/da_DK/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: da_DK\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:39
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Skjul brugers indhold ved at kollapse deres opslag. Erstatter også deres avatar med et generisk billede."
-
-#: blockem.php:40
-msgid "Comma separated profile URLS:"
-msgstr "Kommasepareret liste over profil-URL's:"
-
-#: blockem.php:45
-msgid "Blockem"
-msgstr "Blokdem"
-
-#: blockem.php:120
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Filtreret bruger: %s"
-
-#: blockem.php:183
-msgid "Unblock Author"
-msgstr "Fjern blokering af forfatter"
-
-#: blockem.php:185
-msgid "Block Author"
-msgstr "Blokér forfatter"
diff --git a/blockem/lang/da-dk/strings.php b/blockem/lang/da-dk/strings.php
deleted file mode 100644
index e99144ec..00000000
--- a/blockem/lang/da-dk/strings.php
+++ /dev/null
@@ -1,13 +0,0 @@
-strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Skjul brugers indhold ved at kollapse deres opslag. Erstatter også deres avatar med et generisk billede.';
-$a->strings['Comma separated profile URLS:'] = 'Kommasepareret liste over profil-URL\'s:';
-$a->strings['Blockem'] = 'Blokdem';
-$a->strings['Filtered user: %s'] = 'Filtreret bruger: %s';
-$a->strings['Unblock Author'] = 'Fjern blokering af forfatter';
-$a->strings['Block Author'] = 'Blokér forfatter';
diff --git a/blockem/lang/de/messages.po b/blockem/lang/de/messages.po
deleted file mode 100644
index d1e2f704..00000000
--- a/blockem/lang/de/messages.po
+++ /dev/null
@@ -1,50 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Andreas H., 2018
-# Tobias Diekershoff , 2014
-# Tobias Diekershoff , 2018
-# Ulf Rompe , 2019
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:13-0500\n"
-"PO-Revision-Date: 2021-12-22 15:27+0000\n"
-"Last-Translator: Transifex Bot <>\n"
-"Language-Team: German (http://www.transifex.com/Friendica/friendica/language/de/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: de\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:39
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Verbirgt Inhalte von Benutzern durch Zusammenklappen der Beiträge. Des Weiteren wird das Profilbild durch einen generischen Avatar ersetzt."
-
-#: blockem.php:40
-msgid "Comma separated profile URLS:"
-msgstr "Komma-separierte Liste von Profil-URLs"
-
-#: blockem.php:45
-msgid "Blockem"
-msgstr "Blockem"
-
-#: blockem.php:120
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Gefilterte Person: %s"
-
-#: blockem.php:183
-msgid "Unblock Author"
-msgstr "Autor freischalten"
-
-#: blockem.php:185
-msgid "Block Author"
-msgstr "Autor blockieren"
diff --git a/blockem/lang/de/strings.php b/blockem/lang/de/strings.php
deleted file mode 100644
index 109af368..00000000
--- a/blockem/lang/de/strings.php
+++ /dev/null
@@ -1,13 +0,0 @@
-strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Verbirgt Inhalte von Benutzern durch Zusammenklappen der Beiträge. Des Weiteren wird das Profilbild durch einen generischen Avatar ersetzt.';
-$a->strings['Comma separated profile URLS:'] = 'Komma-separierte Liste von Profil-URLs';
-$a->strings['Blockem'] = 'Blockem';
-$a->strings['Filtered user: %s'] = 'Gefilterte Person: %s';
-$a->strings['Unblock Author'] = 'Autor freischalten';
-$a->strings['Block Author'] = 'Autor blockieren';
diff --git a/blockem/lang/en-gb/messages.po b/blockem/lang/en-gb/messages.po
deleted file mode 100644
index 6bcc7b9b..00000000
--- a/blockem/lang/en-gb/messages.po
+++ /dev/null
@@ -1,59 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Andy H3 , 2018
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-02-09 13:00+0100\n"
-"PO-Revision-Date: 2018-03-15 14:10+0000\n"
-"Last-Translator: Andy H3 \n"
-"Language-Team: English (United Kingdom) (http://www.transifex.com/Friendica/friendica/language/en_GB/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: en_GB\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:51 blockem.php:55
-msgid "\"Blockem\""
-msgstr "\"Blockem\""
-
-#: blockem.php:59
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Hides user's content by collapsing posts. Also replaces their avatar with generic image."
-
-#: blockem.php:60
-msgid "Comma separated profile URLS:"
-msgstr "Comma separated profile URLs:"
-
-#: blockem.php:64
-msgid "Save Settings"
-msgstr "Save settings"
-
-#: blockem.php:77
-msgid "BLOCKEM Settings saved."
-msgstr "Blockem settings saved."
-
-#: blockem.php:140
-#, php-format
-msgid "Hidden content by %s - Click to open/close"
-msgstr "Hidden content by %s - Reveal/hide"
-
-#: blockem.php:193
-msgid "Unblock Author"
-msgstr "Unblock author"
-
-#: blockem.php:195
-msgid "Block Author"
-msgstr "Block author"
-
-#: blockem.php:227
-msgid "blockem settings updated"
-msgstr "Blockem settings updated"
diff --git a/blockem/lang/en-gb/strings.php b/blockem/lang/en-gb/strings.php
deleted file mode 100644
index 0b9d9e4b..00000000
--- a/blockem/lang/en-gb/strings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-strings['"Blockem"'] = '"Blockem"';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.';
-$a->strings['Comma separated profile URLS:'] = 'Comma separated profile URLs:';
-$a->strings['Save Settings'] = 'Save settings';
-$a->strings['BLOCKEM Settings saved.'] = 'Blockem settings saved.';
-$a->strings['Hidden content by %s - Click to open/close'] = 'Hidden content by %s - Reveal/hide';
-$a->strings['Unblock Author'] = 'Unblock author';
-$a->strings['Block Author'] = 'Block author';
-$a->strings['blockem settings updated'] = 'Blockem settings updated';
diff --git a/blockem/lang/en-us/messages.po b/blockem/lang/en-us/messages.po
deleted file mode 100644
index 1d64620b..00000000
--- a/blockem/lang/en-us/messages.po
+++ /dev/null
@@ -1,61 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Adam Clark , 2018
-# Andy H3 , 2018
-# R C , 2018
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-04-01 11:11-0400\n"
-"PO-Revision-Date: 2018-06-13 02:40+0000\n"
-"Last-Translator: R C \n"
-"Language-Team: English (United States) (http://www.transifex.com/Friendica/friendica/language/en_US/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: en_US\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:52 blockem.php:56
-msgid "\"Blockem\""
-msgstr "Blockem"
-
-#: blockem.php:60
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Hides user's content by collapsing posts. Also replaces their avatar with generic image."
-
-#: blockem.php:61
-msgid "Comma separated profile URLS:"
-msgstr "Comma-separated profile URLs:"
-
-#: blockem.php:65
-msgid "Save Settings"
-msgstr "Save settings"
-
-#: blockem.php:78
-msgid "BLOCKEM Settings saved."
-msgstr "Blockem settings saved."
-
-#: blockem.php:136
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Filtered user: %s"
-
-#: blockem.php:189
-msgid "Unblock Author"
-msgstr "Unblock author"
-
-#: blockem.php:191
-msgid "Block Author"
-msgstr "Block author"
-
-#: blockem.php:223
-msgid "blockem settings updated"
-msgstr "Blockem settings updated"
diff --git a/blockem/lang/en-us/strings.php b/blockem/lang/en-us/strings.php
deleted file mode 100644
index fd76a1bc..00000000
--- a/blockem/lang/en-us/strings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-strings['"Blockem"'] = 'Blockem';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.';
-$a->strings['Comma separated profile URLS:'] = 'Comma-separated profile URLs:';
-$a->strings['Save Settings'] = 'Save settings';
-$a->strings['BLOCKEM Settings saved.'] = 'Blockem settings saved.';
-$a->strings['Filtered user: %s'] = 'Filtered user: %s';
-$a->strings['Unblock Author'] = 'Unblock author';
-$a->strings['Block Author'] = 'Block author';
-$a->strings['blockem settings updated'] = 'Blockem settings updated';
diff --git a/blockem/lang/eo/strings.php b/blockem/lang/eo/strings.php
deleted file mode 100644
index b6116507..00000000
--- a/blockem/lang/eo/strings.php
+++ /dev/null
@@ -1,10 +0,0 @@
-strings["\"Blockem\" Settings"] = "\"Blockem\" Agordoj";
-$a->strings["Comma separated profile URLS to block"] = "Blokotaj URL adresoj, disigita per komo";
-$a->strings["Submit"] = "Sendi";
-$a->strings["BLOCKEM Settings saved."] = "Konservis Agordojn de BLOCKEM.";
-$a->strings["Blocked %s - Click to open/close"] = "%s blokita - Klaku por malfermi/fermi";
-$a->strings["Unblock Author"] = "Malbloki Aŭtoron";
-$a->strings["Block Author"] = "Bloki Aŭtoron";
-$a->strings["blockem settings updated"] = "Ĝisdatigis la blockem agordojn";
diff --git a/blockem/lang/es/messages.po b/blockem/lang/es/messages.po
deleted file mode 100644
index 0b59921e..00000000
--- a/blockem/lang/es/messages.po
+++ /dev/null
@@ -1,53 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Albert, 2018
-# Senex Petrovic , 2021
-# Tupambae.org, 2016
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-02-01 18:15+0100\n"
-"PO-Revision-Date: 2021-04-01 09:45+0000\n"
-"Last-Translator: Senex Petrovic \n"
-"Language-Team: Spanish (http://www.transifex.com/Friendica/friendica/language/es/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: es\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:42 blockem.php:46
-msgid "Blockem"
-msgstr "Blockem (Bloquealos)"
-
-#: blockem.php:50
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Oculta el contenido del usuario al colapsar las publicaciones. También reemplaza su avatar con una imagen genérica."
-
-#: blockem.php:51
-msgid "Comma separated profile URLS:"
-msgstr "URLs de perfil separadas por comas:"
-
-#: blockem.php:55
-msgid "Save Settings"
-msgstr "Guardar configuración"
-
-#: blockem.php:131
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Usuario filtrado: %s"
-
-#: blockem.php:190
-msgid "Unblock Author"
-msgstr "Desbloquear autor"
-
-#: blockem.php:192
-msgid "Block Author"
-msgstr "Bloquear autor"
diff --git a/blockem/lang/es/strings.php b/blockem/lang/es/strings.php
deleted file mode 100644
index 7d1de601..00000000
--- a/blockem/lang/es/strings.php
+++ /dev/null
@@ -1,14 +0,0 @@
-strings['Blockem'] = 'Blockem (Bloquealos)';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Oculta el contenido del usuario al colapsar las publicaciones. También reemplaza su avatar con una imagen genérica.';
-$a->strings['Comma separated profile URLS:'] = 'URLs de perfil separadas por comas:';
-$a->strings['Save Settings'] = 'Guardar configuración';
-$a->strings['Filtered user: %s'] = 'Usuario filtrado: %s';
-$a->strings['Unblock Author'] = 'Desbloquear autor';
-$a->strings['Block Author'] = 'Bloquear autor';
diff --git a/blockem/lang/fi-fi/messages.po b/blockem/lang/fi-fi/messages.po
deleted file mode 100644
index 4fac9aa7..00000000
--- a/blockem/lang/fi-fi/messages.po
+++ /dev/null
@@ -1,60 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Kris, 2018
-# Kris, 2018
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-04-01 11:11-0400\n"
-"PO-Revision-Date: 2018-04-18 14:44+0000\n"
-"Last-Translator: Kris\n"
-"Language-Team: Finnish (Finland) (http://www.transifex.com/Friendica/friendica/language/fi_FI/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fi_FI\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:52 blockem.php:56
-msgid "\"Blockem\""
-msgstr "\"Blockem\""
-
-#: blockem.php:60
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr ""
-
-#: blockem.php:61
-msgid "Comma separated profile URLS:"
-msgstr "Profiilien URL-osoitteet pilkulla erotettuina:"
-
-#: blockem.php:65
-msgid "Save Settings"
-msgstr "Tallenna asetukset"
-
-#: blockem.php:78
-msgid "BLOCKEM Settings saved."
-msgstr "Blockem -asetukset tallennettu"
-
-#: blockem.php:136
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Suodatettu käyttäjä: %s"
-
-#: blockem.php:189
-msgid "Unblock Author"
-msgstr "Poista kirjoittaja estolistalta"
-
-#: blockem.php:191
-msgid "Block Author"
-msgstr "Lisää kirjoittaja estolistalle"
-
-#: blockem.php:223
-msgid "blockem settings updated"
-msgstr "blockem -asetukset päivitetty"
diff --git a/blockem/lang/fi-fi/strings.php b/blockem/lang/fi-fi/strings.php
deleted file mode 100644
index d15b4a56..00000000
--- a/blockem/lang/fi-fi/strings.php
+++ /dev/null
@@ -1,15 +0,0 @@
-strings['"Blockem"'] = '"Blockem"';
-$a->strings['Comma separated profile URLS:'] = 'Profiilien URL-osoitteet pilkulla erotettuina:';
-$a->strings['Save Settings'] = 'Tallenna asetukset';
-$a->strings['BLOCKEM Settings saved.'] = 'Blockem -asetukset tallennettu';
-$a->strings['Filtered user: %s'] = 'Suodatettu käyttäjä: %s';
-$a->strings['Unblock Author'] = 'Poista kirjoittaja estolistalta';
-$a->strings['Block Author'] = 'Lisää kirjoittaja estolistalle';
-$a->strings['blockem settings updated'] = 'blockem -asetukset päivitetty';
diff --git a/blockem/lang/fr/messages.po b/blockem/lang/fr/messages.po
deleted file mode 100644
index d3617290..00000000
--- a/blockem/lang/fr/messages.po
+++ /dev/null
@@ -1,50 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Hypolite Petovan , 2016
-# Marie Olive , 2018
-# StefOfficiel , 2015
-# Vladimir Núñez , 2018
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:13-0500\n"
-"PO-Revision-Date: 2014-06-22 11:20+0000\n"
-"Last-Translator: Vladimir Núñez , 2018\n"
-"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: fr\n"
-"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
-
-#: blockem.php:39
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Cache le contenu de l'utilisateur en contractant les publications. Remplace aussi leur avatar par une image générique."
-
-#: blockem.php:40
-msgid "Comma separated profile URLS:"
-msgstr "URLs de profil séparées par des virgules:"
-
-#: blockem.php:45
-msgid "Blockem"
-msgstr "Bloquez-les"
-
-#: blockem.php:120
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Utilisateur filtré:%s"
-
-#: blockem.php:183
-msgid "Unblock Author"
-msgstr "Débloquer l'Auteur"
-
-#: blockem.php:185
-msgid "Block Author"
-msgstr "Bloquer l'Auteur"
diff --git a/blockem/lang/fr/strings.php b/blockem/lang/fr/strings.php
deleted file mode 100644
index 26b86f24..00000000
--- a/blockem/lang/fr/strings.php
+++ /dev/null
@@ -1,13 +0,0 @@
-strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Cache le contenu de l\'utilisateur en contractant les publications. Remplace aussi leur avatar par une image générique.';
-$a->strings['Comma separated profile URLS:'] = 'URLs de profil séparées par des virgules:';
-$a->strings['Blockem'] = 'Bloquez-les';
-$a->strings['Filtered user: %s'] = 'Utilisateur filtré:%s';
-$a->strings['Unblock Author'] = 'Débloquer l\'Auteur';
-$a->strings['Block Author'] = 'Bloquer l\'Auteur';
diff --git a/blockem/lang/hu/messages.po b/blockem/lang/hu/messages.po
deleted file mode 100644
index 3a29b820..00000000
--- a/blockem/lang/hu/messages.po
+++ /dev/null
@@ -1,47 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Balázs Úr, 2020
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:13-0500\n"
-"PO-Revision-Date: 2014-06-22 11:20+0000\n"
-"Last-Translator: Balázs Úr, 2020\n"
-"Language-Team: Hungarian (http://www.transifex.com/Friendica/friendica/language/hu/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: hu\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:39
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Elrejti a felhasználók tartalmát a bejegyzések összecsukásával. Ezenkívül lecseréli a profilképeiket egy általános képre."
-
-#: blockem.php:40
-msgid "Comma separated profile URLS:"
-msgstr "Profil URL-ek vesszővel elválasztva:"
-
-#: blockem.php:45
-msgid "Blockem"
-msgstr "Blockem"
-
-#: blockem.php:120
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Kiszűrt felhasználó: %s"
-
-#: blockem.php:183
-msgid "Unblock Author"
-msgstr "Szerző tiltásának feloldása"
-
-#: blockem.php:185
-msgid "Block Author"
-msgstr "Szerző tiltása"
diff --git a/blockem/lang/hu/strings.php b/blockem/lang/hu/strings.php
deleted file mode 100644
index 5a3abfec..00000000
--- a/blockem/lang/hu/strings.php
+++ /dev/null
@@ -1,13 +0,0 @@
-strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Elrejti a felhasználók tartalmát a bejegyzések összecsukásával. Ezenkívül lecseréli a profilképeiket egy általános képre.';
-$a->strings['Comma separated profile URLS:'] = 'Profil URL-ek vesszővel elválasztva:';
-$a->strings['Blockem'] = 'Blockem';
-$a->strings['Filtered user: %s'] = 'Kiszűrt felhasználó: %s';
-$a->strings['Unblock Author'] = 'Szerző tiltásának feloldása';
-$a->strings['Block Author'] = 'Szerző tiltása';
diff --git a/blockem/lang/is/strings.php b/blockem/lang/is/strings.php
deleted file mode 100644
index 3075c457..00000000
--- a/blockem/lang/is/strings.php
+++ /dev/null
@@ -1,10 +0,0 @@
-strings["\"Blockem\" Settings"] = "\"Blockem\" stillingar";
-$a->strings["Comma separated profile URLS to block"] = "Banna lista af forsíðum (komma á milli)";
-$a->strings["Submit"] = "Senda inn";
-$a->strings["BLOCKEM Settings saved."] = "BLOCKEM stillingar vistaðar.";
-$a->strings["Blocked %s - Click to open/close"] = "%s sett í straff - Smella til að taka úr/setja á";
-$a->strings["Unblock Author"] = "Leyfa notanda";
-$a->strings["Block Author"] = "Banna notanda";
-$a->strings["blockem settings updated"] = "";
diff --git a/blockem/lang/it/messages.po b/blockem/lang/it/messages.po
deleted file mode 100644
index cdf74f99..00000000
--- a/blockem/lang/it/messages.po
+++ /dev/null
@@ -1,59 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# fabrixxm , 2014,2018-2019
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-17 10:23+0200\n"
-"PO-Revision-Date: 2019-03-11 14:21+0000\n"
-"Last-Translator: fabrixxm \n"
-"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: it\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:54 blockem.php:58
-msgid "Blockem"
-msgstr "Blockem"
-
-#: blockem.php:62
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Nascondi il contenuto degli utenti collassando i messaggi. Sostituisce anche gli avatar con un'immagine generica."
-
-#: blockem.php:63
-msgid "Comma separated profile URLS:"
-msgstr "URL profili separati da virgola:"
-
-#: blockem.php:67
-msgid "Save Settings"
-msgstr "Salva Impostazioni"
-
-#: blockem.php:81
-msgid "BLOCKEM Settings saved."
-msgstr "Impostazioni BLOCKEM salvate."
-
-#: blockem.php:143
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Utente filtrato: %s"
-
-#: blockem.php:202
-msgid "Unblock Author"
-msgstr "Sblocca autore"
-
-#: blockem.php:204
-msgid "Block Author"
-msgstr "Blocca autore"
-
-#: blockem.php:244
-msgid "blockem settings updated"
-msgstr "Impostazioni 'blockem' aggiornate."
diff --git a/blockem/lang/it/strings.php b/blockem/lang/it/strings.php
deleted file mode 100644
index aa73286a..00000000
--- a/blockem/lang/it/strings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-strings['Blockem'] = 'Blockem';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Nascondi il contenuto degli utenti collassando i messaggi. Sostituisce anche gli avatar con un\'immagine generica.';
-$a->strings['Comma separated profile URLS:'] = 'URL profili separati da virgola:';
-$a->strings['Save Settings'] = 'Salva Impostazioni';
-$a->strings['BLOCKEM Settings saved.'] = 'Impostazioni BLOCKEM salvate.';
-$a->strings['Filtered user: %s'] = 'Utente filtrato: %s';
-$a->strings['Unblock Author'] = 'Sblocca autore';
-$a->strings['Block Author'] = 'Blocca autore';
-$a->strings['blockem settings updated'] = 'Impostazioni \'blockem\' aggiornate.';
diff --git a/blockem/lang/nb-no/strings.php b/blockem/lang/nb-no/strings.php
deleted file mode 100644
index 0dd6660d..00000000
--- a/blockem/lang/nb-no/strings.php
+++ /dev/null
@@ -1,10 +0,0 @@
-strings["\"Blockem\" Settings"] = "";
-$a->strings["Comma separated profile URLS to block"] = "";
-$a->strings["Submit"] = "Lagre";
-$a->strings["BLOCKEM Settings saved."] = "";
-$a->strings["Blocked %s - Click to open/close"] = "";
-$a->strings["Unblock Author"] = "";
-$a->strings["Block Author"] = "";
-$a->strings["blockem settings updated"] = "";
diff --git a/blockem/lang/nl/messages.po b/blockem/lang/nl/messages.po
deleted file mode 100644
index f8bde25c..00000000
--- a/blockem/lang/nl/messages.po
+++ /dev/null
@@ -1,60 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# AgnesElisa , 2018
-# Jeroen De Meerleer , 2018
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-17 10:23+0200\n"
-"PO-Revision-Date: 2018-08-24 13:49+0000\n"
-"Last-Translator: Jeroen De Meerleer \n"
-"Language-Team: Dutch (http://www.transifex.com/Friendica/friendica/language/nl/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: nl\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:54 blockem.php:58
-msgid "Blockem"
-msgstr "Blockem"
-
-#: blockem.php:62
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Verbergt de inhoud van het bericht van de gebruiker. Daarnaast vervangt het de avatar door een standaardafbeelding."
-
-#: blockem.php:63
-msgid "Comma separated profile URLS:"
-msgstr "Profiel URLs (kommagescheiden):"
-
-#: blockem.php:67
-msgid "Save Settings"
-msgstr "Instellingen opslaan"
-
-#: blockem.php:81
-msgid "BLOCKEM Settings saved."
-msgstr "BLOCKEM instellingen opgeslagen."
-
-#: blockem.php:143
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Gefilterde gebruiker: %s"
-
-#: blockem.php:202
-msgid "Unblock Author"
-msgstr "Deblokkeer Auteur"
-
-#: blockem.php:204
-msgid "Block Author"
-msgstr "Auteur blokkeren"
-
-#: blockem.php:244
-msgid "blockem settings updated"
-msgstr "blockem instellingen opgeslagen"
diff --git a/blockem/lang/nl/strings.php b/blockem/lang/nl/strings.php
deleted file mode 100644
index b523cdc4..00000000
--- a/blockem/lang/nl/strings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-strings['Blockem'] = 'Blockem';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Verbergt de inhoud van het bericht van de gebruiker. Daarnaast vervangt het de avatar door een standaardafbeelding.';
-$a->strings['Comma separated profile URLS:'] = 'Profiel URLs (kommagescheiden):';
-$a->strings['Save Settings'] = 'Instellingen opslaan';
-$a->strings['BLOCKEM Settings saved.'] = 'BLOCKEM instellingen opgeslagen.';
-$a->strings['Filtered user: %s'] = 'Gefilterde gebruiker: %s';
-$a->strings['Unblock Author'] = 'Deblokkeer Auteur';
-$a->strings['Block Author'] = 'Auteur blokkeren';
-$a->strings['blockem settings updated'] = 'blockem instellingen opgeslagen';
diff --git a/blockem/lang/pl/messages.po b/blockem/lang/pl/messages.po
deleted file mode 100644
index 8e70e0b5..00000000
--- a/blockem/lang/pl/messages.po
+++ /dev/null
@@ -1,47 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Waldemar Stoczkowski, 2018
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:13-0500\n"
-"PO-Revision-Date: 2014-06-22 11:20+0000\n"
-"Last-Translator: Waldemar Stoczkowski, 2018\n"
-"Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: pl\n"
-"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
-
-#: blockem.php:39
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Ukrywa zawartość użytkownika, zwijając posty. Zastępuje również awatar wygenerowanym obrazem."
-
-#: blockem.php:40
-msgid "Comma separated profile URLS:"
-msgstr "Rozdzielone przecinkami adresy URL profilu:"
-
-#: blockem.php:45
-msgid "Blockem"
-msgstr "Zablokowanie"
-
-#: blockem.php:120
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Użytkownik filtrowany: %s"
-
-#: blockem.php:183
-msgid "Unblock Author"
-msgstr "Odblokuj autora"
-
-#: blockem.php:185
-msgid "Block Author"
-msgstr "Zablokuj autora"
diff --git a/blockem/lang/pl/strings.php b/blockem/lang/pl/strings.php
deleted file mode 100644
index 49951a68..00000000
--- a/blockem/lang/pl/strings.php
+++ /dev/null
@@ -1,13 +0,0 @@
-=2 && $n%10<=4) && ($n%100<12 || $n%100>14)) { return 1; } else if ($n!=1 && ($n%10>=0 && $n%10<=1) || ($n%10>=5 && $n%10<=9) || ($n%100>=12 && $n%100<=14)) { return 2; } else { return 3; }
-}}
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Ukrywa zawartość użytkownika, zwijając posty. Zastępuje również awatar wygenerowanym obrazem.';
-$a->strings['Comma separated profile URLS:'] = 'Rozdzielone przecinkami adresy URL profilu:';
-$a->strings['Blockem'] = 'Zablokowanie';
-$a->strings['Filtered user: %s'] = 'Użytkownik filtrowany: %s';
-$a->strings['Unblock Author'] = 'Odblokuj autora';
-$a->strings['Block Author'] = 'Zablokuj autora';
diff --git a/blockem/lang/pt-br/strings.php b/blockem/lang/pt-br/strings.php
deleted file mode 100644
index 49f69cc3..00000000
--- a/blockem/lang/pt-br/strings.php
+++ /dev/null
@@ -1,10 +0,0 @@
-strings["\"Blockem\" Settings"] = "Configurações \"Blockem\"";
-$a->strings["Comma separated profile URLS to block"] = "URLS de perfis separados por vírgulas a serem bloqueados";
-$a->strings["Submit"] = "Enviar";
-$a->strings["BLOCKEM Settings saved."] = "Configurações BLOCKEM armazenadas.";
-$a->strings["Blocked %s - Click to open/close"] = "Bloqueado %s - Clique para abrir/fechar";
-$a->strings["Unblock Author"] = "Desbloqueie Autor";
-$a->strings["Block Author"] = "Bloqueie Autor";
-$a->strings["blockem settings updated"] = "configurações blockem atualizadas";
diff --git a/blockem/lang/ro/messages.po b/blockem/lang/ro/messages.po
deleted file mode 100644
index a74e5757..00000000
--- a/blockem/lang/ro/messages.po
+++ /dev/null
@@ -1,52 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-06-22 13:18+0200\n"
-"PO-Revision-Date: 2014-07-08 11:43+0000\n"
-"Last-Translator: Arian - Cazare Muncitori \n"
-"Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/friendica/language/ro_RO/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ro_RO\n"
-"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
-
-#: blockem.php:53 blockem.php:57
-msgid "\"Blockem\""
-msgstr "\"Blockem\""
-
-#: blockem.php:61
-msgid "Comma separated profile URLS to block"
-msgstr "Adresele URL de profil, de blocat, separate prin virgulă"
-
-#: blockem.php:65
-msgid "Save Settings"
-msgstr "Salvare Configurări"
-
-#: blockem.php:78
-msgid "BLOCKEM Settings saved."
-msgstr "Configurările BLOCKEM au fost salvate."
-
-#: blockem.php:142
-#, php-format
-msgid "Blocked %s - Click to open/close"
-msgstr "%s Blocate - Apăsați pentru a deschide/închide"
-
-#: blockem.php:197
-msgid "Unblock Author"
-msgstr "Deblocare Autor"
-
-#: blockem.php:199
-msgid "Block Author"
-msgstr "Blocare Autor"
-
-#: blockem.php:231
-msgid "blockem settings updated"
-msgstr "Configurările blockem au fost actualizate"
diff --git a/blockem/lang/ro/strings.php b/blockem/lang/ro/strings.php
deleted file mode 100644
index 6fc8a094..00000000
--- a/blockem/lang/ro/strings.php
+++ /dev/null
@@ -1,15 +0,0 @@
-19)||(($n%100==0)&&($n!=0)))) { return 2; } else { return 1; }
-}}
-$a->strings['"Blockem"'] = '"Blockem"';
-$a->strings['Comma separated profile URLS to block'] = 'Adresele URL de profil, de blocat, separate prin virgulă';
-$a->strings['Save Settings'] = 'Salvare Configurări';
-$a->strings['BLOCKEM Settings saved.'] = 'Configurările BLOCKEM au fost salvate.';
-$a->strings['Blocked %s - Click to open/close'] = '%s Blocate - Apăsați pentru a deschide/închide';
-$a->strings['Unblock Author'] = 'Deblocare Autor';
-$a->strings['Block Author'] = 'Blocare Autor';
-$a->strings['blockem settings updated'] = 'Configurările blockem au fost actualizate';
diff --git a/blockem/lang/ru/messages.po b/blockem/lang/ru/messages.po
deleted file mode 100644
index 22427327..00000000
--- a/blockem/lang/ru/messages.po
+++ /dev/null
@@ -1,60 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Alexander An , 2020
-# Stanislav N. , 2017-2018
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-08-17 10:23+0200\n"
-"PO-Revision-Date: 2020-04-23 14:13+0000\n"
-"Last-Translator: Alexander An \n"
-"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: ru\n"
-"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
-
-#: blockem.php:54 blockem.php:58
-msgid "Blockem"
-msgstr "Blockem"
-
-#: blockem.php:62
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Скрыть контент пользователя. Также заменяет его аватар изображением по-умолчанию."
-
-#: blockem.php:63
-msgid "Comma separated profile URLS:"
-msgstr "URL профилей, разделенные запятыми:"
-
-#: blockem.php:67
-msgid "Save Settings"
-msgstr "Сохранить настройки"
-
-#: blockem.php:81
-msgid "BLOCKEM Settings saved."
-msgstr "BLOCKEM Настройки сохранены."
-
-#: blockem.php:143
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Отфильтрованный пользователь: %s"
-
-#: blockem.php:202
-msgid "Unblock Author"
-msgstr "Разблокировать автора"
-
-#: blockem.php:204
-msgid "Block Author"
-msgstr "Блокировать автора"
-
-#: blockem.php:244
-msgid "blockem settings updated"
-msgstr "Настройки Blockem обновлены"
diff --git a/blockem/lang/ru/strings.php b/blockem/lang/ru/strings.php
deleted file mode 100644
index ef586740..00000000
--- a/blockem/lang/ru/strings.php
+++ /dev/null
@@ -1,16 +0,0 @@
-=2 && $n%10<=4 && ($n%100<12 || $n%100>14)) { return 1; } else if ($n%10==0 || ($n%10>=5 && $n%10<=9) || ($n%100>=11 && $n%100<=14)) { return 2; } else { return 3; }
-}}
-$a->strings['Blockem'] = 'Blockem';
-$a->strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Скрыть контент пользователя. Также заменяет его аватар изображением по-умолчанию.';
-$a->strings['Comma separated profile URLS:'] = 'URL профилей, разделенные запятыми:';
-$a->strings['Save Settings'] = 'Сохранить настройки';
-$a->strings['BLOCKEM Settings saved.'] = 'BLOCKEM Настройки сохранены.';
-$a->strings['Filtered user: %s'] = 'Отфильтрованный пользователь: %s';
-$a->strings['Unblock Author'] = 'Разблокировать автора';
-$a->strings['Block Author'] = 'Блокировать автора';
-$a->strings['blockem settings updated'] = 'Настройки Blockem обновлены';
diff --git a/blockem/lang/sv/messages.po b/blockem/lang/sv/messages.po
deleted file mode 100644
index ede8ee94..00000000
--- a/blockem/lang/sv/messages.po
+++ /dev/null
@@ -1,47 +0,0 @@
-# ADDON blockem
-# Copyright (C)
-# This file is distributed under the same license as the Friendica blockem addon package.
-#
-#
-# Translators:
-# Bjoessi , 2019
-msgid ""
-msgstr ""
-"Project-Id-Version: friendica\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:13-0500\n"
-"PO-Revision-Date: 2021-12-22 15:27+0000\n"
-"Last-Translator: Transifex Bot <>\n"
-"Language-Team: Swedish (http://www.transifex.com/Friendica/friendica/language/sv/)\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: sv\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#: blockem.php:39
-msgid ""
-"Hides user's content by collapsing posts. Also replaces their avatar with "
-"generic image."
-msgstr "Döljer användares inlägg genom sammanslagning nedåt. Användarens profilbild ersätts med en standardbild."
-
-#: blockem.php:40
-msgid "Comma separated profile URLS:"
-msgstr "Kommaseparerade profiladresser:"
-
-#: blockem.php:45
-msgid "Blockem"
-msgstr "BLOCKEM"
-
-#: blockem.php:120
-#, php-format
-msgid "Filtered user: %s"
-msgstr "Filtrerat på användare:%s"
-
-#: blockem.php:183
-msgid "Unblock Author"
-msgstr "Avblockera författare"
-
-#: blockem.php:185
-msgid "Block Author"
-msgstr "Blockera författare"
diff --git a/blockem/lang/sv/strings.php b/blockem/lang/sv/strings.php
deleted file mode 100644
index 724e2d23..00000000
--- a/blockem/lang/sv/strings.php
+++ /dev/null
@@ -1,13 +0,0 @@
-strings['Hides user\'s content by collapsing posts. Also replaces their avatar with generic image.'] = 'Döljer användares inlägg genom sammanslagning nedåt. Användarens profilbild ersätts med en standardbild.';
-$a->strings['Comma separated profile URLS:'] = 'Kommaseparerade profiladresser:';
-$a->strings['Blockem'] = 'BLOCKEM';
-$a->strings['Filtered user: %s'] = 'Filtrerat på användare:%s';
-$a->strings['Unblock Author'] = 'Avblockera författare';
-$a->strings['Block Author'] = 'Blockera författare';
diff --git a/blockem/lang/zh-cn/strings.php b/blockem/lang/zh-cn/strings.php
deleted file mode 100644
index 3a3dfaeb..00000000
--- a/blockem/lang/zh-cn/strings.php
+++ /dev/null
@@ -1,10 +0,0 @@
-strings["\"Blockem\" Settings"] = "「Blockem」配置";
-$a->strings["Comma separated profile URLS to block"] = "逗号分简介URL为栏";
-$a->strings["Submit"] = "提交";
-$a->strings["BLOCKEM Settings saved."] = "「Blockem」配置保存了。";
-$a->strings["Blocked %s - Click to open/close"] = "%s拦了-点击为开关";
-$a->strings["Unblock Author"] = "不拦作家";
-$a->strings["Block Author"] = "拦作家";
-$a->strings["blockem settings updated"] = "blockem设置更新了";
diff --git a/blockem/templates/settings.tpl b/blockem/templates/settings.tpl
deleted file mode 100644
index 67398400..00000000
--- a/blockem/templates/settings.tpl
+++ /dev/null
@@ -1 +0,0 @@
-{{include file="field_textarea.tpl" field=$words}}
diff --git a/bluesky/README.md b/bluesky/README.md
new file mode 100644
index 00000000..bf900fcd
--- /dev/null
+++ b/bluesky/README.md
@@ -0,0 +1,9 @@
+Bluesky Addon
+==============
+
+This addon supports posting to and receiving posts from Bluesky.
+
+No setup is needed for the admins to make it work for their users.
+
+Bluesky itself is under development as well. It is planned to make it decentral.
+The addon is prepared to support different servers. But it isn't enabled yet.
\ No newline at end of file
diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php
new file mode 100644
index 00000000..ba7c1d65
--- /dev/null
+++ b/bluesky/bluesky.php
@@ -0,0 +1,1969 @@
+
+ *
+ * @todo
+ * Currently technical issues in the core:
+ * - Outgoing mentions
+ *
+ * At some point in time:
+ * - Sending Quote shares https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecord and https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecordwithmedia
+ *
+ * Possibly not possible:
+ * - only fetch new posts
+ *
+ * Currently not possible, due to limitations in Friendica
+ * - mute contacts https://atproto.com/lexicons/app-bsky-graph#appbskygraphmuteactor
+ * - unmute contacts https://atproto.com/lexicons/app-bsky-graph#appbskygraphunmuteactor
+ *
+ * Possibly interesting:
+ * - https://atproto.com/lexicons/com-atproto-label#comatprotolabelsubscribelabels
+ */
+
+use Friendica\Content\Text\BBCode;
+use Friendica\Content\Text\HTML;
+use Friendica\Content\Text\Plaintext;
+use Friendica\Core\Cache\Enum\Duration;
+use Friendica\Core\Config\Util\ConfigFileManager;
+use Friendica\Core\Hook;
+use Friendica\Core\Logger;
+use Friendica\Core\Protocol;
+use Friendica\Core\Renderer;
+use Friendica\Core\Worker;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Contact;
+use Friendica\Model\GServer;
+use Friendica\Model\Item;
+use Friendica\Model\ItemURI;
+use Friendica\Model\Photo;
+use Friendica\Model\Post;
+use Friendica\Model\Tag;
+use Friendica\Model\User;
+use Friendica\Network\HTTPClient\Client\HttpClientAccept;
+use Friendica\Network\HTTPClient\Client\HttpClientOptions;
+use Friendica\Object\Image;
+use Friendica\Protocol\Activity;
+use Friendica\Protocol\Relay;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Strings;
+
+const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes
+const BLUESKY_IMAGE_SIZE = [1000000, 500000, 100000, 50000];
+
+const BLUEKSY_STATUS_UNKNOWN = 0;
+const BLUEKSY_STATUS_TOKEN_OK = 1;
+const BLUEKSY_STATUS_SUCCESS = 2;
+const BLUEKSY_STATUS_API_FAIL = 10;
+const BLUEKSY_STATUS_DID_FAIL = 11;
+const BLUEKSY_STATUS_PDS_FAIL = 12;
+const BLUEKSY_STATUS_TOKEN_FAIL = 13;
+
+/*
+ * (Currently) hard wired paths for Bluesky services
+ */
+const BLUESKY_DIRECTORY = 'https://plc.directory'; // Path to the directory server service to fetch the PDS of a given DID
+const BLUESKY_PDS = 'https://bsky.social'; // Path to the personal data server service (PDS) to fetch the DID for a given handle
+const BLUESKY_WEB = 'https://bsky.app'; // Path to the web interface with the user profile and posts
+
+function bluesky_install()
+{
+ Hook::register('load_config', __FILE__, 'bluesky_load_config');
+ Hook::register('hook_fork', __FILE__, 'bluesky_hook_fork');
+ Hook::register('post_local', __FILE__, 'bluesky_post_local');
+ Hook::register('notifier_normal', __FILE__, 'bluesky_send');
+ Hook::register('jot_networks', __FILE__, 'bluesky_jot_nets');
+ Hook::register('connector_settings', __FILE__, 'bluesky_settings');
+ Hook::register('connector_settings_post', __FILE__, 'bluesky_settings_post');
+ Hook::register('cron', __FILE__, 'bluesky_cron');
+ Hook::register('support_follow', __FILE__, 'bluesky_support_follow');
+ Hook::register('support_probe', __FILE__, 'bluesky_support_probe');
+ Hook::register('follow', __FILE__, 'bluesky_follow');
+ Hook::register('unfollow', __FILE__, 'bluesky_unfollow');
+ Hook::register('block', __FILE__, 'bluesky_block');
+ Hook::register('unblock', __FILE__, 'bluesky_unblock');
+ Hook::register('check_item_notification', __FILE__, 'bluesky_check_item_notification');
+ Hook::register('probe_detect', __FILE__, 'bluesky_probe_detect');
+ Hook::register('item_by_link', __FILE__, 'bluesky_item_by_link');
+}
+
+function bluesky_load_config(ConfigFileManager $loader)
+{
+ DI::app()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC);
+}
+
+function bluesky_check_item_notification(array &$notification_data)
+{
+ if (empty($notification_data['uid'])) {
+ return;
+ }
+
+ $did = bluesky_get_user_did($notification_data['uid']);
+ if (empty($did)) {
+ return;
+ }
+
+ $notification_data['profiles'][] = $did;
+}
+
+function bluesky_probe_detect(array &$hookData)
+{
+ // Don't overwrite an existing result
+ if (isset($hookData['result'])) {
+ return;
+ }
+
+ // Avoid a lookup for the wrong network
+ if (!in_array($hookData['network'], ['', Protocol::BLUESKY])) {
+ return;
+ }
+
+ $pconfig = DBA::selectFirst('pconfig', ['uid'], ["`cat` = ? AND `k` = ? AND `v` != ?", 'bluesky', 'access_token', '']);
+ if (empty($pconfig['uid'])) {
+ return;
+ }
+
+ if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') {
+ $did = $hookData['uri'];
+ } elseif (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) {
+ $did = bluesky_get_did($matches[1]);
+ if (empty($did)) {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ $token = bluesky_get_token($pconfig['uid']);
+ if (empty($token)) {
+ return;
+ }
+
+ $data = bluesky_xrpc_get($pconfig['uid'], 'app.bsky.actor.getProfile', ['actor' => $did]);
+ if (empty($data)) {
+ return;
+ }
+
+ $hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], false);
+
+ $hookData['result']['baseurl'] = bluesky_get_pds($did);
+
+ // Preparing probe data. This differs slightly from the contact array
+ $hookData['result']['about'] = HTML::toBBCode($data->description ?? '');
+ $hookData['result']['photo'] = $data->avatar ?? '';
+ $hookData['result']['header'] = $data->banner ?? '';
+ $hookData['result']['batch'] = '';
+ $hookData['result']['notify'] = '';
+ $hookData['result']['poll'] = '';
+ $hookData['result']['poco'] = '';
+ $hookData['result']['pubkey'] = '';
+ $hookData['result']['priority'] = 0;
+ $hookData['result']['guid'] = '';
+}
+
+function bluesky_item_by_link(array &$hookData)
+{
+ // Don't overwrite an existing result
+ if (isset($hookData['item_id'])) {
+ return;
+ }
+
+ $token = bluesky_get_token($hookData['uid']);
+ if (empty($token)) {
+ return;
+ }
+
+ if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) {
+ return;
+ }
+
+ $did = bluesky_get_did($matches[1]);
+ if (empty($did)) {
+ return;
+ }
+
+ Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'handle' => $matches[1], 'did' => $did, 'cid' => $matches[2]]);
+
+ $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2];
+
+ $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0);
+ Logger::debug('Got post', ['profile' => $matches[1], 'cid' => $matches[2], 'result' => $uri]);
+ if (!empty($uri)) {
+ $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]);
+ if (!empty($item['id'])) {
+ $hookData['item_id'] = $item['id'];
+ }
+ }
+}
+
+function bluesky_support_follow(array &$data)
+{
+ if ($data['protocol'] == Protocol::BLUESKY) {
+ $data['result'] = true;
+ }
+}
+
+function bluesky_support_probe(array &$data)
+{
+ if ($data['protocol'] == Protocol::BLUESKY) {
+ $data['result'] = true;
+ }
+}
+
+function bluesky_follow(array &$hook_data)
+{
+ $token = bluesky_get_token($hook_data['uid']);
+ if (empty($token)) {
+ return;
+ }
+
+ Logger::debug('Check if contact is bluesky', ['data' => $hook_data]);
+ $contact = DBA::selectFirst('contact', [], ['network' => Protocol::BLUESKY, 'url' => $hook_data['url'], 'uid' => [0, $hook_data['uid']]]);
+ if (empty($contact)) {
+ return;
+ }
+
+ $record = [
+ 'subject' => $contact['url'],
+ 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+ '$type' => 'app.bsky.graph.follow'
+ ];
+
+ $post = [
+ 'collection' => 'app.bsky.graph.follow',
+ 'repo' => bluesky_get_user_did($hook_data['uid']),
+ 'record' => $record
+ ];
+
+ $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post);
+ if (!empty($activity->uri)) {
+ $hook_data['contact'] = $contact;
+ Logger::debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]);
+ }
+}
+
+function bluesky_unfollow(array &$hook_data)
+{
+ $token = bluesky_get_token($hook_data['uid']);
+ if (empty($token)) {
+ return;
+ }
+
+ if ($hook_data['contact']['network'] != Protocol::BLUESKY) {
+ return;
+ }
+
+ $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]);
+ if (empty($data->viewer) || empty($data->viewer->following)) {
+ return;
+ }
+
+ bluesky_delete_post($data->viewer->following, $hook_data['uid']);
+
+ $hook_data['result'] = true;
+}
+
+function bluesky_block(array &$hook_data)
+{
+ $token = bluesky_get_token($hook_data['uid']);
+ if (empty($token)) {
+ return;
+ }
+
+ Logger::debug('Check if contact is bluesky', ['data' => $hook_data]);
+ $contact = DBA::selectFirst('contact', [], ['network' => Protocol::BLUESKY, 'url' => $hook_data['url'], 'uid' => [0, $hook_data['uid']]]);
+ if (empty($contact)) {
+ return;
+ }
+
+ $record = [
+ 'subject' => $contact['url'],
+ 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+ '$type' => 'app.bsky.graph.block'
+ ];
+
+ $post = [
+ 'collection' => 'app.bsky.graph.block',
+ 'repo' => bluesky_get_user_did($hook_data['uid']),
+ 'record' => $record
+ ];
+
+ $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post);
+ if (!empty($activity->uri)) {
+ $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']);
+ if (!empty($cdata['user'])) {
+ Contact::remove($cdata['user']);
+ }
+ Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]);
+ }
+}
+
+function bluesky_unblock(array &$hook_data)
+{
+ $token = bluesky_get_token($hook_data['uid']);
+ if (empty($token)) {
+ return;
+ }
+
+ if ($hook_data['contact']['network'] != Protocol::BLUESKY) {
+ return;
+ }
+
+ $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]);
+ if (empty($data->viewer) || empty($data->viewer->blocking)) {
+ return;
+ }
+
+ bluesky_delete_post($data->viewer->blocking, $hook_data['uid']);
+
+ $hook_data['result'] = true;
+}
+
+function bluesky_addon_admin(string &$o)
+{
+ $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/bluesky/');
+
+ $o = Renderer::replaceMacros($t, [
+ '$submit' => DI::l10n()->t('Save Settings'),
+ '$friendica_handles' => ['friendica_handles', DI::l10n()->t('Allow your users to use your hostname for their Bluesky handles'), DI::config()->get('bluesky', 'friendica_handles'), DI::l10n()->t('Before enabling this option, you have to setup a wildcard domain configuration and you have to enable wildcard requests in your webserver configuration. On Apache this is done by adding "ServerAlias *.%s" to your HTTP configuration. You don\'t need to change the HTTPS configuration.', DI::baseUrl()->getHost())],
+ ]);
+}
+
+function bluesky_addon_admin_post()
+{
+ DI::config()->set('bluesky', 'friendica_handles', (bool)$_POST['friendica_handles']);
+}
+
+function bluesky_settings(array &$data)
+{
+ if (!DI::userSession()->getLocalUserId()) {
+ return;
+ }
+
+ $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false;
+ $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false;
+ $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds');
+ $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle');
+ $did = bluesky_get_user_did(DI::userSession()->getLocalUserId());
+ $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token');
+ $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false;
+ $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false;
+ $custom_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle') ?? false;
+
+ if (DI::config()->get('bluesky', 'friendica_handles')) {
+ $self = User::getById(DI::userSession()->getLocalUserId(), ['nickname']);
+ $handle = $self['nickname'] . '.' . DI::baseUrl()->getHost();
+ $friendica_handle = ['bluesky_friendica_handle', DI::l10n()->t('Allow to use %s as your Bluesky handle.', $handle), $custom_handle, DI::l10n()->t('When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select "No DNS Panel". Then select "Verify Text File".', $handle, $handle)];
+ } else {
+ $friendica_handle = [];
+ }
+
+ $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/bluesky/');
+ $html = Renderer::replaceMacros($t, [
+ '$enable' => ['bluesky', DI::l10n()->t('Enable Bluesky Post Addon'), $enabled],
+ '$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled],
+ '$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import],
+ '$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')],
+ '$custom_handle' => $friendica_handle,
+ '$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'],
+ '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle],
+ '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'],
+ '$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")],
+ '$status' => bluesky_get_status($handle, $did, $pds, $token),
+ ]);
+
+ $data = [
+ 'connector' => 'bluesky',
+ 'title' => DI::l10n()->t('Bluesky Import/Export'),
+ 'image' => 'images/bluesky.jpg',
+ 'enabled' => $enabled,
+ 'html' => $html,
+ ];
+}
+
+function bluesky_get_status(string $handle = null, string $did = null, string $pds = null, string $token = null): string
+{
+ if (empty($handle)) {
+ return DI::l10n()->t('You are not authenticated. Please enter your handle and the app password.');
+ }
+
+ $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? BLUEKSY_STATUS_UNKNOWN;
+
+ // Fallback mechanism for connection that had been established before the introduction of the status
+ if ($status == BLUEKSY_STATUS_UNKNOWN) {
+ if (empty($did)) {
+ $status = BLUEKSY_STATUS_DID_FAIL;
+ } elseif (empty($pds)) {
+ $status = BLUEKSY_STATUS_PDS_FAIL;
+ } elseif (!empty($token)) {
+ $status = BLUEKSY_STATUS_TOKEN_OK;
+ } else {
+ $status = BLUEKSY_STATUS_TOKEN_FAIL;
+ }
+ }
+
+ switch ($status) {
+ case BLUEKSY_STATUS_TOKEN_OK:
+ return DI::l10n()->t("You are authenticated to Bluesky. For security reasons the password isn't stored.");
+ case BLUEKSY_STATUS_SUCCESS:
+ return DI::l10n()->t('The communication with the personal data server service (PDS) is established.');
+ case BLUEKSY_STATUS_API_FAIL;
+ return DI::l10n()->t('Communication issues with the personal data server service (PDS).');
+ case BLUEKSY_STATUS_DID_FAIL:
+ return DI::l10n()->t('The DID for the provided handle could not be detected. Please check if you entered the correct handle.');
+ case BLUEKSY_STATUS_PDS_FAIL:
+ return DI::l10n()->t('The personal data server service (PDS) could not be detected.');
+ case BLUEKSY_STATUS_TOKEN_FAIL:
+ return DI::l10n()->t('The authentication with the provided handle and password failed. Please check if you entered the correct password.');
+ default:
+ return '';
+ }
+}
+
+function bluesky_settings_post(array &$b)
+{
+ if (empty($_POST['bluesky-submit'])) {
+ return;
+ }
+
+ $old_pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds');
+ $old_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle');
+ $old_did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did');
+
+ $handle = trim($_POST['bluesky_handle'], ' @');
+
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post', intval($_POST['bluesky']));
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default', intval($_POST['bluesky_bydefault']));
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle);
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import']));
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds']));
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle']));
+
+ if (!empty($handle)) {
+ $did = bluesky_get_user_did(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle);
+ if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) {
+ $pds = bluesky_get_pds($did);
+ if (empty($pds)) {
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_PDS_FAIL);
+ }
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'pds', $pds);
+ } else {
+ $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds');
+ }
+ } else {
+ DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'did');
+ DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'pds');
+ DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token');
+ DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'refresh_token');
+ DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'token_created');
+ DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'status');
+ }
+
+ if (!empty($did) && !empty($pds) && !empty($_POST['bluesky_password'])) {
+ bluesky_create_token(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']);
+ }
+}
+
+function bluesky_jot_nets(array &$jotnets_fields)
+{
+ if (!DI::userSession()->getLocalUserId()) {
+ return;
+ }
+
+ if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post')) {
+ $jotnets_fields[] = [
+ 'type' => 'checkbox',
+ 'field' => [
+ 'bluesky_enable',
+ DI::l10n()->t('Post to Bluesky'),
+ DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default')
+ ]
+ ];
+ }
+}
+
+function bluesky_cron()
+{
+ $last = (int)DI::keyValue()->get('bluesky_last_poll');
+
+ $poll_interval = intval(DI::config()->get('bluesky', 'poll_interval'));
+ if (!$poll_interval) {
+ $poll_interval = BLUESKY_DEFAULT_POLL_INTERVAL;
+ }
+
+ if ($last) {
+ $next = $last + ($poll_interval * 60);
+ if ($next > time()) {
+ Logger::notice('poll interval not reached');
+ return;
+ }
+ }
+ Logger::notice('cron_start');
+
+ $abandon_days = intval(DI::config()->get('system', 'account_abandon_days'));
+ if ($abandon_days < 1) {
+ $abandon_days = 0;
+ }
+
+ $abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400);
+
+ $pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'bluesky', 'k' => 'import', 'v' => true]);
+ foreach ($pconfigs as $pconfig) {
+ if (empty(bluesky_get_user_did($pconfig['uid']))) {
+ continue;
+ }
+
+ if ($abandon_days != 0) {
+ if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) {
+ Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]);
+ continue;
+ }
+ }
+
+ // Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers
+ bluesky_get_token($pconfig['uid']);
+
+ Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last);
+ Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid'], $last);
+
+ if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) {
+ $feeds = bluesky_get_feeds($pconfig['uid']);
+ foreach ($feeds as $feed) {
+ Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last);
+ }
+ }
+ }
+
+ $last_clean = DI::keyValue()->get('bluesky_last_clean');
+ if (empty($last_clean) || ($last_clean + 86400 < time())) {
+ Logger::notice('Start contact cleanup');
+ $contacts = DBA::select('account-user-view', ['id', 'pid'], ["`network` = ? AND `uid` != ? AND `rel` = ?", Protocol::BLUESKY, 0, Contact::NOTHING]);
+ while ($contact = DBA::fetch($contacts)) {
+ Worker::add(Worker::PRIORITY_LOW, 'MergeContact', $contact['pid'], $contact['id'], 0);
+ }
+ DBA::close($contacts);
+ DI::keyValue()->set('bluesky_last_clean', time());
+ Logger::notice('Contact cleanup done');
+ }
+
+ Logger::notice('cron_end');
+
+ DI::keyValue()->set('bluesky_last_poll', time());
+}
+
+function bluesky_hook_fork(array &$b)
+{
+ if ($b['name'] != 'notifier_normal') {
+ return;
+ }
+
+ $post = $b['data'];
+
+ if (($post['created'] !== $post['edited']) && !$post['deleted']) {
+ DI::logger()->info('Editing is not supported by the addon');
+ $b['execute'] = false;
+ return;
+ }
+
+ if (DI::pConfig()->get($post['uid'], 'bluesky', 'import')) {
+ // Don't post if it isn't a reply to a bluesky post
+ if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) {
+ Logger::notice('No bluesky parent found', ['item' => $post['id']]);
+ $b['execute'] = false;
+ return;
+ }
+ } elseif (!strstr($post['postopts'] ?? '', 'bluesky') || ($post['parent'] != $post['id']) || $post['private']) {
+ DI::logger()->info('Activities are never exported when we don\'t import the bluesky timeline', ['uid' => $post['uid']]);
+ $b['execute'] = false;
+ return;
+ }
+}
+
+function bluesky_post_local(array &$b)
+{
+ if ($b['edit']) {
+ return;
+ }
+
+ if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) {
+ return;
+ }
+
+ if ($b['private'] || $b['parent']) {
+ return;
+ }
+
+ $bluesky_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post'));
+ $bluesky_enable = (($bluesky_post && !empty($_REQUEST['bluesky_enable'])) ? intval($_REQUEST['bluesky_enable']) : 0);
+
+ // if API is used, default to the chosen settings
+ if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default'))) {
+ $bluesky_enable = 1;
+ }
+
+ if (!$bluesky_enable) {
+ return;
+ }
+
+ if (strlen($b['postopts'])) {
+ $b['postopts'] .= ',';
+ }
+
+ $b['postopts'] .= 'bluesky';
+}
+
+function bluesky_send(array &$b)
+{
+ if (($b['created'] !== $b['edited']) && !$b['deleted']) {
+ return;
+ }
+
+ if ($b['gravity'] != Item::GRAVITY_PARENT) {
+ Logger::debug('Got comment', ['item' => $b]);
+
+ if ($b['deleted']) {
+ $uri = bluesky_get_uri_class($b['uri']);
+ if (empty($uri)) {
+ Logger::debug('Not a bluesky post', ['uri' => $b['uri']]);
+ return;
+ }
+ bluesky_delete_post($b['uri'], $b['uid']);
+ return;
+ }
+
+ $root = bluesky_get_uri_class($b['parent-uri']);
+ $parent = bluesky_get_uri_class($b['thr-parent']);
+
+ if (empty($root) || empty($parent)) {
+ Logger::debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]);
+ return;
+ }
+
+ if ($b['gravity'] == Item::GRAVITY_COMMENT) {
+ Logger::debug('Posting comment', ['root' => $root, 'parent' => $parent]);
+ bluesky_create_post($b, $root, $parent);
+ return;
+ } elseif (in_array($b['verb'], [Activity::LIKE, Activity::ANNOUNCE])) {
+ bluesky_create_activity($b, $parent);
+ }
+ return;
+ } elseif ($b['private'] || !strstr($b['postopts'], 'bluesky')) {
+ return;
+ }
+
+ bluesky_create_post($b);
+}
+
+function bluesky_create_activity(array $item, stdClass $parent = null)
+{
+ $uid = $item['uid'];
+ $token = bluesky_get_token($uid);
+ if (empty($token)) {
+ return;
+ }
+
+ $did = bluesky_get_user_did($uid);
+ if (empty($did)) {
+ return;
+ }
+
+ if ($item['verb'] == Activity::LIKE) {
+ $record = [
+ 'subject' => $parent,
+ 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+ '$type' => 'app.bsky.feed.like'
+ ];
+
+ $post = [
+ 'collection' => 'app.bsky.feed.like',
+ 'repo' => $did,
+ 'record' => $record
+ ];
+ } elseif ($item['verb'] == Activity::ANNOUNCE) {
+ $record = [
+ 'subject' => $parent,
+ 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+ '$type' => 'app.bsky.feed.repost'
+ ];
+
+ $post = [
+ 'collection' => 'app.bsky.feed.repost',
+ 'repo' => $did,
+ 'record' => $record
+ ];
+ }
+
+ $activity = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post);
+ if (empty($activity)) {
+ return;
+ }
+ Logger::debug('Activity done', ['return' => $activity]);
+ $uri = bluesky_get_uri($activity);
+ Item::update(['extid' => $uri], ['id' => $item['id']]);
+ Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $activity]);
+}
+
+function bluesky_create_post(array $item, stdClass $root = null, stdClass $parent = null)
+{
+ $uid = $item['uid'];
+ $token = bluesky_get_token($uid);
+ if (empty($token)) {
+ return;
+ }
+
+ // Try to fetch the language from the post itself
+ if (!empty($item['language'])) {
+ $language = array_key_first(json_decode($item['language'], true));
+ } else {
+ $language = '';
+ }
+
+ $item['body'] = Post\Media::removeFromBody($item['body']);
+
+ foreach (Post\Media::getByURIId($item['uri-id'], [Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::ACTIVITY]) as $media) {
+ if (strpos($item['body'], $media['url']) === false) {
+ $item['body'] .= "\n[url]" . $media['url'] . "[/url]\n";
+ }
+ }
+
+ if (!empty($item['quote-uri-id'])) {
+ $quote = Post::selectFirstPost(['uri', 'plink'], ['uri-id' => $item['quote-uri-id']]);
+ if (!empty($quote)) {
+ if ((strpos($item['body'], $quote['plink'] ?: $quote['uri']) === false) && (strpos($item['body'], $quote['uri']) === false)) {
+ $item['body'] .= "\n[url]" . ($quote['plink'] ?: $quote['uri']) . "[/url]\n";
+ }
+ }
+ }
+
+ $urls = bluesky_get_urls($item['body']);
+ $item['body'] = $urls['body'];
+
+ $msg = Plaintext::getPost($item, 300, false, BBCode::BLUESKY);
+ foreach ($msg['parts'] as $key => $part) {
+
+ $facets = bluesky_get_facets($part, $urls['urls']);
+
+ $record = [
+ 'text' => $facets['body'],
+ '$type' => 'app.bsky.feed.post',
+ 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
+ ];
+
+ if (!empty($language)) {
+ $record['langs'] = [$language];
+ }
+
+ if (!empty($facets['facets'])) {
+ $record['facets'] = $facets['facets'];
+ }
+
+ if (!empty($root)) {
+ $record['reply'] = ['root' => $root, 'parent' => $parent];
+ }
+
+ if ($key == count($msg['parts']) - 1) {
+ $record = bluesky_add_embed($uid, $msg, $record);
+ if (empty($record)) {
+ if (Worker::getRetrial() < 3) {
+ Worker::defer();
+ }
+ return;
+ }
+ }
+
+ $post = [
+ 'collection' => 'app.bsky.feed.post',
+ 'repo' => bluesky_get_user_did($uid),
+ 'record' => $record
+ ];
+
+ $parent = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post);
+ if (empty($parent)) {
+ if ($part == 0) {
+ Worker::defer();
+ }
+ return;
+ }
+ Logger::debug('Posting done', ['return' => $parent]);
+ if (empty($root)) {
+ $root = $parent;
+ }
+ if (($key == 0) && ($item['gravity'] != Item::GRAVITY_PARENT)) {
+ $uri = bluesky_get_uri($parent);
+ Item::update(['extid' => $uri], ['id' => $item['id']]);
+ Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $uri]);
+ }
+ }
+}
+
+function bluesky_get_urls(string $body): array
+{
+ // Remove all hashtag and mention links
+ $body = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $body);
+
+ $body = BBCode::expandVideoLinks($body);
+ $urls = [];
+
+ // Search for hash tags
+ if (preg_match_all("/#\[url\=(https?:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $text = '#' . $match[2];
+ $urls[strpos($body, $match[0])] = ['tag' => $match[2], 'text' => $text, 'hash' => $text];
+ $body = str_replace($match[0], $text, $body);
+ }
+ }
+
+ // Search for pure links
+ if (preg_match_all("/\[url\](https?:.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $text = Strings::getStyledURL($match[1]);
+ $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text));
+ $urls[strpos($body, $match[0])] = ['url' => $match[1], 'text' => $text, 'hash' => $hash];
+ $body = str_replace($match[0], $hash, $body);
+ }
+ }
+
+ // Search for links with descriptions
+ if (preg_match_all("/\[url\=(https?:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ if ($match[1] == $match[2]) {
+ $text = Strings::getStyledURL($match[1]);
+ } else {
+ $text = $match[2];
+ }
+ if (mb_strlen($text) < 100) {
+ $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text));
+ $urls[strpos($body, $match[0])] = ['url' => $match[1], 'text' => $text, 'hash' => $hash];
+ $body = str_replace($match[0], $hash, $body);
+ } else {
+ $text = Strings::getStyledURL($match[1]);
+ $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text));
+ $urls[strpos($body, $match[0])] = ['url' => $match[1], 'text' => $text, 'hash' => $hash];
+ $body = str_replace($match[0], $text . ' ' . $hash, $body);
+ }
+ }
+ }
+
+ asort($urls);
+
+ return ['body' => $body, 'urls' => $urls];
+}
+
+function bluesky_get_hash_for_url(string $text, int $linklength): string
+{
+ if ($linklength <= 10) {
+ return '|' . hash('crc32', $text) . '|';
+ }
+ return substr('|' . hash('crc32', $text) . base64_encode($text), 0, $linklength - 2) . '|';
+}
+
+function bluesky_get_facets(string $body, array $urls): array
+{
+ $facets = [];
+
+ foreach ($urls as $url) {
+ $pos = strpos($body, $url['hash']);
+ if ($pos === false) {
+ continue;
+ }
+ if ($pos > 0) {
+ $prefix = substr($body, 0, $pos);
+ } else {
+ $prefix = '';
+ }
+
+ $body = $prefix . $url['text'] . substr($body, $pos + strlen($url['hash']));
+
+ $facet = new stdClass;
+ $facet->index = new stdClass;
+ $facet->index->byteEnd = $pos + strlen($url['text']);
+ $facet->index->byteStart = $pos;
+
+ $feature = new stdClass;
+
+ $type = '$type';
+ if (!empty($url['tag'])) {
+ $feature->tag = $url['tag'];
+ $feature->$type = 'app.bsky.richtext.facet#tag';
+ } elseif (!empty($url['url'])) {
+ $feature->uri = $url['url'];
+ $feature->$type = 'app.bsky.richtext.facet#link';
+ } else {
+ continue;
+ }
+
+ $facet->features = [$feature];
+ $facets[] = $facet;
+ }
+
+ return ['facets' => $facets, 'body' => $body];
+}
+
+function bluesky_add_embed(int $uid, array $msg, array $record): array
+{
+ if (($msg['type'] != 'link') && !empty($msg['images'])) {
+ $images = [];
+ foreach ($msg['images'] as $image) {
+ if (count($images) == 4) {
+ continue;
+ }
+ $photo = Photo::selectFirst([], ['id' => $image['id']]);
+ $blob = bluesky_upload_blob($uid, $photo);
+ if (empty($blob)) {
+ return [];
+ }
+ $images[] = ['alt' => $image['description'] ?? '', 'image' => $blob];
+ }
+ if (!empty($images)) {
+ $record['embed'] = ['$type' => 'app.bsky.embed.images', 'images' => $images];
+ }
+ } elseif ($msg['type'] == 'link') {
+ $record['embed'] = [
+ '$type' => 'app.bsky.embed.external',
+ 'external' => [
+ 'uri' => $msg['url'],
+ 'title' => $msg['title'] ?? '',
+ 'description' => $msg['description'] ?? '',
+ ]
+ ];
+ if (!empty($msg['image'])) {
+ $photo = Photo::createPhotoForExternalResource($msg['image']);
+ $blob = bluesky_upload_blob($uid, $photo);
+ if (!empty($blob)) {
+ $record['embed']['external']['thumb'] = $blob;
+ }
+ }
+ }
+ return $record;
+}
+
+function bluesky_upload_blob(int $uid, array $photo): ?stdClass
+{
+ $retrial = Worker::getRetrial();
+ $content = Photo::getImageForPhoto($photo);
+
+ $picture = new Image($content, $photo['type'], $photo['filename']);
+ $height = $picture->getHeight();
+ $width = $picture->getWidth();
+ $size = strlen($content);
+
+ $picture = Photo::resizeToFileSize($picture, BLUESKY_IMAGE_SIZE[$retrial]);
+ $new_height = $picture->getHeight();
+ $new_width = $picture->getWidth();
+ $content = $picture->asString();
+ $new_size = strlen($content);
+
+ Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
+
+ $data = bluesky_post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
+ if (empty($data)) {
+ Logger::info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
+ return null;
+ }
+
+ Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
+ return $data->blob;
+}
+
+function bluesky_delete_post(string $uri, int $uid)
+{
+ $parts = bluesky_get_uri_parts($uri);
+ if (empty($parts)) {
+ Logger::debug('No uri delected', ['uri' => $uri]);
+ return;
+ }
+ bluesky_xrpc_post($uid, 'com.atproto.repo.deleteRecord', $parts);
+ Logger::debug('Deleted', ['parts' => $parts]);
+}
+
+function bluesky_fetch_timeline(int $uid, int $last_poll)
+{
+ $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline');
+ if (empty($data)) {
+ return;
+ }
+
+ if (empty($data->feed)) {
+ return;
+ }
+
+ foreach (array_reverse($data->feed) as $entry) {
+ bluesky_process_post($entry->post, $uid, $uid, Item::PR_NONE, 0, 0, $last_poll);
+ if (!empty($entry->reason)) {
+ bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid);
+ }
+ }
+
+ // @todo Support paging
+ // [cursor] => 1684670516000::bafyreidq3ilwslmlx72jf5vrk367xcc63s6lrhzlyup2bi3zwcvso6w2vi
+}
+
+function bluesky_process_reason(stdClass $reason, string $uri, int $uid)
+{
+ $type = '$type';
+ if ($reason->$type != 'app.bsky.feed.defs#reasonRepost') {
+ return;
+ }
+
+ $contact = bluesky_get_contact($reason->by, $uid, $uid);
+
+ $item = [
+ 'network' => Protocol::BLUESKY,
+ 'uid' => $uid,
+ 'wall' => false,
+ 'uri' => $reason->by->did . '/app.bsky.feed.repost/' . $reason->indexedAt,
+ 'private' => Item::UNLISTED,
+ 'verb' => Activity::POST,
+ 'contact-id' => $contact['id'],
+ 'author-name' => $contact['name'],
+ 'author-link' => $contact['url'],
+ 'author-avatar' => $contact['avatar'],
+ 'verb' => Activity::ANNOUNCE,
+ 'body' => Activity::ANNOUNCE,
+ 'gravity' => Item::GRAVITY_ACTIVITY,
+ 'object-type' => Activity\ObjectType::NOTE,
+ 'thr-parent' => $uri,
+ ];
+
+ if (Post::exists(['uri' => $item['uri'], 'uid' => $uid])) {
+ return;
+ }
+
+ $item['guid'] = Item::guidFromUri($item['uri'], $contact['alias']);
+ $item['owner-name'] = $item['author-name'];
+ $item['owner-link'] = $item['author-link'];
+ $item['owner-avatar'] = $item['author-avatar'];
+ if (Item::insert($item)) {
+ $cdata = Contact::getPublicAndUserContactID($contact['id'], $uid);
+ Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $cdata['public']], ['uri' => $uri, 'uid' => $uid]);
+ }
+}
+
+function bluesky_fetch_notifications(int $uid, int $last_poll)
+{
+ $data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications');
+ if (empty($data->notifications)) {
+ return;
+ }
+ foreach ($data->notifications as $notification) {
+ $uri = bluesky_get_uri($notification);
+ if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) {
+ Logger::debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]);
+ continue;
+ }
+ Logger::debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]);
+ switch ($notification->reason) {
+ case 'like':
+ $item = bluesky_get_header($notification, $uri, $uid, $uid);
+ $item['gravity'] = Item::GRAVITY_ACTIVITY;
+ $item['body'] = $item['verb'] = Activity::LIKE;
+ $item['thr-parent'] = bluesky_get_uri($notification->record->subject);
+ $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll);
+ if (!empty($item['thr-parent'])) {
+ $data = Item::insert($item);
+ Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]);
+ } else {
+ Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]);
+ }
+ break;
+
+ case 'repost':
+ $item = bluesky_get_header($notification, $uri, $uid, $uid);
+ $item['gravity'] = Item::GRAVITY_ACTIVITY;
+ $item['body'] = $item['verb'] = Activity::ANNOUNCE;
+ $item['thr-parent'] = bluesky_get_uri($notification->record->subject);
+ $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll);
+ if (!empty($item['thr-parent'])) {
+ $data = Item::insert($item);
+ Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]);
+ } else {
+ Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]);
+ }
+ break;
+
+ case 'follow':
+ $contact = bluesky_get_contact($notification->author, $uid, $uid);
+ Logger::debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]);
+ break;
+
+ case 'mention':
+ $contact = bluesky_get_contact($notification->author, 0, $uid);
+ $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_TO, $contact['id'], 0, $last_poll);
+ Logger::debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]);
+ break;
+
+ case 'reply':
+ $contact = bluesky_get_contact($notification->author, 0, $uid);
+ $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_COMMENT, $contact['id'], 0, $last_poll);
+ Logger::debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]);
+ break;
+
+ case 'quote':
+ $contact = bluesky_get_contact($notification->author, 0, $uid);
+ $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_PUSHED, $contact['id'], 0, $last_poll);
+ Logger::debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]);
+ break;
+
+ default:
+ Logger::notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]);
+ break;
+ }
+ }
+}
+
+function bluesky_fetch_feed(int $uid, string $feed, int $last_poll)
+{
+ $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeed', ['feed' => $feed]);
+ if (empty($data)) {
+ return;
+ }
+
+ if (empty($data->feed)) {
+ return;
+ }
+
+ $feeddata = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeedGenerator', ['feed' => $feed]);
+ if (!empty($feeddata)) {
+ $feedurl = $feeddata->view->uri;
+ $feedname = $feeddata->view->displayName;
+ } else {
+ $feedurl = $feed;
+ $feedname = $feed;
+ }
+
+ foreach (array_reverse($data->feed) as $entry) {
+ $contact = bluesky_get_contact($entry->post->author, 0, $uid);
+ $languages = $entry->post->record->langs ?? [];
+
+ if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) {
+ Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]);
+ continue;
+ }
+ $uri_id = bluesky_process_post($entry->post, $uid, $uid, Item::PR_TAG, 0, 0, $last_poll);
+ if (!empty($uri_id)) {
+ $stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl);
+ Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]);
+ } else {
+ Logger::notice('Post not found', ['entry' => $entry]);
+ }
+ if (!empty($entry->reason)) {
+ bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid);
+ }
+ }
+}
+
+function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll): int
+{
+ $uri = bluesky_get_uri($post);
+
+ if ($uri_id = bluesky_fetch_uri_id($uri, $uid)) {
+ return $uri_id;
+ }
+
+ if (empty($post->record)) {
+ Logger::debug('Invalid post', ['uri' => $uri]);
+ return 0;
+ }
+
+ Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']);
+
+ $item = bluesky_get_header($post, $uri, $uid, $fetch_uid);
+ $item = bluesky_get_content($item, $post->record, $uri, $uid, $fetch_uid, $level, $last_poll);
+ if (empty($item)) {
+ return 0;
+ }
+
+ if (!empty($post->embed)) {
+ $item = bluesky_add_media($post->embed, $item, $uid, $level, $last_poll);
+ }
+
+ $item['restrictions'] = bluesky_get_restrictions_for_user($post, $item, $post_reason);
+
+ if (empty($item['post-reason'])) {
+ $item['post-reason'] = $post_reason;
+ }
+
+ if ($causer != 0) {
+ $item['causer-id'] = $causer;
+ }
+
+ Item::insert($item);
+ return bluesky_fetch_uri_id($uri, $uid);
+}
+
+function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid): array
+{
+ $parts = bluesky_get_uri_parts($uri);
+ if (empty($post->author) || empty($post->cid) || empty($parts->rkey)) {
+ return [];
+ }
+ $contact = bluesky_get_contact($post->author, $uid, $fetch_uid);
+ $item = [
+ 'network' => Protocol::BLUESKY,
+ 'uid' => $uid,
+ 'wall' => false,
+ 'uri' => $uri,
+ 'guid' => $post->cid,
+ 'private' => Item::UNLISTED,
+ 'verb' => Activity::POST,
+ 'contact-id' => $contact['id'],
+ 'author-name' => $contact['name'],
+ 'author-link' => $contact['url'],
+ 'author-avatar' => $contact['avatar'],
+ 'plink' => $contact['alias'] . '/post/' . $parts->rkey,
+ 'source' => json_encode($post),
+ ];
+
+ $item['uri-id'] = ItemURI::getIdByURI($uri);
+ $item['owner-name'] = $item['author-name'];
+ $item['owner-link'] = $item['author-link'];
+ $item['owner-avatar'] = $item['author-avatar'];
+
+ if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND])) {
+ $item['post-reason'] = Item::PR_FOLLOWER;
+ }
+
+ if (!empty($post->labels)) {
+ foreach ($post->labels as $label) {
+ // Only flag posts as sensitive based on labels that had been provided by the author.
+ // When "ver" is set to "1" it was flagged by some automated process.
+ if (empty($label->ver)) {
+ $item['sensitive'] = true;
+ Logger::debug('Sensitive content', ['uri-id' => $item['uri-id'], 'label' => $label]);
+ }
+ }
+ }
+
+ return $item;
+}
+
+function bluesky_get_restrictions_for_user(stdClass $post, array $item, int $post_reason): ?int
+{
+ if (!empty($post->viewer->replyDisabled)) {
+ return Item::CANT_REPLY;
+ }
+
+ if (empty($post->threadgate)) {
+ return null;
+ }
+
+ if (!isset($post->threadgate->record->allow)) {
+ return null;
+ }
+
+ if ($item['uid'] == 0) {
+ return Item::CANT_REPLY;
+ }
+
+ $restrict = true;
+ $type = '$type';
+ foreach ($post->threadgate->record->allow as $allow) {
+ switch ($allow->$type) {
+ case 'app.bsky.feed.threadgate#followingRule':
+ // Only followers can reply.
+ if (Contact::isFollower($item['author-id'], $item['uid'])) {
+ $restrict = false;
+ }
+ break;
+ case 'app.bsky.feed.threadgate#mentionRule':
+ // Only mentioned accounts can reply.
+ if ($post_reason == Item::PR_TO) {
+ $restrict = false;
+ }
+ break;
+ case 'app.bsky.feed.threadgate#listRule';
+ // Only accounts in the provided list can reply. We don't support this at the moment.
+ break;
+ }
+ }
+
+ return $restrict ? Item::CANT_REPLY : null;
+}
+
+function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $fetch_uid, int $level, int $last_poll): array
+{
+ if (empty($item)) {
+ return [];
+ }
+
+ if (!empty($record->reply)) {
+ $item['parent-uri'] = bluesky_get_uri($record->reply->root);
+ if ($item['parent-uri'] != $uri) {
+ $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll);
+ if (empty($item['parent-uri'])) {
+ return [];
+ }
+ }
+
+ $item['thr-parent'] = bluesky_get_uri($record->reply->parent);
+ if (!in_array($item['thr-parent'], [$uri, $item['parent-uri']])) {
+ $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll, $item['parent-uri']);
+ if (empty($item['thr-parent'])) {
+ return [];
+ }
+ }
+ }
+
+ $item['body'] = bluesky_get_text($record, $item['uri-id']);
+ $item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL);
+ $item['transmitted-languages'] = $record->langs ?? [];
+
+ if (($last_poll != 0) && strtotime($item['created']) > $last_poll) {
+ $item['received'] = $item['created'];
+ }
+
+ return $item;
+}
+
+function bluesky_get_text(stdClass $record, int $uri_id): string
+{
+ $text = $record->text ?? '';
+
+ if (empty($record->facets)) {
+ return $text;
+ }
+
+ $facets = [];
+ foreach ($record->facets as $facet) {
+ $facets[$facet->index->byteStart] = $facet;
+ }
+ krsort($facets);
+
+ foreach ($facets as $facet) {
+ $prefix = substr($text, 0, $facet->index->byteStart);
+ $linktext = substr($text, $facet->index->byteStart, $facet->index->byteEnd - $facet->index->byteStart);
+ $suffix = substr($text, $facet->index->byteEnd);
+
+ $url = '';
+ $type = '$type';
+ foreach ($facet->features as $feature) {
+
+ switch ($feature->$type) {
+ case 'app.bsky.richtext.facet#link':
+ $url = $feature->uri;
+ break;
+
+ case 'app.bsky.richtext.facet#mention':
+ $contact = Contact::getByURL($feature->did, null, ['id']);
+ if (!empty($contact['id'])) {
+ $url = DI::baseUrl() . '/contact/' . $contact['id'];
+ if (substr($linktext, 0, 1) == '@') {
+ $prefix .= '@';
+ $linktext = substr($linktext, 1);
+ }
+ }
+ break;
+
+ case 'app.bsky.richtext.facet#tag';
+ Tag::store($uri_id, Tag::HASHTAG, $feature->tag);
+ $url = DI::baseUrl() . '/search?tag=' . urlencode($feature->tag);
+ $linktext = '#' . $feature->tag;
+ break;
+
+ default:
+ Logger::notice('Unhandled feature type', ['type' => $feature->$type, 'feature' => $feature, 'record' => $record]);
+ break;
+ }
+ }
+ if (!empty($url)) {
+ $text = $prefix . '[url=' . $url . ']' . $linktext . '[/url]' . $suffix;
+ }
+ }
+ return $text;
+}
+
+function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $level, int $last_poll): array
+{
+ $type = '$type';
+ switch ($embed->$type) {
+ case 'app.bsky.embed.images#view':
+ foreach ($embed->images as $image) {
+ $media = [
+ 'uri-id' => $item['uri-id'],
+ 'type' => Post\Media::IMAGE,
+ 'url' => $image->fullsize,
+ 'preview' => $image->thumb,
+ 'description' => $image->alt,
+ ];
+ Post\Media::insert($media);
+ }
+ break;
+
+ case 'app.bsky.embed.external#view':
+ $media = [
+ 'uri-id' => $item['uri-id'],
+ 'type' => Post\Media::HTML,
+ 'url' => $embed->external->uri,
+ 'name' => $embed->external->title,
+ 'description' => $embed->external->description,
+ ];
+ Post\Media::insert($media);
+ break;
+
+ case 'app.bsky.embed.record#view':
+ $original_uri = $uri = bluesky_get_uri($embed->record);
+ $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll);
+ if ($uri) {
+ $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]);
+ $uri_id = $shared['uri-id'] ?? 0;
+ }
+ if (!empty($uri_id)) {
+ $item['quote-uri-id'] = $uri_id;
+ } else {
+ Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]);
+ }
+ break;
+
+ case 'app.bsky.embed.recordWithMedia#view':
+ bluesky_add_media($embed->media, $item, $fetch_uid, $level, $last_poll);
+ $original_uri = $uri = bluesky_get_uri($embed->record->record);
+ $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll);
+ if ($uri) {
+ $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]);
+ $uri_id = $shared['uri-id'] ?? 0;
+ }
+ if (!empty($uri_id)) {
+ $item['quote-uri-id'] = $uri_id;
+ } else {
+ Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]);
+ }
+ break;
+
+ default:
+ Logger::notice('Unhandled embed type', ['uri-id' => $item['uri-id'], 'type' => $embed->$type, 'embed' => $embed]);
+ break;
+ }
+ return $item;
+}
+
+function bluesky_get_uri(stdClass $post): string
+{
+ if (empty($post->cid)) {
+ Logger::info('Invalid URI', ['post' => $post]);
+ return '';
+ }
+ return $post->uri . ':' . $post->cid;
+}
+
+function bluesky_get_uri_class(string $uri): ?stdClass
+{
+ if (empty($uri)) {
+ return null;
+ }
+
+ $elements = explode(':', $uri);
+ if (empty($elements) || ($elements[0] != 'at')) {
+ $post = Post::selectFirstPost(['extid'], ['uri' => $uri]);
+ return bluesky_get_uri_class($post['extid'] ?? '');
+ }
+
+ $class = new stdClass;
+
+ $class->cid = array_pop($elements);
+ $class->uri = implode(':', $elements);
+
+ if ((substr_count($class->uri, '/') == 2) && (substr_count($class->cid, '/') == 2)) {
+ $class->uri .= ':' . $class->cid;
+ $class->cid = '';
+ }
+
+ return $class;
+}
+
+function bluesky_get_uri_parts(string $uri): ?stdClass
+{
+ $class = bluesky_get_uri_class($uri);
+ if (empty($class)) {
+ return null;
+ }
+
+ $parts = explode('/', substr($class->uri, 5));
+
+ $class = new stdClass;
+
+ $class->repo = $parts[0];
+ $class->collection = $parts[1];
+ $class->rkey = $parts[2];
+
+ return $class;
+}
+
+function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = ''): string
+{
+ $fetched_uri = bluesky_fetch_post($uri, $uid);
+ if (!empty($fetched_uri)) {
+ return $fetched_uri;
+ }
+
+ if (++$level > 100) {
+ Logger::info('Recursion level too deep', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]);
+ // When the level is too deep we will fallback to the parent uri.
+ // Allthough the threading won't be correct, we at least had stored all posts and won't try again
+ return $fallback;
+ }
+
+ $class = bluesky_get_uri_class($uri);
+ if (empty($class)) {
+ return $fallback;
+ }
+
+ $fetch_uri = $class->uri;
+
+ Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
+ $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.feed.getPostThread', ['uri' => $fetch_uri]);
+ if (empty($data)) {
+ Logger::info('Thread was not fetched', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]);
+ return $fallback;
+ }
+
+ Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
+
+ if ($causer != 0) {
+ $cdata = Contact::getPublicAndUserContactID($causer, $uid);
+ $causer = $cdata['public'] ?? 0;
+ }
+
+ return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll);
+}
+
+function bluesky_fetch_post(string $uri, int $uid): string
+{
+ if (Post::exists(['uri' => $uri, 'uid' => [$uid, 0]])) {
+ Logger::debug('Post exists', ['uri' => $uri]);
+ return $uri;
+ }
+
+ $reply = Post::selectFirst(['uri'], ['extid' => $uri, 'uid' => [$uid, 0]]);
+ if (!empty($reply['uri'])) {
+ Logger::debug('Post with extid exists', ['uri' => $uri]);
+ return $reply['uri'];
+ }
+ return '';
+}
+
+function bluesky_fetch_uri_id(string $uri, int $uid): string
+{
+ $reply = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$uid, 0]]);
+ if (!empty($reply['uri-id'])) {
+ Logger::debug('Post with extid exists', ['uri' => $uri]);
+ return $reply['uri-id'];
+ }
+ $reply = Post::selectFirst(['uri-id'], ['extid' => $uri, 'uid' => [$uid, 0]]);
+ if (!empty($reply['uri-id'])) {
+ Logger::debug('Post with extid exists', ['uri' => $uri]);
+ return $reply['uri-id'];
+ }
+ return 0;
+}
+
+function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll): string
+{
+ if (empty($thread->post)) {
+ Logger::info('Invalid post', ['post' => $thread]);
+ return '';
+ }
+ $uri = bluesky_get_uri($thread->post);
+
+ $fetched_uri = bluesky_fetch_post($uri, $uid);
+ if (empty($fetched_uri)) {
+ $uri_id = bluesky_process_post($thread->post, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll);
+ if ($uri_id) {
+ Logger::debug('Post has been processed and stored', ['uri-id' => $uri_id, 'uri' => $uri]);
+ return $uri;
+ } else {
+ Logger::info('Post has not not been stored', ['uri' => $uri]);
+ return '';
+ }
+ } else {
+ Logger::debug('Post exists', ['uri' => $uri]);
+ $uri = $fetched_uri;
+ }
+
+ foreach ($thread->replies ?? [] as $reply) {
+ $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll);
+ Logger::debug('Reply has been processed', ['uri' => $uri, 'reply' => $reply_uri]);
+ }
+
+ return $uri;
+}
+
+function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array
+{
+ $condition = ['network' => Protocol::BLUESKY, 'uid' => 0, 'url' => $author->did];
+ $contact = Contact::selectFirst(['id', 'updated'], $condition);
+
+ $update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours');
+
+ $public_fields = $fields = bluesky_get_contact_fields($author, $uid, $fetch_uid, $update);
+
+ $public_fields['uid'] = 0;
+ $public_fields['rel'] = Contact::NOTHING;
+
+ if (empty($contact)) {
+ $cid = Contact::insert($public_fields);
+ } else {
+ $cid = $contact['id'];
+ Contact::update($public_fields, ['id' => $cid], true);
+ }
+
+ if ($uid != 0) {
+ $condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'url' => $author->did];
+
+ $contact = Contact::selectFirst(['id', 'rel', 'uid'], $condition);
+ if (!isset($fields['rel']) && isset($contact['rel'])) {
+ $fields['rel'] = $contact['rel'];
+ } elseif (!isset($fields['rel'])) {
+ $fields['rel'] = Contact::NOTHING;
+ }
+ }
+
+ if (($uid != 0) && ($fields['rel'] != Contact::NOTHING)) {
+ if (empty($contact)) {
+ $cid = Contact::insert($fields);
+ } else {
+ $cid = $contact['id'];
+ Contact::update($fields, ['id' => $cid], true);
+ }
+ Logger::debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]);
+ } else {
+ Logger::debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]);
+ }
+ if (!empty($author->avatar)) {
+ Contact::updateAvatar($cid, $author->avatar);
+ }
+
+ return Contact::getById($cid);
+}
+
+function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, bool $update): array
+{
+ $nick = $author->handle ?? $author->did;
+ $name = $author->displayName ?? $nick;
+ $fields = [
+ 'uid' => $uid,
+ 'network' => Protocol::BLUESKY,
+ 'priority' => 1,
+ 'writable' => true,
+ 'blocked' => false,
+ 'readonly' => false,
+ 'pending' => false,
+ 'url' => $author->did,
+ 'nurl' => $author->did,
+ 'alias' => BLUESKY_WEB . '/profile/' . $nick,
+ 'name' => $name ?: $nick,
+ 'nick' => $nick,
+ 'addr' => $nick,
+ ];
+
+ if (!$update) {
+ Logger::debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]);
+ return $fields;
+ }
+
+ $fields['baseurl'] = bluesky_get_pds($author->did);
+ if (!empty($fields['baseurl'])) {
+ GServer::check($fields['baseurl'], Protocol::BLUESKY);
+ $fields['gsid'] = GServer::getID($fields['baseurl'], true);
+ }
+
+ $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]);
+ if (empty($data)) {
+ Logger::debug('Error fetching contact fields', ['uid' => $uid, 'url' => $fields['url']]);
+ return $fields;
+ }
+
+ $fields['updated'] = DateTimeFormat::utcNow(DateTimeFormat::MYSQL);
+
+ if (!empty($data->description)) {
+ $fields['about'] = HTML::toBBCode($data->description);
+ }
+
+ if (!empty($data->banner)) {
+ $fields['header'] = $data->banner;
+ }
+
+ if (!empty($data->viewer)) {
+ if (!empty($data->viewer->following) && !empty($data->viewer->followedBy)) {
+ $fields['rel'] = Contact::FRIEND;
+ } elseif (!empty($data->viewer->following) && empty($data->viewer->followedBy)) {
+ $fields['rel'] = Contact::SHARING;
+ } elseif (empty($data->viewer->following) && !empty($data->viewer->followedBy)) {
+ $fields['rel'] = Contact::FOLLOWER;
+ } else {
+ $fields['rel'] = Contact::NOTHING;
+ }
+ }
+
+ Logger::debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]);
+ return $fields;
+}
+
+function bluesky_get_feeds(int $uid): array
+{
+ $type = '$type';
+ $preferences = bluesky_get_preferences($uid);
+ foreach ($preferences->preferences as $preference) {
+ if ($preference->$type == 'app.bsky.actor.defs#savedFeedsPref') {
+ return $preference->pinned ?? [];
+ }
+ }
+ return [];
+}
+
+function bluesky_get_preferences(int $uid): stdClass
+{
+ $cachekey = 'bluesky:preferences:' . $uid;
+ $data = DI::cache()->get($cachekey);
+ if (!is_null($data)) {
+ return $data;
+ }
+
+ $data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences');
+
+ DI::cache()->set($cachekey, $data, Duration::HOUR);
+ return $data;
+}
+
+function bluesky_get_did_by_wellknown(string $handle): string
+{
+ $curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did');
+ if ($curlResult->isSuccess() && substr($curlResult->getBodyString(), 0, 4) == 'did:') {
+ $did = $curlResult->getBodyString();
+ if (!bluesky_valid_did($did, $handle)) {
+ Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
+ return '';
+ }
+ Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]);
+ return $did;
+ }
+ return '';
+}
+
+function bluesky_get_did_by_dns(string $handle): string
+{
+ $records = @dns_get_record('_atproto.' . $handle . '.', DNS_TXT);
+ if (empty($records)) {
+ return '';
+ }
+ foreach ($records as $record) {
+ if (!empty($record['txt']) && substr($record['txt'], 0, 4) == 'did=') {
+ $did = substr($record['txt'], 4);
+ if (!bluesky_valid_did($did, $handle)) {
+ Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
+ return '';
+ }
+ Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
+ return $did;
+ }
+ }
+ return '';
+}
+
+function bluesky_get_did(string $handle): string
+{
+ // Deactivated at the moment, since it isn't reliable by now
+ //$did = bluesky_get_did_by_dns($handle);
+ //if ($did != '') {
+ // return $did;
+ //}
+
+ //$did = bluesky_get_did_by_wellknown($handle);
+ //if ($did != '') {
+ // return $did;
+ //}
+
+ $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
+ if (empty($data) || empty($data->did)) {
+ return '';
+ }
+ Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]);
+ return $data->did;
+}
+
+function bluesky_get_user_did(int $uid, bool $refresh = false): ?string
+{
+ if (!$refresh) {
+ $did = DI::pConfig()->get($uid, 'bluesky', 'did');
+ if (!empty($did)) {
+ return $did;
+ }
+ }
+
+ $handle = DI::pConfig()->get($uid, 'bluesky', 'handle');
+ if (empty($handle)) {
+ return null;
+ }
+
+ $did = bluesky_get_did($handle);
+ if (empty($did)) {
+ return null;
+ }
+
+ Logger::debug('Got DID for user', ['uid' => $uid, 'handle' => $handle, 'did' => $did]);
+ DI::pConfig()->set($uid, 'bluesky', 'did', $did);
+ return $did;
+}
+
+function bluesky_get_user_pds(int $uid): ?string
+{
+ $pds = DI::pConfig()->get($uid, 'bluesky', 'pds');
+ if (!empty($pds)) {
+ return $pds;
+ }
+
+ $did = bluesky_get_user_did($uid);
+ if (empty($did)) {
+ return null;
+ }
+
+ $pds = bluesky_get_pds($did);
+ if (empty($pds)) {
+ return null;
+ }
+
+ DI::pConfig()->set($uid, 'bluesky', 'pds', $pds);
+ return $pds;
+}
+
+function bluesky_get_pds(string $did): ?string
+{
+ $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
+ if (empty($data) || empty($data->service)) {
+ return null;
+ }
+
+ foreach ($data->service as $service) {
+ if (($service->id == '#atproto_pds') && ($service->type == 'AtprotoPersonalDataServer') && !empty($service->serviceEndpoint)) {
+ return $service->serviceEndpoint;
+ }
+ }
+
+ return null;
+}
+
+function bluesky_valid_did(string $did, string $handle): bool
+{
+ $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
+ if (empty($data) || empty($data->alsoKnownAs)) {
+ return false;
+ }
+
+ return in_array('at://' . $handle, $data->alsoKnownAs);
+}
+
+function bluesky_get_token(int $uid): string
+{
+ $token = DI::pConfig()->get($uid, 'bluesky', 'access_token');
+ $created = DI::pConfig()->get($uid, 'bluesky', 'token_created');
+ if (empty($token)) {
+ return '';
+ }
+
+ if ($created + 300 < time()) {
+ return bluesky_refresh_token($uid);
+ }
+ return $token;
+}
+
+function bluesky_refresh_token(int $uid): string
+{
+ $token = DI::pConfig()->get($uid, 'bluesky', 'refresh_token');
+
+ $data = bluesky_post($uid, '/xrpc/com.atproto.server.refreshSession', '', ['Authorization' => ['Bearer ' . $token]]);
+ if (empty($data)) {
+ return '';
+ }
+
+ Logger::debug('Refreshed token', ['return' => $data]);
+ DI::pConfig()->set($uid, 'bluesky', 'access_token', $data->accessJwt);
+ DI::pConfig()->set($uid, 'bluesky', 'refresh_token', $data->refreshJwt);
+ DI::pConfig()->set($uid, 'bluesky', 'token_created', time());
+ return $data->accessJwt;
+}
+
+function bluesky_create_token(int $uid, string $password): string
+{
+ $did = bluesky_get_user_did($uid);
+ if (empty($did)) {
+ return '';
+ }
+
+ $data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']);
+ if (empty($data)) {
+ DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL);
+ return '';
+ }
+
+ Logger::debug('Created token', ['return' => $data]);
+ DI::pConfig()->set($uid, 'bluesky', 'access_token', $data->accessJwt);
+ DI::pConfig()->set($uid, 'bluesky', 'refresh_token', $data->refreshJwt);
+ DI::pConfig()->set($uid, 'bluesky', 'token_created', time());
+ DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_OK);
+ return $data->accessJwt;
+}
+
+function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass
+{
+ return bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
+}
+
+function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass
+{
+ $pds = bluesky_get_user_pds($uid);
+ if (empty($pds)) {
+ return null;
+ }
+
+ try {
+ $curlResult = DI::httpClient()->post($pds . $url, $params, $headers);
+ } catch (\Exception $e) {
+ Logger::notice('Exception on post', ['exception' => $e]);
+ DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL);
+ return null;
+ }
+
+ if (!$curlResult->isSuccess()) {
+ Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
+ DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL);
+ return null;
+ }
+
+ DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS);
+ return json_decode($curlResult->getBodyString());
+}
+
+function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdClass
+{
+ if (!empty($parameters)) {
+ $url .= '?' . http_build_query($parameters);
+ }
+
+ $pds = bluesky_get_user_pds($uid);
+ if (empty($pds)) {
+ return null;
+ }
+
+ $data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]);
+ DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS);
+ return $data;
+}
+
+function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass
+{
+ try {
+ $curlResult = DI::httpClient()->get($url, $accept_content, $opts);
+ } catch (\Exception $e) {
+ Logger::notice('Exception on get', ['url' => $url, 'exception' => $e]);
+ return null;
+ }
+
+ if (!$curlResult->isSuccess()) {
+ Logger::notice('API Error', ['url' => $url, 'error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
+ return null;
+ }
+
+ return json_decode($curlResult->getBodyString());
+}
diff --git a/bluesky/bluesky_feed.php b/bluesky/bluesky_feed.php
new file mode 100644
index 00000000..c9a54223
--- /dev/null
+++ b/bluesky/bluesky_feed.php
@@ -0,0 +1,16 @@
+ $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]);
+ bluesky_fetch_feed($argv[1], $argv[2], $argv[3]);
+ Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]);
+}
diff --git a/bluesky/bluesky_notifications.php b/bluesky/bluesky_notifications.php
new file mode 100644
index 00000000..ad35dfe0
--- /dev/null
+++ b/bluesky/bluesky_notifications.php
@@ -0,0 +1,16 @@
+ $argv[1], 'last_poll' => $argv[2]]);
+ bluesky_fetch_notifications($argv[1], $argv[2]);
+ Logger::notice('importing notifications - done', ['user' => $argv[1], 'last_poll' => $argv[2]]);
+}
diff --git a/bluesky/bluesky_timeline.php b/bluesky/bluesky_timeline.php
new file mode 100644
index 00000000..22ef2224
--- /dev/null
+++ b/bluesky/bluesky_timeline.php
@@ -0,0 +1,16 @@
+ $argv[1], 'last_poll' => $argv[2]]);
+ bluesky_fetch_timeline($argv[1], $argv[2]);
+ Logger::notice('importing timeline - done', ['user' => $argv[1], 'last_poll' => $argv[2]]);
+}
diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po
new file mode 100644
index 00000000..9521ab89
--- /dev/null
+++ b/bluesky/lang/C/messages.po
@@ -0,0 +1,147 @@
+# ADDON bluesky
+# Copyright (C)
+# This file is distributed under the same license as the Friendica bluesky addon package.
+#
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2024-03-22 05:31+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: bluesky.php:325
+msgid "Save Settings"
+msgstr ""
+
+#: bluesky.php:326
+msgid "Allow your users to use your hostname for their Bluesky handles"
+msgstr ""
+
+#: bluesky.php:326
+#, php-format
+msgid ""
+"Before enabling this option, you have to setup a wildcard domain "
+"configuration and you have to enable wildcard requests in your webserver "
+"configuration. On Apache this is done by adding \"ServerAlias *.%s\" to your "
+"HTTP configuration. You don't need to change the HTTPS configuration."
+msgstr ""
+
+#: bluesky.php:354
+#, php-format
+msgid "Allow to use %s as your Bluesky handle."
+msgstr ""
+
+#: bluesky.php:354
+#, php-format
+msgid ""
+"When enabled, you can use %s as your Bluesky handle. After you enabled this "
+"option, please go to https://bsky.app/settings and select to change your "
+"handle. Select that you have got your own domain. Then enter %s and select "
+"\"No DNS Panel\". Then select \"Verify Text File\"."
+msgstr ""
+
+#: bluesky.php:361
+msgid "Enable Bluesky Post Addon"
+msgstr ""
+
+#: bluesky.php:362
+msgid "Post to Bluesky by default"
+msgstr ""
+
+#: bluesky.php:363
+msgid "Import the remote timeline"
+msgstr ""
+
+#: bluesky.php:364
+msgid "Import the pinned feeds"
+msgstr ""
+
+#: bluesky.php:364
+msgid ""
+"When activated, Posts will be imported from all the feeds that you pinned in "
+"Bluesky."
+msgstr ""
+
+#: bluesky.php:366
+msgid "Personal Data Server"
+msgstr ""
+
+#: bluesky.php:366
+msgid "The personal data server (PDS) is the system that hosts your profile."
+msgstr ""
+
+#: bluesky.php:367
+msgid "Bluesky handle"
+msgstr ""
+
+#: bluesky.php:368
+msgid "Bluesky DID"
+msgstr ""
+
+#: bluesky.php:368
+msgid ""
+"This is the unique identifier. It will be fetched automatically, when the "
+"handle is entered."
+msgstr ""
+
+#: bluesky.php:369
+msgid "Bluesky app password"
+msgstr ""
+
+#: bluesky.php:369
+msgid ""
+"Please don't add your real password here, but instead create a specific app "
+"password in the Bluesky settings."
+msgstr ""
+
+#: bluesky.php:375
+msgid "Bluesky Import/Export"
+msgstr ""
+
+#: bluesky.php:385
+msgid ""
+"You are not authenticated. Please enter your handle and the app password."
+msgstr ""
+
+#: bluesky.php:405
+msgid ""
+"You are authenticated to Bluesky. For security reasons the password isn't "
+"stored."
+msgstr ""
+
+#: bluesky.php:407
+msgid ""
+"The communication with the personal data server service (PDS) is established."
+msgstr ""
+
+#: bluesky.php:409
+msgid "Communication issues with the personal data server service (PDS)."
+msgstr ""
+
+#: bluesky.php:411
+msgid ""
+"The DID for the provided handle could not be detected. Please check if you "
+"entered the correct handle."
+msgstr ""
+
+#: bluesky.php:413
+msgid "The personal data server service (PDS) could not be detected."
+msgstr ""
+
+#: bluesky.php:415
+msgid ""
+"The authentication with the provided handle and password failed. Please "
+"check if you entered the correct password."
+msgstr ""
+
+#: bluesky.php:484
+msgid "Post to Bluesky"
+msgstr ""
diff --git a/bluesky/lang/de/messages.po b/bluesky/lang/de/messages.po
new file mode 100644
index 00000000..13ea8e96
--- /dev/null
+++ b/bluesky/lang/de/messages.po
@@ -0,0 +1,89 @@
+# ADDON bluesky
+# Copyright (C)
+# This file is distributed under the same license as the Friendica bluesky addon package.
+#
+#
+# Translators:
+# Tobias Diekershoff , 2023
+# haheute , 2023
+# Raroun, 2023
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-05-24 05:52+0000\n"
+"PO-Revision-Date: 2023-05-24 06:02+0000\n"
+"Last-Translator: Raroun, 2023\n"
+"Language-Team: German (https://app.transifex.com/Friendica/teams/12172/de/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: bluesky.php:100
+msgid ""
+"You are authenticated to Bluesky. For security reasons the password isn't "
+"stored."
+msgstr ""
+"Du bist auf Bluesky authentifiziert. Aus Sicherheitsgründen wird das "
+"Passwort nicht gespeichert."
+
+#: bluesky.php:100
+msgid "You are not authenticated. Please enter the app password."
+msgstr ""
+"Du bist derzeit nicht authentifiziert. Bitte gib dein App Passwort ein."
+
+#: bluesky.php:104
+msgid "Enable Bluesky Post Addon"
+msgstr "Bluesky Post Addon aktivieren"
+
+#: bluesky.php:105
+msgid "Post to Bluesky by default"
+msgstr "Standardmäßig auf Bluesky veröffentlichen"
+
+#: bluesky.php:106
+msgid "Import the remote timeline"
+msgstr "Importiere die entfernte Timeline"
+
+#: bluesky.php:107
+msgid "Bluesky host"
+msgstr "Bluesky Host"
+
+#: bluesky.php:108
+msgid "Bluesky handle"
+msgstr "Bluesky Handle"
+
+#: bluesky.php:109
+msgid "Bluesky DID"
+msgstr "Bluesky DID"
+
+#: bluesky.php:109
+msgid ""
+"This is the unique identifier. It will be fetched automatically, when the "
+"handle is entered."
+msgstr ""
+"Sobald das Handle eingegeben ist, wird diese einzigartige Kennung "
+"automatisch abgerufen."
+
+#: bluesky.php:110
+msgid "Bluesky app password"
+msgstr "Bluesky App Passwort"
+
+#: bluesky.php:110
+msgid ""
+"Please don't add your real password here, but instead create a specific app "
+"password in the Bluesky settings."
+msgstr ""
+"Bitte verwende hier nicht dein echtes Passwort, sondern stattdessen ein "
+"speziell für diese App in den Bluesky Einstellungen festgelegtes Passwort."
+
+#: bluesky.php:116
+msgid "Bluesky Import/Export"
+msgstr "Bluesky Import/Export"
+
+#: bluesky.php:167
+msgid "Post to Bluesky"
+msgstr "Auf Bluesky veröffentlichen"
diff --git a/bluesky/lang/de/strings.php b/bluesky/lang/de/strings.php
new file mode 100644
index 00000000..8e3c9421
--- /dev/null
+++ b/bluesky/lang/de/strings.php
@@ -0,0 +1,20 @@
+strings['You are authenticated to Bluesky. For security reasons the password isn\'t stored.'] = 'Du bist auf Bluesky authentifiziert. Aus Sicherheitsgründen wird das Passwort nicht gespeichert.';
+$a->strings['You are not authenticated. Please enter the app password.'] = 'Du bist derzeit nicht authentifiziert. Bitte gib dein App Passwort ein.';
+$a->strings['Enable Bluesky Post Addon'] = 'Bluesky Post Addon aktivieren';
+$a->strings['Post to Bluesky by default'] = 'Standardmäßig auf Bluesky veröffentlichen';
+$a->strings['Import the remote timeline'] = 'Importiere die entfernte Timeline';
+$a->strings['Bluesky host'] = 'Bluesky Host';
+$a->strings['Bluesky handle'] = 'Bluesky Handle';
+$a->strings['Bluesky DID'] = 'Bluesky DID';
+$a->strings['This is the unique identifier. It will be fetched automatically, when the handle is entered.'] = 'Sobald das Handle eingegeben ist, wird diese einzigartige Kennung automatisch abgerufen.';
+$a->strings['Bluesky app password'] = 'Bluesky App Passwort';
+$a->strings['Please don\'t add your real password here, but instead create a specific app password in the Bluesky settings.'] = 'Bitte verwende hier nicht dein echtes Passwort, sondern stattdessen ein speziell für diese App in den Bluesky Einstellungen festgelegtes Passwort.';
+$a->strings['Bluesky Import/Export'] = 'Bluesky Import/Export';
+$a->strings['Post to Bluesky'] = 'Auf Bluesky veröffentlichen';
diff --git a/bluesky/lang/zh-cn/messages.po b/bluesky/lang/zh-cn/messages.po
new file mode 100644
index 00000000..9074ce34
--- /dev/null
+++ b/bluesky/lang/zh-cn/messages.po
@@ -0,0 +1,80 @@
+# ADDON bluesky
+# Copyright (C)
+# This file is distributed under the same license as the Friendica bluesky addon package.
+#
+#
+# Translators:
+# tslmuun, 2023
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-05-24 05:52+0000\n"
+"PO-Revision-Date: 2023-05-24 06:02+0000\n"
+"Last-Translator: tslmuun, 2023\n"
+"Language-Team: Chinese (China) (https://app.transifex.com/Friendica/teams/12172/zh_CN/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_CN\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: bluesky.php:100
+msgid ""
+"You are authenticated to Bluesky. For security reasons the password isn't "
+"stored."
+msgstr "您已通过 Bluesky 的身份验证。 出于安全原因,不存储密码。"
+
+#: bluesky.php:100
+msgid "You are not authenticated. Please enter the app password."
+msgstr "您未通过身份验证。 请输入应用密码。"
+
+#: bluesky.php:104
+msgid "Enable Bluesky Post Addon"
+msgstr "启用Bluesky插件"
+
+#: bluesky.php:105
+msgid "Post to Bluesky by default"
+msgstr "默认发布到Bluesky"
+
+#: bluesky.php:106
+msgid "Import the remote timeline"
+msgstr "导入远程时间线"
+
+#: bluesky.php:107
+msgid "Bluesky host"
+msgstr "Bluesky地址"
+
+#: bluesky.php:108
+msgid "Bluesky handle"
+msgstr "Bluesky handle"
+
+#: bluesky.php:109
+msgid "Bluesky DID"
+msgstr "Bluesky DID"
+
+#: bluesky.php:109
+msgid ""
+"This is the unique identifier. It will be fetched automatically, when the "
+"handle is entered."
+msgstr "这是唯一标识符。 输入句柄时,它将自动获取。"
+
+#: bluesky.php:110
+msgid "Bluesky app password"
+msgstr "Bluesky 应用密码"
+
+#: bluesky.php:110
+msgid ""
+"Please don't add your real password here, but instead create a specific app "
+"password in the Bluesky settings."
+msgstr "请不要在此处填写您的真实密码,而是在 Bluesky 设置中创建一个特定的应用程序密码。"
+
+#: bluesky.php:116
+msgid "Bluesky Import/Export"
+msgstr "Bluesky 导入/导出"
+
+#: bluesky.php:167
+msgid "Post to Bluesky"
+msgstr "发布到Bluesky"
diff --git a/bluesky/lang/zh-cn/strings.php b/bluesky/lang/zh-cn/strings.php
new file mode 100644
index 00000000..9c71d974
--- /dev/null
+++ b/bluesky/lang/zh-cn/strings.php
@@ -0,0 +1,20 @@
+strings['You are authenticated to Bluesky. For security reasons the password isn\'t stored.'] = '您已通过 Bluesky 的身份验证。 出于安全原因,不存储密码。';
+$a->strings['You are not authenticated. Please enter the app password.'] = '您未通过身份验证。 请输入应用密码。';
+$a->strings['Enable Bluesky Post Addon'] = '启用Bluesky插件';
+$a->strings['Post to Bluesky by default'] = '默认发布到Bluesky';
+$a->strings['Import the remote timeline'] = '导入远程时间线';
+$a->strings['Bluesky host'] = 'Bluesky地址';
+$a->strings['Bluesky handle'] = 'Bluesky handle';
+$a->strings['Bluesky DID'] = 'Bluesky DID';
+$a->strings['This is the unique identifier. It will be fetched automatically, when the handle is entered.'] = '这是唯一标识符。 输入句柄时,它将自动获取。';
+$a->strings['Bluesky app password'] = 'Bluesky 应用密码';
+$a->strings['Please don\'t add your real password here, but instead create a specific app password in the Bluesky settings.'] = '请不要在此处填写您的真实密码,而是在 Bluesky 设置中创建一个特定的应用程序密码。';
+$a->strings['Bluesky Import/Export'] = 'Bluesky 导入/导出';
+$a->strings['Post to Bluesky'] = '发布到Bluesky';
diff --git a/bluesky/templates/admin.tpl b/bluesky/templates/admin.tpl
new file mode 100644
index 00000000..7b752a88
--- /dev/null
+++ b/bluesky/templates/admin.tpl
@@ -0,0 +1,2 @@
+{{include file="field_checkbox.tpl" field=$friendica_handles}}
+
diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl
new file mode 100644
index 00000000..3ebea827
--- /dev/null
+++ b/bluesky/templates/connector_settings.tpl
@@ -0,0 +1,12 @@
+{{$status}}
+{{include file="field_checkbox.tpl" field=$enable}}
+{{include file="field_checkbox.tpl" field=$bydefault}}
+{{include file="field_checkbox.tpl" field=$import}}
+{{include file="field_checkbox.tpl" field=$import_feeds}}
+{{if $custom_handle}}
+ {{include file="field_checkbox.tpl" field=$custom_handle}}
+{{/if}}
+{{include file="field_input.tpl" field=$pds}}
+{{include file="field_input.tpl" field=$handle}}
+{{include file="field_input.tpl" field=$did}}
+{{include file="field_input.tpl" field=$password}}
\ No newline at end of file
diff --git a/catavatar/lang/fr/messages.po b/catavatar/lang/fr/messages.po
index f4c4dd0d..64e98568 100644
--- a/catavatar/lang/fr/messages.po
+++ b/catavatar/lang/fr/messages.po
@@ -5,8 +5,7 @@
#
# Translators:
# Vladimir Núñez , 2019
-# Walter Bulbazor, 2021
-# Hypolite Petovan , 2022
+# Florent C., 2023
#
#, fuzzy
msgid ""
@@ -15,8 +14,8 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
"PO-Revision-Date: 2018-04-07 05:23+0000\n"
-"Last-Translator: Hypolite Petovan , 2022\n"
-"Language-Team: French (https://www.transifex.com/Friendica/teams/12172/fr/)\n"
+"Last-Translator: Florent C., 2023\n"
+"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -25,7 +24,7 @@ msgstr ""
#: catavatar.php:48
msgid "Set default profile avatar or randomize the cat."
-msgstr "Mettre l'avatar par défaut ou tirer au sort le Chat."
+msgstr "Mettre l'avatar par défaut ou tirer au sort le chat."
#: catavatar.php:53
msgid "Cat Avatar Settings"
@@ -33,15 +32,15 @@ msgstr "Paramètres de Chat avatar"
#: catavatar.php:56
msgid "Use Cat as Avatar"
-msgstr "Utiliser Chat comme avatar"
+msgstr "Utiliser ce Chat"
#: catavatar.php:57
msgid "Another random Cat!"
-msgstr "Un autre chat aléatoire !"
+msgstr "Un autre Chat aléatoire !"
#: catavatar.php:58
msgid "Reset to email Cat"
-msgstr "Réinitialiser à Chat courriel"
+msgstr "Revenir au Chat par défaut"
#: catavatar.php:77
msgid "The cat hadn't found itself."
diff --git a/catavatar/lang/fr/strings.php b/catavatar/lang/fr/strings.php
index 5d8a10a3..b68b9d45 100644
--- a/catavatar/lang/fr/strings.php
+++ b/catavatar/lang/fr/strings.php
@@ -5,11 +5,11 @@ function string_plural_select_fr($n){
$n = intval($n);
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
}}
-$a->strings['Set default profile avatar or randomize the cat.'] = 'Mettre l\'avatar par défaut ou tirer au sort le Chat.';
+$a->strings['Set default profile avatar or randomize the cat.'] = 'Mettre l\'avatar par défaut ou tirer au sort le chat.';
$a->strings['Cat Avatar Settings'] = 'Paramètres de Chat avatar';
-$a->strings['Use Cat as Avatar'] = 'Utiliser Chat comme avatar';
-$a->strings['Another random Cat!'] = 'Un autre chat aléatoire !';
-$a->strings['Reset to email Cat'] = 'Réinitialiser à Chat courriel';
+$a->strings['Use Cat as Avatar'] = 'Utiliser ce Chat';
+$a->strings['Another random Cat!'] = 'Un autre Chat aléatoire !';
+$a->strings['Reset to email Cat'] = 'Revenir au Chat par défaut';
$a->strings['The cat hadn\'t found itself.'] = 'Le Chat ne s\'y est pas retrouvé';
$a->strings['There was an error, the cat ran away.'] = 'Il y a eu une erreur et le chat s\'est enfui';
$a->strings['Profile Photos'] = 'Photos de profil';
diff --git a/circle_text/group_text.php b/circle_text/group_text.php
new file mode 100644
index 00000000..b52cbc19
--- /dev/null
+++ b/circle_text/group_text.php
@@ -0,0 +1,64 @@
+
+ */
+
+use Friendica\Core\Hook;
+use Friendica\Core\Renderer;
+use Friendica\DI;
+
+function circle_text_install()
+{
+ Hook::register('addon_settings', __FILE__, 'circle_text_settings');
+ Hook::register('addon_settings_post', __FILE__, 'circle_text_settings_post');
+}
+
+/**
+ *
+ * Callback from the settings post function.
+ * $post contains the $_POST array.
+ * We will make sure we've got a valid user account
+ * and if so set our configuration setting for this person.
+ *
+ */
+
+function circle_text_settings_post(array $post)
+{
+ if (!DI::userSession()->getLocalUserId() || empty($post['circle_text-submit'])) {
+ return;
+ }
+
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'circle_edit_image_limit', intval($post['circle_text']));
+}
+
+
+/**
+ *
+ * Called from the Addon Setting form.
+ * Add our own settings info to the page.
+ *
+ */
+
+function circle_text_settings(array &$data)
+{
+ if (!DI::userSession()->getLocalUserId()) {
+ return;
+ }
+
+ $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'circle_edit_image_limit') ??
+ DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'groupedit_image_limit');
+
+ $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/circle_text/');
+ $html = Renderer::replaceMacros($t, [
+ '$enabled' => ['circle_text', DI::l10n()->t('Use a text only (non-image) circle selector in the "circle edit" menu'), $enabled],
+ ]);
+
+ $data = [
+ 'addon' => 'circle_text',
+ 'title' => DI::l10n()->t('Circle Text'),
+ 'html' => $html,
+ ];
+}
diff --git a/circle_text/lang/C/messages.po b/circle_text/lang/C/messages.po
new file mode 100644
index 00000000..27c0e60e
--- /dev/null
+++ b/circle_text/lang/C/messages.po
@@ -0,0 +1,26 @@
+# ADDON circle_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica circle_text addon package.
+#
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-06-03 15:48-0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: group_text.php:56
+msgid "Use a text only (non-image) circle selector in the \"circle edit\" menu"
+msgstr ""
+
+#: group_text.php:61
+msgid "Circle Text"
+msgstr ""
diff --git a/circle_text/lang/ar/messages.po b/circle_text/lang/ar/messages.po
new file mode 100644
index 00000000..cfe9bb63
--- /dev/null
+++ b/circle_text/lang/ar/messages.po
@@ -0,0 +1,32 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Farida Khalaf , 2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2021-02-21 02:59+0000\n"
+"Last-Translator: Farida Khalaf \n"
+"Language-Team: Arabic (http://www.transifex.com/Friendica/friendica/language/ar/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ar\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#: group_text.php:62
+msgid "Group Text"
+msgstr "نص المجموعة:"
+
+#: group_text.php:64
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "استخدم محدد نصي للمجموعة فقط (غير مصور) في قائمة \"تعديل المجموعة\""
+
+#: group_text.php:70
+msgid "Save Settings"
+msgstr "حفظ الإعدادات"
diff --git a/circle_text/lang/ar/strings.php b/circle_text/lang/ar/strings.php
new file mode 100644
index 00000000..20e8496a
--- /dev/null
+++ b/circle_text/lang/ar/strings.php
@@ -0,0 +1,10 @@
+=3 && $n%100<=10) { return 3; } else if ($n%100>=11 && $n%100<=99) { return 4; } else { return 5; }
+}}
+$a->strings['Group Text'] = 'نص المجموعة:';
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'استخدم محدد نصي للمجموعة فقط (غير مصور) في قائمة "تعديل المجموعة"';
+$a->strings['Save Settings'] = 'حفظ الإعدادات';
diff --git a/circle_text/lang/ca/messages.po b/circle_text/lang/ca/messages.po
new file mode 100644
index 00000000..7081c0d7
--- /dev/null
+++ b/circle_text/lang/ca/messages.po
@@ -0,0 +1,36 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Joan Bar , 2019
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2019-10-14 00:45+0000\n"
+"Last-Translator: Joan Bar \n"
+"Language-Team: Catalan (http://www.transifex.com/Friendica/friendica/language/ca/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ca\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:46
+msgid "Group Text settings updated."
+msgstr "La configuració del text del grup s'ha actualitzat."
+
+#: group_text.php:76
+msgid "Group Text"
+msgstr "Missatge del grup"
+
+#: group_text.php:78
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Utilitzeu un selector de grup de només text (que no sigui una imatge) al menú 'Edita grup'"
+
+#: group_text.php:84
+msgid "Submit"
+msgstr "sotmetre's"
diff --git a/circle_text/lang/ca/strings.php b/circle_text/lang/ca/strings.php
new file mode 100644
index 00000000..b28db322
--- /dev/null
+++ b/circle_text/lang/ca/strings.php
@@ -0,0 +1,11 @@
+strings['Group Text settings updated.'] = 'La configuració del text del grup s\'ha actualitzat.';
+$a->strings['Group Text'] = 'Missatge del grup';
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Utilitzeu un selector de grup de només text (que no sigui una imatge) al menú \'Edita grup\'';
+$a->strings['Submit'] = 'sotmetre\'s';
diff --git a/circle_text/lang/cs/messages.po b/circle_text/lang/cs/messages.po
new file mode 100644
index 00000000..8b56b630
--- /dev/null
+++ b/circle_text/lang/cs/messages.po
@@ -0,0 +1,37 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Aditoo, 2018
+# michal_s , 2014-2015
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2018-09-12 09:47+0000\n"
+"Last-Translator: Aditoo\n"
+"Language-Team: Czech (http://www.transifex.com/Friendica/friendica/language/cs/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: cs\n"
+"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
+
+#: group_text.php:46
+msgid "Group Text settings updated."
+msgstr "Nastavení Group Text aktualizována."
+
+#: group_text.php:76
+msgid "Group Text"
+msgstr "Skupinový text"
+
+#: group_text.php:78
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Použijte pouze textový (bezobrázkový) výběr skupiny v menu úpravy skupin."
+
+#: group_text.php:84
+msgid "Submit"
+msgstr "Odeslat"
diff --git a/circle_text/lang/cs/strings.php b/circle_text/lang/cs/strings.php
new file mode 100644
index 00000000..510453af
--- /dev/null
+++ b/circle_text/lang/cs/strings.php
@@ -0,0 +1,11 @@
+= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; }
+}}
+$a->strings['Group Text settings updated.'] = 'Nastavení Group Text aktualizována.';
+$a->strings['Group Text'] = 'Skupinový text';
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Použijte pouze textový (bezobrázkový) výběr skupiny v menu úpravy skupin.';
+$a->strings['Submit'] = 'Odeslat';
diff --git a/circle_text/lang/da-dk/messages.po b/circle_text/lang/da-dk/messages.po
new file mode 100644
index 00000000..9f1fbefa
--- /dev/null
+++ b/circle_text/lang/da-dk/messages.po
@@ -0,0 +1,28 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Anton , 2022
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-11-21 19:14-0500\n"
+"PO-Revision-Date: 2014-06-23 08:35+0000\n"
+"Last-Translator: Anton , 2022\n"
+"Language-Team: Danish (Denmark) (http://www.transifex.com/Friendica/friendica/language/da_DK/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: da_DK\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:58
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Brug en kun-tekst (intet billede) gruppevælger i grupperedigeringsmenuen"
+
+#: group_text.php:63
+msgid "Group Text"
+msgstr "Gruppebesked"
diff --git a/circle_text/lang/da-dk/strings.php b/circle_text/lang/da-dk/strings.php
new file mode 100644
index 00000000..4306b769
--- /dev/null
+++ b/circle_text/lang/da-dk/strings.php
@@ -0,0 +1,9 @@
+strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Brug en kun-tekst (intet billede) gruppevælger i grupperedigeringsmenuen';
+$a->strings['Group Text'] = 'Gruppebesked';
diff --git a/circle_text/lang/de/messages.po b/circle_text/lang/de/messages.po
new file mode 100644
index 00000000..e4e5d782
--- /dev/null
+++ b/circle_text/lang/de/messages.po
@@ -0,0 +1,31 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Andreas H., 2014
+# Tobias Diekershoff , 2014
+# Tobias Diekershoff , 2021
+# Ulf Rompe , 2019
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-11-21 19:14-0500\n"
+"PO-Revision-Date: 2014-06-23 08:35+0000\n"
+"Last-Translator: Tobias Diekershoff , 2021\n"
+"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:58
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Beim Bearbeiten von Gruppen Text statt Bilder anzeigen"
+
+#: group_text.php:63
+msgid "Group Text"
+msgstr "Gruppen als Text"
diff --git a/circle_text/lang/de/strings.php b/circle_text/lang/de/strings.php
new file mode 100644
index 00000000..7a75b54d
--- /dev/null
+++ b/circle_text/lang/de/strings.php
@@ -0,0 +1,9 @@
+strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Beim Bearbeiten von Gruppen Text statt Bilder anzeigen';
+$a->strings['Group Text'] = 'Gruppen als Text';
diff --git a/circle_text/lang/eo/strings.php b/circle_text/lang/eo/strings.php
new file mode 100644
index 00000000..4e220fb0
--- /dev/null
+++ b/circle_text/lang/eo/strings.php
@@ -0,0 +1,5 @@
+strings["Group Text"] = "";
+$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = "";
+$a->strings["Submit"] = "Sendi";
diff --git a/circle_text/lang/es/messages.po b/circle_text/lang/es/messages.po
new file mode 100644
index 00000000..5d6d4107
--- /dev/null
+++ b/circle_text/lang/es/messages.po
@@ -0,0 +1,33 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Albert, 2016
+# Senex Petrovic , 2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2021-04-01 09:56+0000\n"
+"Last-Translator: Senex Petrovic \n"
+"Language-Team: Spanish (http://www.transifex.com/Friendica/friendica/language/es/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: es\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:62
+msgid "Group Text"
+msgstr "Grupo de Texto"
+
+#: group_text.php:64
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Utilice sólo el selector de grupo de texto (no imagen) en el menú \"edición de grupo\""
+
+#: group_text.php:70
+msgid "Save Settings"
+msgstr "Guardar Ajustes"
diff --git a/circle_text/lang/es/strings.php b/circle_text/lang/es/strings.php
new file mode 100644
index 00000000..632130fd
--- /dev/null
+++ b/circle_text/lang/es/strings.php
@@ -0,0 +1,10 @@
+strings['Group Text'] = 'Grupo de Texto';
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Utilice sólo el selector de grupo de texto (no imagen) en el menú "edición de grupo"';
+$a->strings['Save Settings'] = 'Guardar Ajustes';
diff --git a/circle_text/lang/fi-fi/messages.po b/circle_text/lang/fi-fi/messages.po
new file mode 100644
index 00000000..2e3782fd
--- /dev/null
+++ b/circle_text/lang/fi-fi/messages.po
@@ -0,0 +1,37 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Kris, 2018
+# Kris, 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2018-04-08 15:51+0000\n"
+"Last-Translator: Kris\n"
+"Language-Team: Finnish (Finland) (http://www.transifex.com/Friendica/friendica/language/fi_FI/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fi_FI\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:46
+msgid "Group Text settings updated."
+msgstr "Group Text -asetukset päivitetty."
+
+#: group_text.php:76
+msgid "Group Text"
+msgstr "Group Text"
+
+#: group_text.php:78
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr ""
+
+#: group_text.php:84
+msgid "Submit"
+msgstr "Lähetä"
diff --git a/circle_text/lang/fi-fi/strings.php b/circle_text/lang/fi-fi/strings.php
new file mode 100644
index 00000000..5bcd0ddc
--- /dev/null
+++ b/circle_text/lang/fi-fi/strings.php
@@ -0,0 +1,10 @@
+strings['Group Text settings updated.'] = 'Group Text -asetukset päivitetty.';
+$a->strings['Group Text'] = 'Group Text';
+$a->strings['Submit'] = 'Lähetä';
diff --git a/circle_text/lang/fr/messages.po b/circle_text/lang/fr/messages.po
new file mode 100644
index 00000000..c076d697
--- /dev/null
+++ b/circle_text/lang/fr/messages.po
@@ -0,0 +1,29 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# bob lebonche , 2021
+# Hypolite Petovan , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-11-21 19:14-0500\n"
+"PO-Revision-Date: 2014-06-23 08:35+0000\n"
+"Last-Translator: bob lebonche , 2021\n"
+"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
+
+#: group_text.php:58
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Utiliser uniquement un groupe de texte (pas d'image) dans le menu \"groupedit\""
+
+#: group_text.php:63
+msgid "Group Text"
+msgstr "Groupe de texte"
diff --git a/circle_text/lang/fr/strings.php b/circle_text/lang/fr/strings.php
new file mode 100644
index 00000000..657d7657
--- /dev/null
+++ b/circle_text/lang/fr/strings.php
@@ -0,0 +1,9 @@
+strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Utiliser uniquement un groupe de texte (pas d\'image) dans le menu "groupedit"';
+$a->strings['Group Text'] = 'Groupe de texte';
diff --git a/circle_text/lang/hu/messages.po b/circle_text/lang/hu/messages.po
new file mode 100644
index 00000000..2c4f19c9
--- /dev/null
+++ b/circle_text/lang/hu/messages.po
@@ -0,0 +1,28 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Balázs Úr, 2020-2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-11-21 19:14-0500\n"
+"PO-Revision-Date: 2014-06-23 08:35+0000\n"
+"Last-Translator: Balázs Úr, 2020-2021\n"
+"Language-Team: Hungarian (http://www.transifex.com/Friendica/friendica/language/hu/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hu\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:58
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Csak szöveges (kép nélküli) csoportválasztó használata a „csoportszerkesztés” menüben"
+
+#: group_text.php:63
+msgid "Group Text"
+msgstr "Csoportszöveg"
diff --git a/circle_text/lang/hu/strings.php b/circle_text/lang/hu/strings.php
new file mode 100644
index 00000000..ac72f9e0
--- /dev/null
+++ b/circle_text/lang/hu/strings.php
@@ -0,0 +1,9 @@
+strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Csak szöveges (kép nélküli) csoportválasztó használata a „csoportszerkesztés” menüben';
+$a->strings['Group Text'] = 'Csoportszöveg';
diff --git a/circle_text/lang/is/strings.php b/circle_text/lang/is/strings.php
new file mode 100644
index 00000000..d331b2f9
--- /dev/null
+++ b/circle_text/lang/is/strings.php
@@ -0,0 +1,5 @@
+strings["Group Text"] = "";
+$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = "";
+$a->strings["Submit"] = "Senda inn";
diff --git a/circle_text/lang/it/messages.po b/circle_text/lang/it/messages.po
new file mode 100644
index 00000000..daab3fb6
--- /dev/null
+++ b/circle_text/lang/it/messages.po
@@ -0,0 +1,33 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# fabrixxm , 2014-2015
+# Sylke Vicious , 2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2021-02-16 12:48+0000\n"
+"Last-Translator: Sylke Vicious \n"
+"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: it\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:62
+msgid "Group Text"
+msgstr "Editor Gruppi Testuale"
+
+#: group_text.php:64
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Usa un selettore testuale (senza immagini) nella pagina \"modifica gruppo\""
+
+#: group_text.php:70
+msgid "Save Settings"
+msgstr "Salva Impostazioni"
diff --git a/circle_text/lang/it/strings.php b/circle_text/lang/it/strings.php
new file mode 100644
index 00000000..e52683e9
--- /dev/null
+++ b/circle_text/lang/it/strings.php
@@ -0,0 +1,10 @@
+strings['Group Text'] = 'Editor Gruppi Testuale';
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Usa un selettore testuale (senza immagini) nella pagina "modifica gruppo"';
+$a->strings['Save Settings'] = 'Salva Impostazioni';
diff --git a/circle_text/lang/nb-no/strings.php b/circle_text/lang/nb-no/strings.php
new file mode 100644
index 00000000..cd9bebd4
--- /dev/null
+++ b/circle_text/lang/nb-no/strings.php
@@ -0,0 +1,5 @@
+strings["Group Text"] = "";
+$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = "";
+$a->strings["Submit"] = "Lagre";
diff --git a/circle_text/lang/nl/messages.po b/circle_text/lang/nl/messages.po
new file mode 100644
index 00000000..56b5aae0
--- /dev/null
+++ b/circle_text/lang/nl/messages.po
@@ -0,0 +1,36 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Jeroen De Meerleer , 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2018-08-24 13:48+0000\n"
+"Last-Translator: Jeroen De Meerleer \n"
+"Language-Team: Dutch (http://www.transifex.com/Friendica/friendica/language/nl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:46
+msgid "Group Text settings updated."
+msgstr "Groupsberichten instellingen opgeslagen"
+
+#: group_text.php:76
+msgid "Group Text"
+msgstr "Groepsbericht"
+
+#: group_text.php:78
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr ""
+
+#: group_text.php:84
+msgid "Submit"
+msgstr ""
diff --git a/circle_text/lang/nl/strings.php b/circle_text/lang/nl/strings.php
new file mode 100644
index 00000000..ba3cb3ec
--- /dev/null
+++ b/circle_text/lang/nl/strings.php
@@ -0,0 +1,9 @@
+strings['Group Text settings updated.'] = 'Groupsberichten instellingen opgeslagen';
+$a->strings['Group Text'] = 'Groepsbericht';
diff --git a/circle_text/lang/pl/messages.po b/circle_text/lang/pl/messages.po
new file mode 100644
index 00000000..a1d6a3c8
--- /dev/null
+++ b/circle_text/lang/pl/messages.po
@@ -0,0 +1,28 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Waldemar Stoczkowski, 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-11-21 19:14-0500\n"
+"PO-Revision-Date: 2014-06-23 08:35+0000\n"
+"Last-Translator: Waldemar Stoczkowski, 2018\n"
+"Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pl\n"
+"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
+
+#: group_text.php:58
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Użyj tylko tekst (bez obrazu) selektor grupy w menu \"Edycja grupy\""
+
+#: group_text.php:63
+msgid "Group Text"
+msgstr "Grupuj tekst"
diff --git a/circle_text/lang/pl/strings.php b/circle_text/lang/pl/strings.php
new file mode 100644
index 00000000..96157c99
--- /dev/null
+++ b/circle_text/lang/pl/strings.php
@@ -0,0 +1,9 @@
+=2 && $n%10<=4) && ($n%100<12 || $n%100>14)) { return 1; } else if ($n!=1 && ($n%10>=0 && $n%10<=1) || ($n%10>=5 && $n%10<=9) || ($n%100>=12 && $n%100<=14)) { return 2; } else { return 3; }
+}}
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Użyj tylko tekst (bez obrazu) selektor grupy w menu "Edycja grupy"';
+$a->strings['Group Text'] = 'Grupuj tekst';
diff --git a/circle_text/lang/pt-br/strings.php b/circle_text/lang/pt-br/strings.php
new file mode 100644
index 00000000..4579a5b1
--- /dev/null
+++ b/circle_text/lang/pt-br/strings.php
@@ -0,0 +1,5 @@
+strings["Group Text"] = "";
+$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = "";
+$a->strings["Submit"] = "Enviar";
diff --git a/circle_text/lang/ro/messages.po b/circle_text/lang/ro/messages.po
new file mode 100644
index 00000000..c912f113
--- /dev/null
+++ b/circle_text/lang/ro/messages.po
@@ -0,0 +1,36 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Doru DEACONU , 2014
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2014-11-27 14:15+0000\n"
+"Last-Translator: Doru DEACONU \n"
+"Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/friendica/language/ro_RO/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ro_RO\n"
+"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
+
+#: group_text.php:46
+msgid "Group Text settings updated."
+msgstr "Configurările Text Grup, au fost actualizate."
+
+#: group_text.php:76
+msgid "Group Text"
+msgstr "Text Grup"
+
+#: group_text.php:78
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Folosiți în meniul \"editare grup\" un selector de grup strict textual (fără-imagine)"
+
+#: group_text.php:84
+msgid "Submit"
+msgstr "Trimite"
diff --git a/circle_text/lang/ro/strings.php b/circle_text/lang/ro/strings.php
new file mode 100644
index 00000000..892ffc68
--- /dev/null
+++ b/circle_text/lang/ro/strings.php
@@ -0,0 +1,11 @@
+19)||(($n%100==0)&&($n!=0)))) { return 2; } else { return 1; }
+}}
+$a->strings['Group Text settings updated.'] = 'Configurările Text Grup, au fost actualizate.';
+$a->strings['Group Text'] = 'Text Grup';
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Folosiți în meniul "editare grup" un selector de grup strict textual (fără-imagine)';
+$a->strings['Submit'] = 'Trimite';
diff --git a/circle_text/lang/ru/messages.po b/circle_text/lang/ru/messages.po
new file mode 100644
index 00000000..05a25367
--- /dev/null
+++ b/circle_text/lang/ru/messages.po
@@ -0,0 +1,36 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Stanislav N. , 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2017-04-08 17:26+0000\n"
+"Last-Translator: Stanislav N. \n"
+"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ru\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
+
+#: group_text.php:46
+msgid "Group Text settings updated."
+msgstr "Настройки Group Text обновлены."
+
+#: group_text.php:76
+msgid "Group Text"
+msgstr "Group Text"
+
+#: group_text.php:78
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr "Используйте текстовый (не изображение) селектор группы в режиме редактирования группы"
+
+#: group_text.php:84
+msgid "Submit"
+msgstr "Добавить"
diff --git a/circle_text/lang/ru/strings.php b/circle_text/lang/ru/strings.php
new file mode 100644
index 00000000..0f74e7ca
--- /dev/null
+++ b/circle_text/lang/ru/strings.php
@@ -0,0 +1,11 @@
+=2 && $n%10<=4 && ($n%100<12 || $n%100>14)) { return 1; } else if ($n%10==0 || ($n%10>=5 && $n%10<=9) || ($n%100>=11 && $n%100<=14)) { return 2; } else { return 3; }
+}}
+$a->strings['Group Text settings updated.'] = 'Настройки Group Text обновлены.';
+$a->strings['Group Text'] = 'Group Text';
+$a->strings['Use a text only (non-image) group selector in the "group edit" menu'] = 'Используйте текстовый (не изображение) селектор группы в режиме редактирования группы';
+$a->strings['Submit'] = 'Добавить';
diff --git a/circle_text/lang/sv/messages.po b/circle_text/lang/sv/messages.po
new file mode 100644
index 00000000..8ddc1806
--- /dev/null
+++ b/circle_text/lang/sv/messages.po
@@ -0,0 +1,28 @@
+# ADDON group_text
+# Copyright (C)
+# This file is distributed under the same license as the Friendica group_text addon package.
+#
+#
+# Translators:
+# Kristoffer Grundström , 2022
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-11-21 19:14-0500\n"
+"PO-Revision-Date: 2022-01-16 00:35+0000\n"
+"Last-Translator: Kristoffer Grundström \n"
+"Language-Team: Swedish (http://www.transifex.com/Friendica/friendica/language/sv/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sv\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: group_text.php:58
+msgid "Use a text only (non-image) group selector in the \"group edit\" menu"
+msgstr ""
+
+#: group_text.php:63
+msgid "Group Text"
+msgstr "Grupptext"
diff --git a/circle_text/lang/sv/strings.php b/circle_text/lang/sv/strings.php
new file mode 100644
index 00000000..5d5e98db
--- /dev/null
+++ b/circle_text/lang/sv/strings.php
@@ -0,0 +1,8 @@
+strings['Group Text'] = 'Grupptext';
diff --git a/circle_text/lang/zh-cn/strings.php b/circle_text/lang/zh-cn/strings.php
new file mode 100644
index 00000000..a7b37bf2
--- /dev/null
+++ b/circle_text/lang/zh-cn/strings.php
@@ -0,0 +1,6 @@
+strings["Group Text settings updated."] = "组正文设置更新了。";
+$a->strings["Group Text"] = "组正文";
+$a->strings["Use a text only (non-image) group selector in the \"group edit\" menu"] = "用光正文(无图片)组选择器在「组编辑」单";
+$a->strings["Submit"] = "提交";
diff --git a/circle_text/templates/settings.tpl b/circle_text/templates/settings.tpl
new file mode 100644
index 00000000..2f3f4ce7
--- /dev/null
+++ b/circle_text/templates/settings.tpl
@@ -0,0 +1 @@
+{{include file="field_checkbox.tpl" field=$enabled}}
diff --git a/cld/README.md b/cld/README.md
new file mode 100644
index 00000000..933dbcee
--- /dev/null
+++ b/cld/README.md
@@ -0,0 +1,85 @@
+Compact Language Detector
+===
+CLD2 is an advanced language dectection library with a high reliability.
+
+This addon depends on the CLD PHP module which is not included in any Linux distribution.
+It needs to be built and installed by hand, which is not totally straightforward.
+
+Prerequisite
+---
+To be able to build the extension, you need the CLD module and the files for the PHP module development.
+On Debian you install the packages php-dev, libcld2-dev and libcld2-0.
+Make sure to have installed the correct PHP version.
+Means: When you have got both PHP 8.0 and 8.2 on your system, you have to install php8.0-dev as well.
+
+Installation
+---
+The original PHP extension is https://github.com/fntlnz/cld2-php-ext.
+However, it doesn't support PHP8.
+So https://github.com/hiteule/cld2-php-ext/tree/support-php8 has to be used.
+
+Download the source code:
+```
+wget https://github.com/hiteule/cld2-php-ext/archive/refs/heads/support-php8.zip
+```
+
+Unzip it:
+```
+unzip support-php8.zip
+```
+
+Change into the folder:
+```
+cd cld2-php-ext-support-php8/
+```
+
+Configure for the PHP Api version:
+```
+phpize
+```
+(if you have got several PHP versions on your system, execute the command with the version that you run Friendica with, e.g. `phpize8.0`)
+
+Create the Makefile:
+```
+./configure --with-cld2=/usr/include/cld2
+```
+
+Have a look at the line `checking for PHP includes`.
+When the output (for example `/usr/include/php/20220829` doesn't match the API version that you got from `phpize`, then you have to change all the version codes in your `Makefile` afterwards)
+
+Create the module:
+```
+make -j
+```
+
+Install it:
+```
+sudo make install
+```
+
+Change to the folder with the available modules. When you use PHP 8.2 on Debian it is:
+```
+cd /etc/php/8.2/mods-available
+```
+
+Create the file `cld2.ini` with this content:
+```
+; configuration for php cld2 module
+; priority=20
+extension=cld2.so
+```
+
+Enable the module for all versions and all sapi:
+```
+phpenmod -v ALL -s ALL cld2
+```
+
+Then restart the apache or fpm (or whatever you use) to load the changed configuration.
+
+Call `/admin/phpinfo` on your webserver.
+You then see the PHP Info.
+Search for "cld2".
+The module is installed, when you find it here.
+**Only proceed when the module is installed**
+
+Now you can enable the addon.
\ No newline at end of file
diff --git a/cld/cld.php b/cld/cld.php
new file mode 100644
index 00000000..5ca4c932
--- /dev/null
+++ b/cld/cld.php
@@ -0,0 +1,71 @@
+
+ */
+
+use Friendica\Core\Hook;
+use Friendica\Core\Logger;
+use Friendica\DI;
+
+function cld_install()
+{
+ Hook::register('detect_languages', __FILE__, 'cld_detect_languages');
+}
+
+function cld_detect_languages(array &$data)
+{
+ if (!in_array('cld2', get_loaded_extensions())) {
+ Logger::warning('CLD2 is not installed.');
+ return;
+ }
+
+ $cld2 = new \CLD2Detector();
+
+ $cld2->setEncodingHint(CLD2Encoding::UTF8); // optional, hints about text encoding
+ $cld2->setPlainText(true);
+
+ $result = $cld2->detect($data['text']);
+
+ if ($data['detected']) {
+ $original = array_key_first($data['detected']);
+ } else {
+ $original = '';
+ }
+
+ $detected = DI::l10n()->toISO6391($result['language_code']);
+
+ // languages that aren't supported via the base language detection or tend to false detections
+ if ((strlen($detected) == 3) || in_array($detected, ['ht', 'kk', 'ku', 'ky', 'lg', 'mg', 'mk', 'mt', 'ny', 'rw', 'st', 'su', 'tg', 'ts', 'xx'])) {
+ return;
+ }
+
+ if (!$result['is_reliable']) {
+ Logger::debug('Unreliable detection', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]);
+ if (($original == $detected) && ($data['detected'][$original] < $result['language_probability'] / 100)) {
+ $data['detected'][$original] = $result['language_probability'] / 100;
+ }
+ return;
+ }
+
+ $available = array_keys(DI::l10n()->getLanguageCodes());
+
+ if (!in_array($detected, $available)) {
+ Logger::debug('Unsupported language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]);
+ return;
+ }
+
+ if ($original != $detected) {
+ Logger::debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]);
+ }
+
+ $length = count($data['detected']);
+ if ($length > 0) {
+ unset($data['detected'][$detected]);
+ $data['detected'] = array_merge([$detected => $result['language_probability'] / 100], array_slice($data['detected'], 0, $length - 1));
+ } else {
+ $data['detected'] = [$detected => $result['language_probability'] / 100];
+ }
+}
diff --git a/curweather/curweather.php b/curweather/curweather.php
index f614840a..5a14a9cf 100644
--- a/curweather/curweather.php
+++ b/curweather/curweather.php
@@ -9,12 +9,10 @@
*
*/
-use Friendica\App;
use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\DI;
-use Friendica\Util\Proxy as ProxyUtils;
function curweather_install()
{
@@ -127,7 +125,7 @@ function curweather_network_mod_init(string &$body)
$t = Renderer::getMarkupTemplate("widget.tpl", "addon/curweather/" );
$curweather = Renderer::replaceMacros($t, [
'$title' => DI::l10n()->t("Current Weather"),
- '$icon' => ProxyUtils::proxifyUrl('http://openweathermap.org/img/w/'.$res['icon'].'.png'),
+ '$icon' => 'http://openweathermap.org/img/w/'.$res['icon'].'.png',
'$city' => $res['city'],
'$lon' => $res['lon'],
'$lat' => $res['lat'],
diff --git a/diaspora/diaspora.php b/diaspora/diaspora.php
index d48ddac6..cb2eb996 100644
--- a/diaspora/diaspora.php
+++ b/diaspora/diaspora.php
@@ -205,7 +205,7 @@ function diaspora_send(array &$b)
$b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b));
// Dont't post if the post doesn't belong to us.
- // This is a check for forum postings
+ // This is a check for group postings
$self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]);
if ($b['contact-id'] != $self['id']) {
diff --git a/diaspora/lang/C/messages.po b/diaspora/lang/C/messages.po
index 262e4cd8..b9944720 100644
--- a/diaspora/lang/C/messages.po
+++ b/diaspora/lang/C/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:17-0500\n"
+"POT-Creation-Date: 2023-06-03 15:48-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,84 +17,84 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: diaspora.php:44
+#: diaspora.php:43
msgid "Post to Diaspora"
msgstr ""
-#: diaspora.php:67
+#: diaspora.php:66
#, php-format
msgid ""
"Please remember: You can always be reached from Diaspora with your Friendica "
"handle %s . "
msgstr ""
-#: diaspora.php:68
+#: diaspora.php:67
msgid ""
"This connector is only meant if you still want to use your old Diaspora "
"account for some time. "
msgstr ""
-#: diaspora.php:69
+#: diaspora.php:68
#, php-format
msgid ""
"However, it is preferred that you tell your Diaspora contacts the new handle "
"%s instead."
msgstr ""
-#: diaspora.php:79
+#: diaspora.php:78
msgid "All aspects"
msgstr ""
-#: diaspora.php:80
+#: diaspora.php:79
msgid "Public"
msgstr ""
-#: diaspora.php:86
+#: diaspora.php:85
msgid "Post to aspect:"
msgstr ""
-#: diaspora.php:87
+#: diaspora.php:86
#, php-format
msgid "Connected with your Diaspora account %s "
msgstr ""
-#: diaspora.php:90
+#: diaspora.php:89
msgid ""
"Can't login to your Diaspora account. Please check handle (in the format "
"user@domain.tld) and password."
msgstr ""
-#: diaspora.php:97
+#: diaspora.php:96
msgid "Information"
msgstr ""
-#: diaspora.php:98
+#: diaspora.php:97
msgid "Error"
msgstr ""
-#: diaspora.php:104
+#: diaspora.php:103
msgid "Enable Diaspora Post Addon"
msgstr ""
-#: diaspora.php:105
+#: diaspora.php:104
msgid "Diaspora handle"
msgstr ""
-#: diaspora.php:106
+#: diaspora.php:105
msgid "Diaspora password"
msgstr ""
-#: diaspora.php:106
+#: diaspora.php:105
msgid ""
"Privacy notice: Your Diaspora password will be stored unencrypted to "
"authenticate you with your Diaspora pod. This means your Friendica node "
"administrator can have access to it."
msgstr ""
-#: diaspora.php:108
+#: diaspora.php:107
msgid "Post to Diaspora by default"
msgstr ""
-#: diaspora.php:113
+#: diaspora.php:112
msgid "Diaspora Export"
msgstr ""
diff --git a/discourse/discourse.php b/discourse/discourse.php
index 3d27c5b0..298b3f3e 100644
--- a/discourse/discourse.php
+++ b/discourse/discourse.php
@@ -126,7 +126,7 @@ function discourse_fetch_post($host, $topic, $pid)
return false;
}
- $raw = $curlResult->getBody();
+ $raw = $curlResult->getBodyString();
$data = json_decode($raw, true);
$posts = $data['post_stream']['posts'];
foreach($posts as $post) {
@@ -162,7 +162,7 @@ function discourse_fetch_post_from_api(&$message, $post, $host)
return false;
}
- $raw = $curlResult->getBody();
+ $raw = $curlResult->getBodyString();
$data = json_decode($raw, true);
if (empty($data)) {
return false;
diff --git a/dwpost/dwpost.php b/dwpost/dwpost.php
index 6c1742e4..4ad5021f 100644
--- a/dwpost/dwpost.php
+++ b/dwpost/dwpost.php
@@ -192,7 +192,7 @@ EOT;
Logger::debug('dwpost: data: ' . $xml);
if ($dw_blog !== 'test') {
- $x = DI::httpClient()->post($dw_blog, $xml, ['Content-Type' => 'text/xml'])->getBody();
+ $x = DI::httpClient()->post($dw_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString();
}
Logger::info('posted to dreamwidth: ' . ($x) ? $x : '');
diff --git a/forumdirectory/forumdirectory.php b/forumdirectory/forumdirectory.php
index 61d3efd4..114da1da 100644
--- a/forumdirectory/forumdirectory.php
+++ b/forumdirectory/forumdirectory.php
@@ -4,6 +4,8 @@
* Description: Add a directory of forums hosted on your server, with verbose descriptions.
* Version: 1.1
* Author: Thomas Willingham
+ * Status: Unsupported
+ * Note: Please use Group Directory instead
*/
use Friendica\App;
@@ -102,8 +104,8 @@ function forumdirectory_content()
$total = 0;
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
- WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? $sql_extra",
- User::PAGE_FLAGS_COMMUNITY);
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) $sql_extra",
+ User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN);
if (DBA::isResult($cnt)) {
$total = $cnt['total'];
}
@@ -118,8 +120,8 @@ function forumdirectory_content()
`contact`.`addr`, `contact`.`url` FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
- WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` = ? AND `contact`.`self`
- $sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) AND `contact`.`self`
+ $sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN
);
if (DBA::isResult($r)) {
diff --git a/group_text/group_text.php b/group_text/group_text.php
index 8520f696..02e9fd0a 100644
--- a/group_text/group_text.php
+++ b/group_text/group_text.php
@@ -4,6 +4,8 @@
* Description: Disable images in group edit menu
* Version: 1.0
* Author: Thomas Willingham
+ * Status: Unsupported
+ * Note: Please use Circle Text instead
*/
use Friendica\App;
diff --git a/groupdirectory/groupdirectory.php b/groupdirectory/groupdirectory.php
new file mode 100644
index 00000000..6d562cdc
--- /dev/null
+++ b/groupdirectory/groupdirectory.php
@@ -0,0 +1,155 @@
+
+ */
+
+use Friendica\Content\Nav;
+use Friendica\Content\Pager;
+use Friendica\Content\Widget;
+use Friendica\Core\Hook;
+use Friendica\Core\Renderer;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Profile;
+use Friendica\Model\User;
+
+global $groupdirectory_search;
+
+function groupdirectory_install()
+{
+ Hook::register('app_menu', __FILE__, 'groupdirectory_app_menu');
+}
+
+/**
+ * This is a statement rather than an actual function definition. The simple
+ * existence of this method is checked to figure out if the addon offers a
+ * module.
+ */
+/**
+ * This is a statement rather than an actual function definition. The simple
+ * existence of this method is checked to figure out if the addon offers a
+ * module.
+ */
+function groupdirectory_module() {}
+
+function groupdirectory_app_menu(array &$b)
+{
+ $b['app_menu'][] = '';
+}
+
+function groupdirectory_init()
+{
+ if (DI::userSession()->getLocalUserId()) {
+ DI::page()['aside'] .= Widget::findPeople();
+ }
+}
+
+function groupdirectory_post()
+{
+ global $groupdirectory_search;
+
+ if (!empty($_POST['search'])) {
+ $groupdirectory_search = $_POST['search'];
+ }
+}
+
+function groupdirectory_content()
+{
+ global $groupdirectory_search;
+
+ if (DI::config()->get('system', 'block_public') && !DI::userSession()->getLocalUserId() && !DI::userSession()->getRemoteUserId()) {
+ DI::sysmsg()->addNotice(DI::l10n()->t('Public access denied.'));
+ return '';
+ }
+
+ $o = '';
+ $entries = [];
+
+ Nav::setSelected('directory');
+
+ if (!empty($groupdirectory_search)) {
+ $search = trim($groupdirectory_search);
+ } else {
+ $search = (!empty($_GET['search']) ? trim(rawurldecode($_GET['search'])) : '');
+ }
+
+ $gdirpath = '';
+ $dirurl = DI::config()->get('system', 'directory');
+ if (strlen($dirurl)) {
+ $gdirpath = Profile::zrl($dirurl, true);
+ }
+
+ $sql_extra = '';
+ if (strlen($search)) {
+ $search = DBA::escape($search);
+
+ $sql_extra = " AND ((`profile`.`name` LIKE '%$search%') OR
+ (`user`.`nickname` LIKE '%$search%') OR
+ (`profile`.`about` LIKE '%$search%') OR
+ (`profile`.`locality` LIKE '%$search%') OR
+ (`profile`.`region` LIKE '%$search%') OR
+ (`profile`.`country-name` LIKE '%$search%') OR
+ (`profile`.`pub_keywords` LIKE '%$search%') OR
+ (`profile`.`prv_keywords` LIKE '%$search%'))";
+ }
+
+ $publish = DI::config()->get('system', 'publish_all') ? '' : "`publish` = 1";
+
+ $total = 0;
+ $cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile`
+ INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) $sql_extra",
+ User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN);
+ if (DBA::isResult($cnt)) {
+ $total = $cnt['total'];
+ }
+
+ $pager = new Pager(DI::l10n(), DI::args()->getQueryString(), 60);
+
+ $order = " ORDER BY `name` ASC ";
+
+ $limit = $pager->getStart() . "," . $pager->getItemsPerPage();
+
+ $r = DBA::p("SELECT `profile`.*, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`,
+ `contact`.`addr`, `contact`.`url` FROM `profile`
+ INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
+ INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid`
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `user`.`page-flags` IN (?, ?) AND `contact`.`self`
+ $sql_extra $order LIMIT $limit", User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_COMM_MAN
+ );
+
+ if (DBA::isResult($r)) {
+ if (in_array('small', DI::args()->getArgv())) {
+ $photo = 'thumb';
+ } else {
+ $photo = 'photo';
+ }
+
+ while ($rr = DBA::fetch($r)) {
+ $entries[] = Friendica\Module\Directory::formatEntry($rr, $photo);
+ }
+ DBA::close($r);
+ } else {
+ DI::sysmsg()->addNotice(DI::l10n()->t('No entries (some entries may be hidden).'));
+ }
+
+ $tpl = Renderer::getMarkupTemplate('directory_header.tpl');
+ $o .= Renderer::replaceMacros($tpl, [
+ '$search' => $search,
+ '$globaldir' => DI::l10n()->t('Global Directory'),
+ '$gdirpath' => $gdirpath,
+ '$desc' => DI::l10n()->t('Find on this site'),
+ '$contacts' => $entries,
+ '$finding' => DI::l10n()->t('Results for:'),
+ '$findterm' => (strlen($search) ? $search : ""),
+ '$title' => DI::l10n()->t('Group Directory'),
+ '$search_mod' => 'groupdirectory',
+ '$submit' => DI::l10n()->t('Find'),
+ '$paginate' => $pager->renderFull($total),
+ ]);
+
+ return $o;
+}
diff --git a/groupdirectory/lang/C/messages.po b/groupdirectory/lang/C/messages.po
new file mode 100644
index 00000000..f83171f4
--- /dev/null
+++ b/groupdirectory/lang/C/messages.po
@@ -0,0 +1,46 @@
+# ADDON groupdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica groupdirectory addon package.
+#
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-06-03 15:49-0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: groupdirectory.php:40 groupdirectory.php:148
+msgid "Group Directory"
+msgstr ""
+
+#: groupdirectory.php:64
+msgid "Public access denied."
+msgstr ""
+
+#: groupdirectory.php:136
+msgid "No entries (some entries may be hidden)."
+msgstr ""
+
+#: groupdirectory.php:142
+msgid "Global Directory"
+msgstr ""
+
+#: groupdirectory.php:144
+msgid "Find on this site"
+msgstr ""
+
+#: groupdirectory.php:146
+msgid "Results for:"
+msgstr ""
+
+#: groupdirectory.php:150
+msgid "Find"
+msgstr ""
diff --git a/groupdirectory/lang/ar/messages.po b/groupdirectory/lang/ar/messages.po
new file mode 100644
index 00000000..24380f0f
--- /dev/null
+++ b/groupdirectory/lang/ar/messages.po
@@ -0,0 +1,50 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# abidin toumi , 2021
+# ButterflyOfFire, 2019
+# Farida Khalaf , 2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2021-10-29 10:27+0000\n"
+"Last-Translator: abidin toumi \n"
+"Language-Team: Arabic (http://www.transifex.com/Friendica/friendica/language/ar/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ar\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "دليل المنتدى"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "رُفض الوصول العمومي."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "لا توجد مدخلات (قد تكون بعض المدخلات مخفية)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "الدليل العالمي"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "ابحث في هذا الموقع"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "النتائج:"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "ابحث"
diff --git a/groupdirectory/lang/ar/strings.php b/groupdirectory/lang/ar/strings.php
new file mode 100644
index 00000000..eb6f3077
--- /dev/null
+++ b/groupdirectory/lang/ar/strings.php
@@ -0,0 +1,14 @@
+=3 && $n%100<=10) { return 3; } else if ($n%100>=11 && $n%100<=99) { return 4; } else { return 5; }
+}}
+$a->strings['Forum Directory'] = 'دليل المنتدى';
+$a->strings['Public access denied.'] = 'رُفض الوصول العمومي.';
+$a->strings['No entries (some entries may be hidden).'] = 'لا توجد مدخلات (قد تكون بعض المدخلات مخفية).';
+$a->strings['Global Directory'] = 'الدليل العالمي';
+$a->strings['Find on this site'] = 'ابحث في هذا الموقع';
+$a->strings['Results for:'] = 'النتائج:';
+$a->strings['Find'] = 'ابحث';
diff --git a/groupdirectory/lang/ca/messages.po b/groupdirectory/lang/ca/messages.po
new file mode 100644
index 00000000..0aa19b1c
--- /dev/null
+++ b/groupdirectory/lang/ca/messages.po
@@ -0,0 +1,80 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Joan Bar , 2019
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2019-10-18 18:57+0000\n"
+"Last-Translator: Joan Bar \n"
+"Language-Team: Catalan (http://www.transifex.com/Friendica/friendica/language/ca/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ca\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:22
+msgid "Forum Directory"
+msgstr "Directori de fòrums"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "L'accés al públic s'ha denegat."
+
+#: forumdirectory.php:71
+msgid "Global Directory"
+msgstr "Directori global"
+
+#: forumdirectory.php:79
+msgid "Find on this site"
+msgstr "Cerqueu en aquest lloc"
+
+#: forumdirectory.php:81
+msgid "Finding: "
+msgstr "Trobament:"
+
+#: forumdirectory.php:82
+msgid "Site Directory"
+msgstr "Directori de llocs"
+
+#: forumdirectory.php:83
+msgid "Find"
+msgstr "trobar"
+
+#: forumdirectory.php:133
+msgid "Age: "
+msgstr "Edat:"
+
+#: forumdirectory.php:136
+msgid "Gender: "
+msgstr "Gènere:"
+
+#: forumdirectory.php:156
+msgid "Location:"
+msgstr "Ubicació:"
+
+#: forumdirectory.php:158
+msgid "Gender:"
+msgstr "Gènere:"
+
+#: forumdirectory.php:160
+msgid "Status:"
+msgstr "Estat:"
+
+#: forumdirectory.php:162
+msgid "Homepage:"
+msgstr "Pàgina inicial:"
+
+#: forumdirectory.php:164
+msgid "About:"
+msgstr "Sobre:"
+
+#: forumdirectory.php:201
+msgid "No entries (some entries may be hidden)."
+msgstr "No hi ha entrades (algunes entrades poden estar ocultes)."
diff --git a/groupdirectory/lang/ca/strings.php b/groupdirectory/lang/ca/strings.php
new file mode 100644
index 00000000..07a39488
--- /dev/null
+++ b/groupdirectory/lang/ca/strings.php
@@ -0,0 +1,22 @@
+strings['Forum Directory'] = 'Directori de fòrums';
+$a->strings['Public access denied.'] = 'L\'accés al públic s\'ha denegat.';
+$a->strings['Global Directory'] = 'Directori global';
+$a->strings['Find on this site'] = 'Cerqueu en aquest lloc';
+$a->strings['Finding: '] = 'Trobament:';
+$a->strings['Site Directory'] = 'Directori de llocs';
+$a->strings['Find'] = 'trobar';
+$a->strings['Age: '] = 'Edat:';
+$a->strings['Gender: '] = 'Gènere:';
+$a->strings['Location:'] = 'Ubicació:';
+$a->strings['Gender:'] = 'Gènere:';
+$a->strings['Status:'] = 'Estat:';
+$a->strings['Homepage:'] = 'Pàgina inicial:';
+$a->strings['About:'] = 'Sobre:';
+$a->strings['No entries (some entries may be hidden).'] = 'No hi ha entrades (algunes entrades poden estar ocultes).';
diff --git a/groupdirectory/lang/cs/messages.po b/groupdirectory/lang/cs/messages.po
new file mode 100644
index 00000000..138c26f3
--- /dev/null
+++ b/groupdirectory/lang/cs/messages.po
@@ -0,0 +1,81 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Aditoo, 2018
+# michal_s , 2014
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2018-09-11 19:04+0000\n"
+"Last-Translator: Aditoo\n"
+"Language-Team: Czech (http://www.transifex.com/Friendica/friendica/language/cs/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: cs\n"
+"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
+
+#: forumdirectory.php:22
+msgid "Forum Directory"
+msgstr "Adresář fór"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Veřejný přístup odepřen."
+
+#: forumdirectory.php:71
+msgid "Global Directory"
+msgstr "Globální adresář"
+
+#: forumdirectory.php:79
+msgid "Find on this site"
+msgstr "Najít na tomto webu"
+
+#: forumdirectory.php:81
+msgid "Finding: "
+msgstr "Hledání: "
+
+#: forumdirectory.php:82
+msgid "Site Directory"
+msgstr "Adresář serveru"
+
+#: forumdirectory.php:83
+msgid "Find"
+msgstr "Najít"
+
+#: forumdirectory.php:133
+msgid "Age: "
+msgstr "Věk: "
+
+#: forumdirectory.php:136
+msgid "Gender: "
+msgstr "Pohlaví: "
+
+#: forumdirectory.php:156
+msgid "Location:"
+msgstr "Poloha:"
+
+#: forumdirectory.php:158
+msgid "Gender:"
+msgstr "Pohlaví:"
+
+#: forumdirectory.php:160
+msgid "Status:"
+msgstr "Stav:"
+
+#: forumdirectory.php:162
+msgid "Homepage:"
+msgstr "Domovská stránka:"
+
+#: forumdirectory.php:164
+msgid "About:"
+msgstr "O mě:"
+
+#: forumdirectory.php:201
+msgid "No entries (some entries may be hidden)."
+msgstr "Žádné záznamy (některé položky mohou být skryty)."
diff --git a/groupdirectory/lang/cs/strings.php b/groupdirectory/lang/cs/strings.php
new file mode 100644
index 00000000..2e7d6378
--- /dev/null
+++ b/groupdirectory/lang/cs/strings.php
@@ -0,0 +1,22 @@
+= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; }
+}}
+$a->strings['Forum Directory'] = 'Adresář fór';
+$a->strings['Public access denied.'] = 'Veřejný přístup odepřen.';
+$a->strings['Global Directory'] = 'Globální adresář';
+$a->strings['Find on this site'] = 'Najít na tomto webu';
+$a->strings['Finding: '] = 'Hledání: ';
+$a->strings['Site Directory'] = 'Adresář serveru';
+$a->strings['Find'] = 'Najít';
+$a->strings['Age: '] = 'Věk: ';
+$a->strings['Gender: '] = 'Pohlaví: ';
+$a->strings['Location:'] = 'Poloha:';
+$a->strings['Gender:'] = 'Pohlaví:';
+$a->strings['Status:'] = 'Stav:';
+$a->strings['Homepage:'] = 'Domovská stránka:';
+$a->strings['About:'] = 'O mě:';
+$a->strings['No entries (some entries may be hidden).'] = 'Žádné záznamy (některé položky mohou být skryty).';
diff --git a/groupdirectory/lang/da-dk/messages.po b/groupdirectory/lang/da-dk/messages.po
new file mode 100644
index 00000000..882c896e
--- /dev/null
+++ b/groupdirectory/lang/da-dk/messages.po
@@ -0,0 +1,48 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Anton , 2022
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2014-06-22 12:31+0000\n"
+"Last-Translator: Anton , 2022\n"
+"Language-Team: Danish (Denmark) (http://www.transifex.com/Friendica/friendica/language/da_DK/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: da_DK\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Forum adressebog"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Offentlig adgang nægtet."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Ingen poster (nogle poster er måske skjulte)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Global adressebog"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Find på denne side"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "Resultater for:"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Find"
diff --git a/groupdirectory/lang/da-dk/strings.php b/groupdirectory/lang/da-dk/strings.php
new file mode 100644
index 00000000..fecaed71
--- /dev/null
+++ b/groupdirectory/lang/da-dk/strings.php
@@ -0,0 +1,14 @@
+strings['Forum Directory'] = 'Forum adressebog';
+$a->strings['Public access denied.'] = 'Offentlig adgang nægtet.';
+$a->strings['No entries (some entries may be hidden).'] = 'Ingen poster (nogle poster er måske skjulte).';
+$a->strings['Global Directory'] = 'Global adressebog';
+$a->strings['Find on this site'] = 'Find på denne side';
+$a->strings['Results for:'] = 'Resultater for:';
+$a->strings['Find'] = 'Find';
diff --git a/groupdirectory/lang/de/messages.po b/groupdirectory/lang/de/messages.po
new file mode 100644
index 00000000..35ee4a55
--- /dev/null
+++ b/groupdirectory/lang/de/messages.po
@@ -0,0 +1,49 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Tobias Diekershoff , 2014
+# Tobias Diekershoff , 2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2014-06-22 12:31+0000\n"
+"Last-Translator: Tobias Diekershoff , 2021\n"
+"Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Foren Verzeichnis"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Öffentlicher Zugriff verweigert."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Keine Einträge (einige Einträge könnten versteckt sein)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Weltweites Verzeichnis"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Auf diesem Server suchen"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "Ergebnis für:"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Finde"
diff --git a/groupdirectory/lang/de/strings.php b/groupdirectory/lang/de/strings.php
new file mode 100644
index 00000000..081f3152
--- /dev/null
+++ b/groupdirectory/lang/de/strings.php
@@ -0,0 +1,14 @@
+strings['Forum Directory'] = 'Foren Verzeichnis';
+$a->strings['Public access denied.'] = 'Öffentlicher Zugriff verweigert.';
+$a->strings['No entries (some entries may be hidden).'] = 'Keine Einträge (einige Einträge könnten versteckt sein).';
+$a->strings['Global Directory'] = 'Weltweites Verzeichnis';
+$a->strings['Find on this site'] = 'Auf diesem Server suchen';
+$a->strings['Results for:'] = 'Ergebnis für:';
+$a->strings['Find'] = 'Finde';
diff --git a/groupdirectory/lang/eo/strings.php b/groupdirectory/lang/eo/strings.php
new file mode 100644
index 00000000..4ec15e76
--- /dev/null
+++ b/groupdirectory/lang/eo/strings.php
@@ -0,0 +1,16 @@
+strings["Public access denied."] = "Publika atingo ne permesita.";
+$a->strings["Global Directory"] = "Tutmonda Katalogo";
+$a->strings["Find on this site"] = "Trovi en ĉi retejo";
+$a->strings["Finding: "] = "Trovata:";
+$a->strings["Site Directory"] = "Reteja Katalogo";
+$a->strings["Find"] = "Trovi";
+$a->strings["Age: "] = "Aĝo:";
+$a->strings["Gender: "] = "Sekso:";
+$a->strings["Location:"] = "Loko:";
+$a->strings["Gender:"] = "Sekso:";
+$a->strings["Status:"] = "Stato:";
+$a->strings["Homepage:"] = "Hejmpaĝo:";
+$a->strings["About:"] = "Pri:";
+$a->strings["No entries (some entries may be hidden)."] = "Neniom da afiŝoj (kelkaj afiŝoj eble ne estas videbla).";
diff --git a/groupdirectory/lang/es/messages.po b/groupdirectory/lang/es/messages.po
new file mode 100644
index 00000000..74948223
--- /dev/null
+++ b/groupdirectory/lang/es/messages.po
@@ -0,0 +1,49 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Albert, 2016
+# Senex Petrovic , 2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2021-04-01 09:54+0000\n"
+"Last-Translator: Senex Petrovic \n"
+"Language-Team: Spanish (http://www.transifex.com/Friendica/friendica/language/es/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: es\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Directorio de foro"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Acceso público denegado."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Sin entradas (algunas entradas pueden estar ocultas)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Directorio global"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Encontrar en esta página"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "Resultados para:"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Encontrar"
diff --git a/groupdirectory/lang/es/strings.php b/groupdirectory/lang/es/strings.php
new file mode 100644
index 00000000..4f1a59f1
--- /dev/null
+++ b/groupdirectory/lang/es/strings.php
@@ -0,0 +1,14 @@
+strings['Forum Directory'] = 'Directorio de foro';
+$a->strings['Public access denied.'] = 'Acceso público denegado.';
+$a->strings['No entries (some entries may be hidden).'] = 'Sin entradas (algunas entradas pueden estar ocultas).';
+$a->strings['Global Directory'] = 'Directorio global';
+$a->strings['Find on this site'] = 'Encontrar en esta página';
+$a->strings['Results for:'] = 'Resultados para:';
+$a->strings['Find'] = 'Encontrar';
diff --git a/groupdirectory/lang/fi-fi/messages.po b/groupdirectory/lang/fi-fi/messages.po
new file mode 100644
index 00000000..6c4f08c9
--- /dev/null
+++ b/groupdirectory/lang/fi-fi/messages.po
@@ -0,0 +1,81 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Kris, 2018
+# Kris, 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2018-05-12 12:50+0000\n"
+"Last-Translator: Kris\n"
+"Language-Team: Finnish (Finland) (http://www.transifex.com/Friendica/friendica/language/fi_FI/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fi_FI\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:22
+msgid "Forum Directory"
+msgstr "Foorumihakemisto"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Julkinen käyttö estetty."
+
+#: forumdirectory.php:71
+msgid "Global Directory"
+msgstr "Maailmanlaajuinen hakemisto"
+
+#: forumdirectory.php:79
+msgid "Find on this site"
+msgstr "Sivustohaku"
+
+#: forumdirectory.php:81
+msgid "Finding: "
+msgstr ""
+
+#: forumdirectory.php:82
+msgid "Site Directory"
+msgstr "Sivustoluettelo"
+
+#: forumdirectory.php:83
+msgid "Find"
+msgstr "Etsi"
+
+#: forumdirectory.php:133
+msgid "Age: "
+msgstr "Ikä:"
+
+#: forumdirectory.php:136
+msgid "Gender: "
+msgstr "Sukupuoli:"
+
+#: forumdirectory.php:156
+msgid "Location:"
+msgstr "Sijainti:"
+
+#: forumdirectory.php:158
+msgid "Gender:"
+msgstr "Sukupuoli:"
+
+#: forumdirectory.php:160
+msgid "Status:"
+msgstr "Tila:"
+
+#: forumdirectory.php:162
+msgid "Homepage:"
+msgstr "Kotisivu:"
+
+#: forumdirectory.php:164
+msgid "About:"
+msgstr "Lisätietoja:"
+
+#: forumdirectory.php:201
+msgid "No entries (some entries may be hidden)."
+msgstr "Ei kohteita (jotkut kohteet saattaa olla piilotettuja)."
diff --git a/groupdirectory/lang/fi-fi/strings.php b/groupdirectory/lang/fi-fi/strings.php
new file mode 100644
index 00000000..70657d3c
--- /dev/null
+++ b/groupdirectory/lang/fi-fi/strings.php
@@ -0,0 +1,21 @@
+strings['Forum Directory'] = 'Foorumihakemisto';
+$a->strings['Public access denied.'] = 'Julkinen käyttö estetty.';
+$a->strings['Global Directory'] = 'Maailmanlaajuinen hakemisto';
+$a->strings['Find on this site'] = 'Sivustohaku';
+$a->strings['Site Directory'] = 'Sivustoluettelo';
+$a->strings['Find'] = 'Etsi';
+$a->strings['Age: '] = 'Ikä:';
+$a->strings['Gender: '] = 'Sukupuoli:';
+$a->strings['Location:'] = 'Sijainti:';
+$a->strings['Gender:'] = 'Sukupuoli:';
+$a->strings['Status:'] = 'Tila:';
+$a->strings['Homepage:'] = 'Kotisivu:';
+$a->strings['About:'] = 'Lisätietoja:';
+$a->strings['No entries (some entries may be hidden).'] = 'Ei kohteita (jotkut kohteet saattaa olla piilotettuja).';
diff --git a/groupdirectory/lang/fr/messages.po b/groupdirectory/lang/fr/messages.po
new file mode 100644
index 00000000..7f9e2458
--- /dev/null
+++ b/groupdirectory/lang/fr/messages.po
@@ -0,0 +1,51 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# bob lebonche , 2021
+# Hypolite Petovan , 2016
+# StefOfficiel , 2015
+# Valvin , 2019
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2014-06-22 12:31+0000\n"
+"Last-Translator: bob lebonche , 2021\n"
+"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Annuaire de Forums"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Accès public refusé."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Pas de résultats (certains résultats peuvent être cachés)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Annuaire Global"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Trouver sur cette instance"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "Résultats pour :"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Chercher"
diff --git a/groupdirectory/lang/fr/strings.php b/groupdirectory/lang/fr/strings.php
new file mode 100644
index 00000000..ac0e2323
--- /dev/null
+++ b/groupdirectory/lang/fr/strings.php
@@ -0,0 +1,14 @@
+strings['Forum Directory'] = 'Annuaire de Forums';
+$a->strings['Public access denied.'] = 'Accès public refusé.';
+$a->strings['No entries (some entries may be hidden).'] = 'Pas de résultats (certains résultats peuvent être cachés).';
+$a->strings['Global Directory'] = 'Annuaire Global';
+$a->strings['Find on this site'] = 'Trouver sur cette instance';
+$a->strings['Results for:'] = 'Résultats pour :';
+$a->strings['Find'] = 'Chercher';
diff --git a/groupdirectory/lang/hu/messages.po b/groupdirectory/lang/hu/messages.po
new file mode 100644
index 00000000..996d310c
--- /dev/null
+++ b/groupdirectory/lang/hu/messages.po
@@ -0,0 +1,48 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Balázs Úr, 2020-2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2014-06-22 12:31+0000\n"
+"Last-Translator: Balázs Úr, 2020-2021\n"
+"Language-Team: Hungarian (http://www.transifex.com/Friendica/friendica/language/hu/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hu\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Fórumkönyvtár"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Nyilvános hozzáférés megtagadva."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Nincsenek bejegyzések (néhány bejegyzés rejtve lehet)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Globális könyvtár"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Keresés ezen az oldalon"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "Találatok ehhez:"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Keresés"
diff --git a/groupdirectory/lang/hu/strings.php b/groupdirectory/lang/hu/strings.php
new file mode 100644
index 00000000..290cf7ed
--- /dev/null
+++ b/groupdirectory/lang/hu/strings.php
@@ -0,0 +1,14 @@
+strings['Forum Directory'] = 'Fórumkönyvtár';
+$a->strings['Public access denied.'] = 'Nyilvános hozzáférés megtagadva.';
+$a->strings['No entries (some entries may be hidden).'] = 'Nincsenek bejegyzések (néhány bejegyzés rejtve lehet).';
+$a->strings['Global Directory'] = 'Globális könyvtár';
+$a->strings['Find on this site'] = 'Keresés ezen az oldalon';
+$a->strings['Results for:'] = 'Találatok ehhez:';
+$a->strings['Find'] = 'Keresés';
diff --git a/groupdirectory/lang/is/strings.php b/groupdirectory/lang/is/strings.php
new file mode 100644
index 00000000..da710b73
--- /dev/null
+++ b/groupdirectory/lang/is/strings.php
@@ -0,0 +1,16 @@
+strings["Public access denied."] = "Alemennings aðgangur ekki veittur.";
+$a->strings["Global Directory"] = "Heims tengiliða skrá";
+$a->strings["Find on this site"] = "Leita á þessum vef";
+$a->strings["Finding: "] = "Niðurstöður:";
+$a->strings["Site Directory"] = "Vef tengiliða skrá";
+$a->strings["Find"] = "Finna";
+$a->strings["Age: "] = "Aldur:";
+$a->strings["Gender: "] = "Kyn:";
+$a->strings["Location:"] = "Staðsetning:";
+$a->strings["Gender:"] = "Kyn:";
+$a->strings["Status:"] = "Staða:";
+$a->strings["Homepage:"] = "Heimasíða:";
+$a->strings["About:"] = "Um:";
+$a->strings["No entries (some entries may be hidden)."] = "Engar færslur (sumar geta verið faldar).";
diff --git a/groupdirectory/lang/it/messages.po b/groupdirectory/lang/it/messages.po
new file mode 100644
index 00000000..8e3e5fa3
--- /dev/null
+++ b/groupdirectory/lang/it/messages.po
@@ -0,0 +1,49 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# fabrixxm , 2014
+# Sylke Vicious , 2021
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2021-02-16 12:56+0000\n"
+"Last-Translator: Sylke Vicious \n"
+"Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: it\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Elenco Forum"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Accesso negato."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Nessuna voce (qualche voce potrebbe essere nascosta)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Elenco globale"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Cerca nel sito"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "Risultati per:"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Trova"
diff --git a/groupdirectory/lang/it/strings.php b/groupdirectory/lang/it/strings.php
new file mode 100644
index 00000000..4378cec3
--- /dev/null
+++ b/groupdirectory/lang/it/strings.php
@@ -0,0 +1,14 @@
+strings['Forum Directory'] = 'Elenco Forum';
+$a->strings['Public access denied.'] = 'Accesso negato.';
+$a->strings['No entries (some entries may be hidden).'] = 'Nessuna voce (qualche voce potrebbe essere nascosta).';
+$a->strings['Global Directory'] = 'Elenco globale';
+$a->strings['Find on this site'] = 'Cerca nel sito';
+$a->strings['Results for:'] = 'Risultati per:';
+$a->strings['Find'] = 'Trova';
diff --git a/groupdirectory/lang/nb-no/strings.php b/groupdirectory/lang/nb-no/strings.php
new file mode 100644
index 00000000..bcc94233
--- /dev/null
+++ b/groupdirectory/lang/nb-no/strings.php
@@ -0,0 +1,17 @@
+strings["Forum Directory"] = "";
+$a->strings["Public access denied."] = "Offentlig tilgang ikke tillatt.";
+$a->strings["Global Directory"] = "Global katalog";
+$a->strings["Find on this site"] = "";
+$a->strings["Finding: "] = "Fant:";
+$a->strings["Site Directory"] = "Stedets katalog";
+$a->strings["Find"] = "Finn";
+$a->strings["Age: "] = "Alder:";
+$a->strings["Gender: "] = "Kjønn:";
+$a->strings["Location:"] = "Plassering:";
+$a->strings["Gender:"] = "Kjønn:";
+$a->strings["Status:"] = "Status:";
+$a->strings["Homepage:"] = "Hjemmeside:";
+$a->strings["About:"] = "Om:";
+$a->strings["No entries (some entries may be hidden)."] = "Ingen oppføringer (noen oppføringer kan være skjulte).";
diff --git a/groupdirectory/lang/nl/messages.po b/groupdirectory/lang/nl/messages.po
new file mode 100644
index 00000000..746e1bff
--- /dev/null
+++ b/groupdirectory/lang/nl/messages.po
@@ -0,0 +1,80 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Jeroen De Meerleer , 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2018-08-24 13:21+0000\n"
+"Last-Translator: Jeroen De Meerleer \n"
+"Language-Team: Dutch (http://www.transifex.com/Friendica/friendica/language/nl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:22
+msgid "Forum Directory"
+msgstr "Forum index"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Publieke toegang geweigerd"
+
+#: forumdirectory.php:71
+msgid "Global Directory"
+msgstr "Globaal overzicht"
+
+#: forumdirectory.php:79
+msgid "Find on this site"
+msgstr "Zoeken"
+
+#: forumdirectory.php:81
+msgid "Finding: "
+msgstr "Zoeken..."
+
+#: forumdirectory.php:82
+msgid "Site Directory"
+msgstr "Site overzicht"
+
+#: forumdirectory.php:83
+msgid "Find"
+msgstr "Zoek"
+
+#: forumdirectory.php:133
+msgid "Age: "
+msgstr "Leeftijd:"
+
+#: forumdirectory.php:136
+msgid "Gender: "
+msgstr "Geslacht:"
+
+#: forumdirectory.php:156
+msgid "Location:"
+msgstr "Woonplaats:"
+
+#: forumdirectory.php:158
+msgid "Gender:"
+msgstr "Geslacht:"
+
+#: forumdirectory.php:160
+msgid "Status:"
+msgstr "Status:"
+
+#: forumdirectory.php:162
+msgid "Homepage:"
+msgstr "Website:"
+
+#: forumdirectory.php:164
+msgid "About:"
+msgstr "Over:"
+
+#: forumdirectory.php:201
+msgid "No entries (some entries may be hidden)."
+msgstr "Geen berichten (sommige berichten kunnen verborgen zijn)."
diff --git a/groupdirectory/lang/nl/strings.php b/groupdirectory/lang/nl/strings.php
new file mode 100644
index 00000000..ae764ed7
--- /dev/null
+++ b/groupdirectory/lang/nl/strings.php
@@ -0,0 +1,22 @@
+strings['Forum Directory'] = 'Forum index';
+$a->strings['Public access denied.'] = 'Publieke toegang geweigerd';
+$a->strings['Global Directory'] = 'Globaal overzicht';
+$a->strings['Find on this site'] = 'Zoeken';
+$a->strings['Finding: '] = 'Zoeken...';
+$a->strings['Site Directory'] = 'Site overzicht';
+$a->strings['Find'] = 'Zoek';
+$a->strings['Age: '] = 'Leeftijd:';
+$a->strings['Gender: '] = 'Geslacht:';
+$a->strings['Location:'] = 'Woonplaats:';
+$a->strings['Gender:'] = 'Geslacht:';
+$a->strings['Status:'] = 'Status:';
+$a->strings['Homepage:'] = 'Website:';
+$a->strings['About:'] = 'Over:';
+$a->strings['No entries (some entries may be hidden).'] = 'Geen berichten (sommige berichten kunnen verborgen zijn).';
diff --git a/groupdirectory/lang/pl/messages.po b/groupdirectory/lang/pl/messages.po
new file mode 100644
index 00000000..49226ac0
--- /dev/null
+++ b/groupdirectory/lang/pl/messages.po
@@ -0,0 +1,50 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# TORminator , 2015
+# Piotr Strębski , 2022
+# Waldemar Stoczkowski, 2018
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2014-06-22 12:31+0000\n"
+"Last-Translator: Piotr Strębski , 2022\n"
+"Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pl\n"
+"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Katalog forum"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Odmowa dostępu publicznego."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Brak wpisów (niektóre wpisy mogą być ukryte)."
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Globalny katalog"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Znajdź na tej stronie"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr "Wyniki dla:"
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Szukaj"
diff --git a/groupdirectory/lang/pl/strings.php b/groupdirectory/lang/pl/strings.php
new file mode 100644
index 00000000..9bf60bd7
--- /dev/null
+++ b/groupdirectory/lang/pl/strings.php
@@ -0,0 +1,14 @@
+=2 && $n%10<=4) && ($n%100<12 || $n%100>14)) { return 1; } else if ($n!=1 && ($n%10>=0 && $n%10<=1) || ($n%10>=5 && $n%10<=9) || ($n%100>=12 && $n%100<=14)) { return 2; } else { return 3; }
+}}
+$a->strings['Forum Directory'] = 'Katalog forum';
+$a->strings['Public access denied.'] = 'Odmowa dostępu publicznego.';
+$a->strings['No entries (some entries may be hidden).'] = 'Brak wpisów (niektóre wpisy mogą być ukryte).';
+$a->strings['Global Directory'] = 'Globalny katalog';
+$a->strings['Find on this site'] = 'Znajdź na tej stronie';
+$a->strings['Results for:'] = 'Wyniki dla:';
+$a->strings['Find'] = 'Szukaj';
diff --git a/groupdirectory/lang/pt-br/messages.po b/groupdirectory/lang/pt-br/messages.po
new file mode 100644
index 00000000..c8d528ed
--- /dev/null
+++ b/groupdirectory/lang/pt-br/messages.po
@@ -0,0 +1,80 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Beatriz Vital , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2016-08-19 17:03+0000\n"
+"Last-Translator: Beatriz Vital \n"
+"Language-Team: Portuguese (Brazil) (http://www.transifex.com/Friendica/friendica/language/pt_BR/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pt_BR\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: forumdirectory.php:22
+msgid "Forum Directory"
+msgstr "Diretório de Fóruns"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Acesso do público negado."
+
+#: forumdirectory.php:71
+msgid "Global Directory"
+msgstr "Diretório Global"
+
+#: forumdirectory.php:79
+msgid "Find on this site"
+msgstr "Procurar neste site"
+
+#: forumdirectory.php:81
+msgid "Finding: "
+msgstr "Procurando:"
+
+#: forumdirectory.php:82
+msgid "Site Directory"
+msgstr "Diretório do Site"
+
+#: forumdirectory.php:83
+msgid "Find"
+msgstr "Procurar"
+
+#: forumdirectory.php:133
+msgid "Age: "
+msgstr "Idade:"
+
+#: forumdirectory.php:136
+msgid "Gender: "
+msgstr "Sexo:"
+
+#: forumdirectory.php:156
+msgid "Location:"
+msgstr "Local:"
+
+#: forumdirectory.php:158
+msgid "Gender:"
+msgstr "Sexo:"
+
+#: forumdirectory.php:160
+msgid "Status:"
+msgstr "Estado:"
+
+#: forumdirectory.php:162
+msgid "Homepage:"
+msgstr "Página principal:"
+
+#: forumdirectory.php:164
+msgid "About:"
+msgstr "Sobre:"
+
+#: forumdirectory.php:201
+msgid "No entries (some entries may be hidden)."
+msgstr "Sem resultados (alguns resultados podem estar ocultos)."
diff --git a/groupdirectory/lang/pt-br/strings.php b/groupdirectory/lang/pt-br/strings.php
new file mode 100644
index 00000000..8c6d216e
--- /dev/null
+++ b/groupdirectory/lang/pt-br/strings.php
@@ -0,0 +1,22 @@
+ 1);
+}}
+$a->strings['Forum Directory'] = 'Diretório de Fóruns';
+$a->strings['Public access denied.'] = 'Acesso do público negado.';
+$a->strings['Global Directory'] = 'Diretório Global';
+$a->strings['Find on this site'] = 'Procurar neste site';
+$a->strings['Finding: '] = 'Procurando:';
+$a->strings['Site Directory'] = 'Diretório do Site';
+$a->strings['Find'] = 'Procurar';
+$a->strings['Age: '] = 'Idade:';
+$a->strings['Gender: '] = 'Sexo:';
+$a->strings['Location:'] = 'Local:';
+$a->strings['Gender:'] = 'Sexo:';
+$a->strings['Status:'] = 'Estado:';
+$a->strings['Homepage:'] = 'Página principal:';
+$a->strings['About:'] = 'Sobre:';
+$a->strings['No entries (some entries may be hidden).'] = 'Sem resultados (alguns resultados podem estar ocultos).';
diff --git a/groupdirectory/lang/ro/messages.po b/groupdirectory/lang/ro/messages.po
new file mode 100644
index 00000000..84de16f3
--- /dev/null
+++ b/groupdirectory/lang/ro/messages.po
@@ -0,0 +1,79 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2014-07-08 11:49+0000\n"
+"Last-Translator: Arian - Cazare Muncitori \n"
+"Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/friendica/language/ro_RO/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ro_RO\n"
+"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
+
+#: forumdirectory.php:22
+msgid "Forum Directory"
+msgstr "Director Forum"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Acces public refuzat."
+
+#: forumdirectory.php:71
+msgid "Global Directory"
+msgstr "Director Global"
+
+#: forumdirectory.php:79
+msgid "Find on this site"
+msgstr "Căutați pe acest site"
+
+#: forumdirectory.php:81
+msgid "Finding: "
+msgstr "Căutare:"
+
+#: forumdirectory.php:82
+msgid "Site Directory"
+msgstr "Director Site"
+
+#: forumdirectory.php:83
+msgid "Find"
+msgstr "Căutați"
+
+#: forumdirectory.php:133
+msgid "Age: "
+msgstr "Vârsta:"
+
+#: forumdirectory.php:136
+msgid "Gender: "
+msgstr "Sex:"
+
+#: forumdirectory.php:156
+msgid "Location:"
+msgstr "Locație:"
+
+#: forumdirectory.php:158
+msgid "Gender:"
+msgstr "Sex:"
+
+#: forumdirectory.php:160
+msgid "Status:"
+msgstr "Status:"
+
+#: forumdirectory.php:162
+msgid "Homepage:"
+msgstr "Pagină web:"
+
+#: forumdirectory.php:164
+msgid "About:"
+msgstr "Despre:"
+
+#: forumdirectory.php:201
+msgid "No entries (some entries may be hidden)."
+msgstr "Fără înregistrări (unele înregistrări pot fi ascunse)."
diff --git a/groupdirectory/lang/ro/strings.php b/groupdirectory/lang/ro/strings.php
new file mode 100644
index 00000000..750fe1e1
--- /dev/null
+++ b/groupdirectory/lang/ro/strings.php
@@ -0,0 +1,22 @@
+19)||(($n%100==0)&&($n!=0)))) { return 2; } else { return 1; }
+}}
+$a->strings['Forum Directory'] = 'Director Forum';
+$a->strings['Public access denied.'] = 'Acces public refuzat.';
+$a->strings['Global Directory'] = 'Director Global';
+$a->strings['Find on this site'] = 'Căutați pe acest site';
+$a->strings['Finding: '] = 'Căutare:';
+$a->strings['Site Directory'] = 'Director Site';
+$a->strings['Find'] = 'Căutați';
+$a->strings['Age: '] = 'Vârsta:';
+$a->strings['Gender: '] = 'Sex:';
+$a->strings['Location:'] = 'Locație:';
+$a->strings['Gender:'] = 'Sex:';
+$a->strings['Status:'] = 'Status:';
+$a->strings['Homepage:'] = 'Pagină web:';
+$a->strings['About:'] = 'Despre:';
+$a->strings['No entries (some entries may be hidden).'] = 'Fără înregistrări (unele înregistrări pot fi ascunse).';
diff --git a/groupdirectory/lang/ru/messages.po b/groupdirectory/lang/ru/messages.po
new file mode 100644
index 00000000..48250ba6
--- /dev/null
+++ b/groupdirectory/lang/ru/messages.po
@@ -0,0 +1,80 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Stanislav N. , 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: 2017-04-08 17:12+0000\n"
+"Last-Translator: Stanislav N. \n"
+"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ru\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
+
+#: forumdirectory.php:22
+msgid "Forum Directory"
+msgstr "Каталог форумов"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Свободный доступ закрыт."
+
+#: forumdirectory.php:71
+msgid "Global Directory"
+msgstr "Глобальный каталог"
+
+#: forumdirectory.php:79
+msgid "Find on this site"
+msgstr "Найти на этом сайте"
+
+#: forumdirectory.php:81
+msgid "Finding: "
+msgstr "Результат поиска: "
+
+#: forumdirectory.php:82
+msgid "Site Directory"
+msgstr "Каталог сайта"
+
+#: forumdirectory.php:83
+msgid "Find"
+msgstr "Найти"
+
+#: forumdirectory.php:133
+msgid "Age: "
+msgstr "Возраст: "
+
+#: forumdirectory.php:136
+msgid "Gender: "
+msgstr "Пол: "
+
+#: forumdirectory.php:156
+msgid "Location:"
+msgstr "Откуда:"
+
+#: forumdirectory.php:158
+msgid "Gender:"
+msgstr "Пол:"
+
+#: forumdirectory.php:160
+msgid "Status:"
+msgstr "Статус:"
+
+#: forumdirectory.php:162
+msgid "Homepage:"
+msgstr "Домашняя страничка:"
+
+#: forumdirectory.php:164
+msgid "About:"
+msgstr "О себе:"
+
+#: forumdirectory.php:201
+msgid "No entries (some entries may be hidden)."
+msgstr "Нет записей (некоторые записи могут быть скрыты)."
diff --git a/groupdirectory/lang/ru/strings.php b/groupdirectory/lang/ru/strings.php
new file mode 100644
index 00000000..54954d72
--- /dev/null
+++ b/groupdirectory/lang/ru/strings.php
@@ -0,0 +1,22 @@
+=2 && $n%10<=4 && ($n%100<12 || $n%100>14)) { return 1; } else if ($n%10==0 || ($n%10>=5 && $n%10<=9) || ($n%100>=11 && $n%100<=14)) { return 2; } else { return 3; }
+}}
+$a->strings['Forum Directory'] = 'Каталог форумов';
+$a->strings['Public access denied.'] = 'Свободный доступ закрыт.';
+$a->strings['Global Directory'] = 'Глобальный каталог';
+$a->strings['Find on this site'] = 'Найти на этом сайте';
+$a->strings['Finding: '] = 'Результат поиска: ';
+$a->strings['Site Directory'] = 'Каталог сайта';
+$a->strings['Find'] = 'Найти';
+$a->strings['Age: '] = 'Возраст: ';
+$a->strings['Gender: '] = 'Пол: ';
+$a->strings['Location:'] = 'Откуда:';
+$a->strings['Gender:'] = 'Пол:';
+$a->strings['Status:'] = 'Статус:';
+$a->strings['Homepage:'] = 'Домашняя страничка:';
+$a->strings['About:'] = 'О себе:';
+$a->strings['No entries (some entries may be hidden).'] = 'Нет записей (некоторые записи могут быть скрыты).';
diff --git a/groupdirectory/lang/sv/messages.po b/groupdirectory/lang/sv/messages.po
new file mode 100644
index 00000000..cf3ebfde
--- /dev/null
+++ b/groupdirectory/lang/sv/messages.po
@@ -0,0 +1,49 @@
+# ADDON forumdirectory
+# Copyright (C)
+# This file is distributed under the same license as the Friendica forumdirectory addon package.
+#
+#
+# Translators:
+# Hypolite Petovan , 2019
+# Kristoffer Grundström , 2022
+msgid ""
+msgstr ""
+"Project-Id-Version: friendica\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2021-02-01 18:15+0100\n"
+"PO-Revision-Date: 2022-01-15 23:39+0000\n"
+"Last-Translator: Kristoffer Grundström \n"
+"Language-Team: Swedish (http://www.transifex.com/Friendica/friendica/language/sv/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sv\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: forumdirectory.php:33 forumdirectory.php:137
+msgid "Forum Directory"
+msgstr "Forum-mapp"
+
+#: forumdirectory.php:53
+msgid "Public access denied."
+msgstr "Publik åtkomst nekades."
+
+#: forumdirectory.php:125
+msgid "No entries (some entries may be hidden)."
+msgstr "Inget att visa. (Man kan välja att inte synas här)"
+
+#: forumdirectory.php:131
+msgid "Global Directory"
+msgstr "Medlemskatalog för flera sajter (global)"
+
+#: forumdirectory.php:133
+msgid "Find on this site"
+msgstr "Hitta på den här sidan"
+
+#: forumdirectory.php:135
+msgid "Results for:"
+msgstr ""
+
+#: forumdirectory.php:139
+msgid "Find"
+msgstr "Sök"
diff --git a/groupdirectory/lang/sv/strings.php b/groupdirectory/lang/sv/strings.php
new file mode 100644
index 00000000..0f06eaa3
--- /dev/null
+++ b/groupdirectory/lang/sv/strings.php
@@ -0,0 +1,13 @@
+strings['Forum Directory'] = 'Forum-mapp';
+$a->strings['Public access denied.'] = 'Publik åtkomst nekades.';
+$a->strings['No entries (some entries may be hidden).'] = 'Inget att visa. (Man kan välja att inte synas här)';
+$a->strings['Global Directory'] = 'Medlemskatalog för flera sajter (global)';
+$a->strings['Find on this site'] = 'Hitta på den här sidan';
+$a->strings['Find'] = 'Sök';
diff --git a/groupdirectory/lang/zh-cn/strings.php b/groupdirectory/lang/zh-cn/strings.php
new file mode 100644
index 00000000..4b5c78ba
--- /dev/null
+++ b/groupdirectory/lang/zh-cn/strings.php
@@ -0,0 +1,17 @@
+strings["Forum Directory"] = "评坛目录";
+$a->strings["Public access denied."] = "公众看拒绝";
+$a->strings["Global Directory"] = "综合目录";
+$a->strings["Find on this site"] = "找在这网站";
+$a->strings["Finding: "] = "找着:";
+$a->strings["Site Directory"] = "网站目录";
+$a->strings["Find"] = "搜索";
+$a->strings["Age: "] = "年纪:";
+$a->strings["Gender: "] = "性别:";
+$a->strings["Location:"] = "位置:";
+$a->strings["Gender:"] = "性别:";
+$a->strings["Status:"] = "现状:";
+$a->strings["Homepage:"] = "主页:";
+$a->strings["About:"] = "关于:";
+$a->strings["No entries (some entries may be hidden)."] = "没有文章(有的文章会被隐藏)。";
diff --git a/ifttt/ifttt.php b/ifttt/ifttt.php
index 6d4f402c..faaea2ca 100644
--- a/ifttt/ifttt.php
+++ b/ifttt/ifttt.php
@@ -180,5 +180,5 @@ function ifttt_message($uid, $item)
$link = hash('ripemd128', $item['msg']);
}
- Post\Delayed::add($link, $post, Worker::PRIORITY_MEDIUM, Post\Delayed::PREPARED);
+ Post\Delayed::add($link, $post, Worker::PRIORITY_MEDIUM, Post\Delayed::UNPREPARED);
}
diff --git a/ijpost/ijpost.php b/ijpost/ijpost.php
index 55d3fb05..885bc289 100644
--- a/ijpost/ijpost.php
+++ b/ijpost/ijpost.php
@@ -186,7 +186,7 @@ EOT;
Logger::debug('ijpost: data: ' . $xml);
if ($ij_blog !== 'test') {
- $x = DI::httpClient()->post($ij_blog, $xml, ['Content-Type' => 'text/xml'])->getBody();
+ $x = DI::httpClient()->post($ij_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString();
}
Logger::info('posted to insanejournal: ' . $x ? $x : '');
}
diff --git a/impressum/impressum.php b/impressum/impressum.php
index 1d572f85..754cb828 100644
--- a/impressum/impressum.php
+++ b/impressum/impressum.php
@@ -14,7 +14,7 @@ use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\DI;
use Friendica\Core\Config\Util\ConfigFileManager;
-use Friendica\Util\Proxy as ProxyUtils;
+use Friendica\Model\User;
function impressum_install()
{
@@ -45,7 +45,7 @@ function obfuscate_email (string $s): string
function impressum_footer(string &$body)
{
- $text = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'footer_text')));
+ $text = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'footer_text'));
if ($text != '') {
DI::page()['htmlhead'] .= ' ';
@@ -64,8 +64,8 @@ function impressum_show(string &$body)
$body .= '' . DI::l10n()->t('Impressum') . ' ';
$owner = DI::config()->get('impressum', 'owner');
$owner_profile = DI::config()->get('impressum', 'ownerprofile');
- $postal = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'postal')));
- $notes = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'notes')));
+ $postal = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'postal'));
+ $notes = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'notes'));
if ($owner) {
if ($owner_profile) {
diff --git a/invidious/README.md b/invidious/README.md
new file mode 100644
index 00000000..0f91fa02
--- /dev/null
+++ b/invidious/README.md
@@ -0,0 +1,4 @@
+invidious Addon for Friendica
+==========================
+
+This addon will replace "youtube.com" with the chosen Invidious instance
diff --git a/invidious/invidious.php b/invidious/invidious.php
new file mode 100644
index 00000000..7153aab9
--- /dev/null
+++ b/invidious/invidious.php
@@ -0,0 +1,104 @@
+
+ * Author: Michael Vogel
+ * Status: Unsupported
+ * Note: Please use the URL Replace addon instead
+ */
+
+use Friendica\Core\Hook;
+use Friendica\Core\Renderer;
+use Friendica\DI;
+
+CONST INVIDIOUS_DEFAULT = 'https://invidio.us';
+
+function invidious_install()
+{
+ Hook::register('prepare_body_final', __FILE__, 'invidious_render');
+ Hook::register('addon_settings', __FILE__, 'invidious_settings');
+ Hook::register('addon_settings_post', __FILE__, 'invidious_settings_post');
+}
+
+/* Handle the send data from the admin settings
+ */
+function invidious_addon_admin_post()
+{
+ DI::config()->set('invidious', 'server', trim($_POST['invidiousserver'], " \n\r\t\v\x00/"));
+}
+
+/* Hook into the admin settings to let the admin choose an
+ * invidious server to use for the replacement.
+ */
+function invidious_addon_admin(string &$o)
+{
+ $invidiousserver = DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT);
+ $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/invidious/');
+ $o = Renderer::replaceMacros($t, [
+ '$settingdescription' => DI::l10n()->t('Which Invidious server shall be used for the replacements in the post bodies? Use the URL with servername and protocol. See %s for a list of available public Invidious servers.', 'https://redirect.invidious.io'),
+ '$invidiousserver' => ['invidiousserver', DI::l10n()->t('Invidious server'), $invidiousserver, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/ ')],
+ '$submit' => DI::l10n()->t('Save Settings'),
+ ]);
+}
+
+function invidious_settings(array &$data)
+{
+ if (!DI::userSession()->getLocalUserId()) {
+ return;
+ }
+
+ $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'enabled');
+ $server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT));
+
+ $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/invidious/');
+ $html = Renderer::replaceMacros($t, [
+ '$enabled' => ['enabled', DI::l10n()->t('Replace Youtube links with links to an Invidious server'), $enabled, DI::l10n()->t('If enabled, Youtube links are replaced with the links to the specified Invidious server.')],
+ '$server' => ['server', DI::l10n()->t('Invidious server'), $server, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/ ')],
+ ]);
+
+ $data = [
+ 'addon' => 'invidious',
+ 'title' => DI::l10n()->t('Invidious Settings'),
+ 'html' => $html,
+ ];
+}
+
+function invidious_settings_post(array &$b)
+{
+ if (!DI::userSession()->getLocalUserId() || empty($_POST['invidious-submit'])) {
+ return;
+ }
+
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'enabled', (bool)$_POST['enabled']);
+
+ $server = trim($_POST['server'], " \n\r\t\v\x00/");
+ if ($server != DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT) && !empty($server)) {
+ DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'server', $server);
+ } else {
+ DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'invidious', 'server');
+ }
+}
+
+/*
+ * replace "youtube.com" with the chosen Invidious instance
+ */
+function invidious_render(array &$b)
+{
+ if (!DI::userSession()->getLocalUserId() || !DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'enabled')) {
+ return;
+ }
+
+ $original = $b['html'];
+ $server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT));
+
+ $b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/watch\?v=(.*?)~ism", $server . '/watch?v=$1', $b['html']);
+ $b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/embed/(.*?)~ism", $server . '/embed/$1', $b['html']);
+ $b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/shorts/(.*?)~ism", $server . '/shorts/$1', $b['html']);
+ $b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
+
+ if ($original != $b['html']) {
+ $b['html'] .= '' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $server) . '
';
+ }
+}
diff --git a/invidious/lang/C/messages.po b/invidious/lang/C/messages.po
new file mode 100644
index 00000000..b9de496c
--- /dev/null
+++ b/invidious/lang/C/messages.po
@@ -0,0 +1,58 @@
+# ADDON invidious
+# Copyright (C)
+# This file is distributed under the same license as the Friendica invidious addon package.
+#
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-12-18 17:23+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: invidious.php:39
+#, php-format
+msgid ""
+"Which Invidious server shall be used for the replacements in the post "
+"bodies? Use the URL with servername and protocol. See %s for a list of "
+"available public Invidious servers."
+msgstr ""
+
+#: invidious.php:40 invidious.php:57
+msgid "Invidious server"
+msgstr ""
+
+#: invidious.php:40 invidious.php:57
+#, php-format
+msgid "See %s for a list of available Invidious servers."
+msgstr ""
+
+#: invidious.php:41
+msgid "Save Settings"
+msgstr ""
+
+#: invidious.php:56
+msgid "Replace Youtube links with links to an Invidious server"
+msgstr ""
+
+#: invidious.php:56
+msgid ""
+"If enabled, Youtube links are replaced with the links to the specified "
+"Invidious server."
+msgstr ""
+
+#: invidious.php:62
+msgid "Invidious Settings"
+msgstr ""
+
+#: invidious.php:101
+#, php-format
+msgid "(Invidious addon enabled: YouTube links via %s)"
+msgstr ""
diff --git a/invidious/templates/admin.tpl b/invidious/templates/admin.tpl
new file mode 100644
index 00000000..1db85ff9
--- /dev/null
+++ b/invidious/templates/admin.tpl
@@ -0,0 +1,5 @@
+{{$settingdescription}}
+
+{{include file="field_input.tpl" field=$invidiousserver}}
+
+
diff --git a/invidious/templates/settings.tpl b/invidious/templates/settings.tpl
new file mode 100644
index 00000000..387286ef
--- /dev/null
+++ b/invidious/templates/settings.tpl
@@ -0,0 +1,2 @@
+{{include file="field_checkbox.tpl" field=$enabled}}
+{{include file="field_input.tpl" field=$server}}
diff --git a/js_upload/js_upload.php b/js_upload/js_upload.php
index 089cb7e2..786fc3c2 100644
--- a/js_upload/js_upload.php
+++ b/js_upload/js_upload.php
@@ -7,11 +7,11 @@
* Maintainer: Hypolite Petovan
*/
-use Friendica\App;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\DI;
+use Friendica\Util\Images;
use Friendica\Util\Strings;
global $js_upload_jsonresponse;
@@ -20,9 +20,9 @@ global $js_upload_result;
function js_upload_install()
{
Hook::register('photo_upload_form', __FILE__, 'js_upload_form');
- Hook::register('photo_post_init', __FILE__, 'js_upload_post_init');
- Hook::register('photo_post_file', __FILE__, 'js_upload_post_file');
- Hook::register('photo_post_end', __FILE__, 'js_upload_post_end');
+ Hook::register('photo_post_init', __FILE__, 'js_upload_post_init');
+ Hook::register('photo_post_file', __FILE__, 'js_upload_post_file');
+ Hook::register('photo_post_end', __FILE__, 'js_upload_post_end');
}
function js_upload_form(array &$b)
@@ -34,11 +34,11 @@ function js_upload_form(array &$b)
$tpl = Renderer::getMarkupTemplate('js_upload.tpl', 'addon/js_upload');
$b['addon_text'] .= Renderer::replaceMacros($tpl, [
- '$upload_msg' => DI::l10n()->t('Select files for upload'),
- '$drop_msg' => DI::l10n()->t('Drop files here to upload'),
- '$cancel' => DI::l10n()->t('Cancel'),
- '$failed' => DI::l10n()->t('Failed'),
- '$post_url' => $b['post_url'],
+ '$upload_msg' => DI::l10n()->t('Select files for upload'),
+ '$drop_msg' => DI::l10n()->t('Drop files here to upload'),
+ '$cancel' => DI::l10n()->t('Cancel'),
+ '$failed' => DI::l10n()->t('Failed'),
+ '$post_url' => $b['post_url'],
'$maximagesize' => Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize')),
]);
}
@@ -48,7 +48,10 @@ function js_upload_post_init(array &$b)
global $js_upload_result, $js_upload_jsonresponse;
// list of valid extensions
- $allowedExtensions = ['jpeg', 'gif', 'png', 'jpg'];
+ $allowedExtensions = [];
+ foreach (Images::IMAGETYPES as $type) {
+ $allowedExtensions[] = image_type_to_extension($type, false);
+ }
// max file size in bytes
$sizeLimit = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
@@ -75,10 +78,9 @@ function js_upload_post_file(array &$b)
$result = $js_upload_result;
- $b['src'] = $result['path'];
+ $b['src'] = $result['path'];
$b['filename'] = $result['filename'];
$b['filesize'] = filesize($b['src']);
-
}
function js_upload_post_end(int &$b)
@@ -179,11 +181,11 @@ class qqUploadedFileForm
class qqFileUploader
{
- private $allowedExtensions = [];
- private $sizeLimit = 10485760;
+ private $allowedExtensions;
+ private $sizeLimit;
private $file;
- function __construct(array $allowedExtensions = [], $sizeLimit = 10485760)
+ function __construct(array $allowedExtensions = [], $sizeLimit)
{
$allowedExtensions = array_map('strtolower', $allowedExtensions);
@@ -197,7 +199,6 @@ class qqFileUploader
} else {
$this->file = false;
}
-
}
/**
@@ -216,11 +217,9 @@ class qqFileUploader
}
// if ($size > $this->sizeLimit) {
-
// return array('error' => DI::l10n()->t('Uploaded file is too large'));
// }
-
$maximagesize = Strings::getBytesFromShorthand(DI::config()->get('system', 'maximagesize'));
if (($maximagesize) && ($size > $maximagesize)) {
@@ -241,14 +240,14 @@ class qqFileUploader
if ($this->file->save()) {
return [
- 'success' => true,
- 'path' => $this->file->getPath(),
+ 'success' => true,
+ 'path' => $this->file->getPath(),
'filename' => $filename . '.' . $ext
];
} else {
return [
- 'error' => DI::l10n()->t('Upload was cancelled, or server error encountered'),
- 'path' => $this->file->getPath(),
+ 'error' => DI::l10n()->t('Upload was cancelled, or server error encountered'),
+ 'path' => $this->file->getPath(),
'filename' => $filename . '.' . $ext
];
}
diff --git a/js_upload/lang/C/messages.po b/js_upload/lang/C/messages.po
index 4d16fe17..0d607bd5 100644
--- a/js_upload/lang/C/messages.po
+++ b/js_upload/lang/C/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-03-23 23:53-0400\n"
+"POT-Creation-Date: 2023-06-03 15:49-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,40 +17,40 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: js_upload.php:34
+#: js_upload.php:37
msgid "Select files for upload"
msgstr ""
-#: js_upload.php:35
+#: js_upload.php:38
msgid "Drop files here to upload"
msgstr ""
-#: js_upload.php:36
+#: js_upload.php:39
msgid "Cancel"
msgstr ""
-#: js_upload.php:37
+#: js_upload.php:40
msgid "Failed"
msgstr ""
-#: js_upload.php:215
+#: js_upload.php:209
msgid "No files were uploaded."
msgstr ""
-#: js_upload.php:221
+#: js_upload.php:215
msgid "Uploaded file is empty"
msgstr ""
-#: js_upload.php:233
+#: js_upload.php:227
#, php-format
msgid "Image exceeds size limit of %s"
msgstr ""
-#: js_upload.php:245
+#: js_upload.php:239
#, php-format
msgid "File has an invalid extension, it should be one of %s."
msgstr ""
-#: js_upload.php:256
+#: js_upload.php:250
msgid "Upload was cancelled, or server error encountered"
msgstr ""
diff --git a/js_upload/templates/js_upload.tpl b/js_upload/templates/js_upload.tpl
index f45b495c..b482cd2b 100644
--- a/js_upload/templates/js_upload.tpl
+++ b/js_upload/templates/js_upload.tpl
@@ -35,18 +35,18 @@
let albumElm = document.getElementById('photos-upload-album-select');
let contact_allow = document.querySelector('[name="contact_allow"]:not(:disabled)');
- let group_allow = document.querySelector('[name="group_allow"]:not(:disabled)');
- let contact_deny = document.querySelector('[name="contact_deny"]:not(:disabled)');
- let group_deny = document.querySelector('[name="group_deny"]:not(:disabled)');
+ let circle_allow = document.querySelector('[name="circle_allow"]:not(:disabled)');
+ let contact_deny = document.querySelector('[name="contact_deny"]:not(:disabled)');
+ let circle_deny = document.querySelector('[name="circle_deny"]:not(:disabled)');
uploader.setParams({
newalbum : newalbumElm ? newalbumElm.value : '',
album : albumElm ? albumElm.value : '',
not_visible : document.getElementById('photos-upload-noshare').checked,
contact_allow : contact_allow ? contact_allow.value : '',
- group_allow : group_allow ? group_allow.value : '',
+ circle_allow : circle_allow ? circle_allow.value : '',
contact_deny : contact_deny ? contact_deny.value : '',
- group_deny : group_deny ? group_deny.value : '',
+ circle_deny : circle_deny ? circle_deny.value : '',
});
}
});
diff --git a/langfilter/lang/ru/messages.po b/langfilter/lang/ru/messages.po
index e1fbc9e8..45ad7b3d 100644
--- a/langfilter/lang/ru/messages.po
+++ b/langfilter/lang/ru/messages.po
@@ -4,63 +4,59 @@
#
#
# Translators:
-# Alexander An , 2020
+# Alexander An , 2020,2023
# Stanislav N. , 2018
msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-10-03 22:02-0400\n"
-"PO-Revision-Date: 2020-10-09 17:48+0000\n"
-"Last-Translator: Alexander An \n"
-"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n"
+"POT-Creation-Date: 2021-11-21 19:15-0500\n"
+"PO-Revision-Date: 2015-07-25 08:05+0000\n"
+"Last-Translator: Alexander An , 2020,2023\n"
+"Language-Team: Russian (http://app.transifex.com/Friendica/friendica/language/ru/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ru\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
-#: langfilter.php:52
-msgid "Language Filter"
-msgstr "Языковой фильтр"
-
-#: langfilter.php:53
+#: langfilter.php:49
msgid ""
"This addon tries to identify the language posts are written in. If it does "
"not match any language specified below, posts will be hidden by collapsing "
"them."
-msgstr "Это дополнение пытается идентифицировать язык, на котором написаны посты. Если язык не соответствует ни одному, указанному ниже, то такие посты будут скрыты."
+msgstr "Это дополнение пытается идентифицировать язык, на котором сделаны записи. Если язык не соответствует ни одному, указанному ниже, то такие посты будут свёрнуты."
-#: langfilter.php:54
+#: langfilter.php:50
msgid "Use the language filter"
msgstr "Использовать языковой фильтр"
-#: langfilter.php:55
+#: langfilter.php:51
msgid "Able to read"
msgstr "Возможность читать"
-#: langfilter.php:55
+#: langfilter.php:51
msgid ""
"List of abbreviations (ISO 639-1 codes) for languages you speak, comma "
"separated. For example \"de,it\"."
msgstr "Список аббревиатур (кодов по ISO 639-1 ) для языков, на которых вы говорите. Например, \"ru,en\"."
-#: langfilter.php:56
+#: langfilter.php:52
msgid "Minimum confidence in language detection"
msgstr "Минимальная уверенность в определении языка"
-#: langfilter.php:56
+#: langfilter.php:52
msgid ""
"Minimum confidence in language detection being correct, from 0 to 100. Posts"
" will not be filtered when the confidence of language detection is below "
"this percent value."
msgstr "Минимальная уверенность в правильном определении языка, от 0 до 100. Посты не будут скрыты, если уверенность в правильном определении языка в процентах ниже этого значения."
-#: langfilter.php:57
+#: langfilter.php:53
msgid "Minimum length of message body"
msgstr "Минимальная длина тела сообщения"
-#: langfilter.php:57
+#: langfilter.php:53
msgid ""
"Minimum number of characters in message body for filter to be used. Posts "
"shorter than this will not be filtered. Note: Language detection is "
@@ -68,10 +64,14 @@ msgid ""
msgstr "Минимальное количество знаков в теле сообщения для применения фильтрации. Посты, длина которых меньше указанного значения, не будут отфильтрованы. Обратите внимание, что определение языка работает ненадежно для небольших постов (<200 символов)."
#: langfilter.php:58
+msgid "Language Filter"
+msgstr "Языковой фильтр"
+
+#: langfilter.php:60
msgid "Save Settings"
msgstr "Сохранить настройки"
-#: langfilter.php:189
+#: langfilter.php:193
#, php-format
msgid "Filtered language: %s"
msgstr "Отфильтрованный язык: %s"
diff --git a/langfilter/lang/ru/strings.php b/langfilter/lang/ru/strings.php
index 0489bd4f..1f5619f7 100644
--- a/langfilter/lang/ru/strings.php
+++ b/langfilter/lang/ru/strings.php
@@ -5,8 +5,7 @@ function string_plural_select_ru($n){
$n = intval($n);
if ($n%10==1 && $n%100!=11) { return 0; } else if ($n%10>=2 && $n%10<=4 && ($n%100<12 || $n%100>14)) { return 1; } else if ($n%10==0 || ($n%10>=5 && $n%10<=9) || ($n%100>=11 && $n%100<=14)) { return 2; } else { return 3; }
}}
-$a->strings['Language Filter'] = 'Языковой фильтр';
-$a->strings['This addon tries to identify the language posts are written in. If it does not match any language specified below, posts will be hidden by collapsing them.'] = 'Это дополнение пытается идентифицировать язык, на котором написаны посты. Если язык не соответствует ни одному, указанному ниже, то такие посты будут скрыты.';
+$a->strings['This addon tries to identify the language posts are written in. If it does not match any language specified below, posts will be hidden by collapsing them.'] = 'Это дополнение пытается идентифицировать язык, на котором сделаны записи. Если язык не соответствует ни одному, указанному ниже, то такие посты будут свёрнуты.';
$a->strings['Use the language filter'] = 'Использовать языковой фильтр';
$a->strings['Able to read'] = 'Возможность читать';
$a->strings['List of abbreviations (ISO 639-1 codes) for languages you speak, comma separated. For example "de,it".'] = 'Список аббревиатур (кодов по ISO 639-1 ) для языков, на которых вы говорите. Например, "ru,en".';
@@ -14,5 +13,6 @@ $a->strings['Minimum confidence in language detection'] = 'Минимальна
$a->strings['Minimum confidence in language detection being correct, from 0 to 100. Posts will not be filtered when the confidence of language detection is below this percent value.'] = 'Минимальная уверенность в правильном определении языка, от 0 до 100. Посты не будут скрыты, если уверенность в правильном определении языка в процентах ниже этого значения.';
$a->strings['Minimum length of message body'] = 'Минимальная длина тела сообщения';
$a->strings['Minimum number of characters in message body for filter to be used. Posts shorter than this will not be filtered. Note: Language detection is unreliable for short content (<200 characters).'] = 'Минимальное количество знаков в теле сообщения для применения фильтрации. Посты, длина которых меньше указанного значения, не будут отфильтрованы. Обратите внимание, что определение языка работает ненадежно для небольших постов (<200 символов).';
+$a->strings['Language Filter'] = 'Языковой фильтр';
$a->strings['Save Settings'] = 'Сохранить настройки';
$a->strings['Filtered language: %s'] = 'Отфильтрованный язык: %s';
diff --git a/langfilter/langfilter.php b/langfilter/langfilter.php
index 61b357f6..e5efa8fb 100644
--- a/langfilter/langfilter.php
+++ b/langfilter/langfilter.php
@@ -122,7 +122,7 @@ function langfilter_prepare_body_content_filter(&$hook_data)
$naked_body = strip_tags(
$hook_data['item']['rendered-html']
??''?: // Equivalent of !empty()
- BBCode::convert($hook_data['item']['body'], false, BBCode::ACTIVITYPUB, true)
+ BBCode::convertForUriId($hook_data['item']['uri-id'], $hook_data['item']['body'], BBCode::ACTIVITYPUB)
);
$naked_body = preg_replace('#\s+#', ' ', trim($naked_body));
@@ -163,7 +163,7 @@ function langfilter_prepare_body_content_filter(&$hook_data)
return;
}
- $lang = $iso639->languageByCode1($iso2);
+ $lang = $iso639->languageByCode1(substr($iso2, 0, 2));
} else {
$opts = $hook_data['item']['postopts'];
if (!$opts) {
diff --git a/libertree/lang/C/messages.po b/libertree/lang/C/messages.po
index 6feeef8d..3162b6a7 100644
--- a/libertree/lang/C/messages.po
+++ b/libertree/lang/C/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-21 19:17-0500\n"
+"POT-Creation-Date: 2023-06-03 15:49-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -21,22 +21,22 @@ msgstr ""
msgid "Post to libertree"
msgstr ""
-#: libertree.php:60
+#: libertree.php:59
msgid "Enable Libertree Post Addon"
msgstr ""
-#: libertree.php:61
+#: libertree.php:60
msgid "Libertree site URL"
msgstr ""
-#: libertree.php:62
+#: libertree.php:61
msgid "Libertree API token"
msgstr ""
-#: libertree.php:63
+#: libertree.php:62
msgid "Post to Libertree by default"
msgstr ""
-#: libertree.php:68
+#: libertree.php:67
msgid "Libertree Export"
msgstr ""
diff --git a/libertree/libertree.php b/libertree/libertree.php
index 8e8c9ba9..f69c0aab 100644
--- a/libertree/libertree.php
+++ b/libertree/libertree.php
@@ -151,7 +151,7 @@ function libertree_send(array &$b)
}
// Dont't post if the post doesn't belong to us.
- // This is a check for forum postings
+ // This is a check for group postings
$self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]);
if ($b['contact-id'] != $self['id']) {
return;
@@ -201,7 +201,7 @@ function libertree_send(array &$b)
// 'token' => $ltree_api_token
];
- $result = DI::httpClient()->post($ltree_blog, $params)->getBody();
+ $result = DI::httpClient()->post($ltree_blog, $params)->getBodyString();
Logger::notice('libertree: ' . $result);
}
}
diff --git a/ljpost/ljpost.php b/ljpost/ljpost.php
index f6f2b79a..fac44767 100644
--- a/ljpost/ljpost.php
+++ b/ljpost/ljpost.php
@@ -207,7 +207,7 @@ EOT;
Logger::debug('ljpost: data: ' . $xml);
if ($lj_blog !== 'test') {
- $x = DI::httpClient()->post($lj_blog, $xml, ['Content-Type' => 'text/xml'])->getBody();
+ $x = DI::httpClient()->post($lj_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString();
}
Logger::info('posted to livejournal: ' . ($x) ? $x : '');
diff --git a/mailstream/lang/fr/messages.po b/mailstream/lang/fr/messages.po
index 488d4c08..043181c5 100644
--- a/mailstream/lang/fr/messages.po
+++ b/mailstream/lang/fr/messages.po
@@ -4,6 +4,7 @@
#
#
# Translators:
+# Florent C., 2023
# Nicolas Derive, 2022
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
# StefOfficiel , 2015
@@ -13,8 +14,8 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:15-0500\n"
"PO-Revision-Date: 2014-06-23 09:54+0000\n"
-"Last-Translator: Nicolas Derive, 2022\n"
-"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
+"Last-Translator: Florent C., 2023\n"
+"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -33,68 +34,72 @@ msgstr "Adresse de courriel de laquelle les éléments du flux sembleront proven
msgid "Save Settings"
msgstr "Sauvegarder les paramètres"
-#: mailstream.php:301
+#: mailstream.php:311
msgid "Re:"
msgstr "Re :"
-#: mailstream.php:314 mailstream.php:317
+#: mailstream.php:324 mailstream.php:327
msgid "Friendica post"
msgstr "Message Friendica"
-#: mailstream.php:320
+#: mailstream.php:330
msgid "Diaspora post"
msgstr "Message Diaspora"
-#: mailstream.php:330
+#: mailstream.php:340
msgid "Feed item"
msgstr "Élément du flux"
-#: mailstream.php:333
+#: mailstream.php:343
msgid "Email"
msgstr "Courriel"
-#: mailstream.php:335
+#: mailstream.php:345
msgid "Friendica Item"
msgstr "Élément de Friendica"
-#: mailstream.php:404
+#: mailstream.php:419
msgid "Upstream"
msgstr "En amont"
-#: mailstream.php:405
+#: mailstream.php:420
+msgid "URI"
+msgstr "URI"
+
+#: mailstream.php:421
msgid "Local"
msgstr "Local"
-#: mailstream.php:481
+#: mailstream.php:499
msgid "Enabled"
msgstr "Activer"
-#: mailstream.php:486
+#: mailstream.php:504
msgid "Email Address"
msgstr "Adresse de courriel"
-#: mailstream.php:488
+#: mailstream.php:506
msgid "Leave blank to use your account email address"
msgstr "Laissez vide pour utiliser l'adresse de courriel de votre compte"
-#: mailstream.php:492
+#: mailstream.php:510
msgid "Exclude Likes"
msgstr "Exclure les \"j'aime\""
-#: mailstream.php:494
+#: mailstream.php:512
msgid "Check this to omit mailing \"Like\" notifications"
msgstr "Cochez ceci pour éviter d'envoyer les notifications des \"J'aime\""
-#: mailstream.php:498
+#: mailstream.php:516
msgid "Attach Images"
msgstr "Attacher les images"
-#: mailstream.php:500
+#: mailstream.php:518
msgid ""
"Download images in posts and attach them to the email. Useful for reading "
"email while offline."
msgstr "Télécharger les images des messages et les attacher au courriel. Utile pour les les courriels hors-ligne."
-#: mailstream.php:507
+#: mailstream.php:525
msgid "Mail Stream Settings"
msgstr "Paramètres de Mail Stream"
diff --git a/mailstream/lang/fr/strings.php b/mailstream/lang/fr/strings.php
index bfaf4389..a21d80b8 100644
--- a/mailstream/lang/fr/strings.php
+++ b/mailstream/lang/fr/strings.php
@@ -15,6 +15,7 @@ $a->strings['Feed item'] = 'Élément du flux';
$a->strings['Email'] = 'Courriel';
$a->strings['Friendica Item'] = 'Élément de Friendica';
$a->strings['Upstream'] = 'En amont';
+$a->strings['URI'] = 'URI';
$a->strings['Local'] = 'Local';
$a->strings['Enabled'] = 'Activer';
$a->strings['Email Address'] = 'Adresse de courriel';
diff --git a/mailstream/lang/hu/messages.po b/mailstream/lang/hu/messages.po
index 3302564d..66d09299 100644
--- a/mailstream/lang/hu/messages.po
+++ b/mailstream/lang/hu/messages.po
@@ -4,15 +4,15 @@
#
#
# Translators:
-# Balázs Úr, 2020-2021
+# Balázs Úr, 2020-2021,2023
msgid ""
msgstr ""
"Project-Id-Version: friendica\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-21 19:15-0500\n"
"PO-Revision-Date: 2014-06-23 09:54+0000\n"
-"Last-Translator: Balázs Úr, 2020-2021\n"
-"Language-Team: Hungarian (http://www.transifex.com/Friendica/friendica/language/hu/)\n"
+"Last-Translator: Balázs Úr, 2020-2021,2023\n"
+"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -31,68 +31,72 @@ msgstr "E-mail-cím, ahonnan úgy tűnik, hogy a folyam elemei származnak."
msgid "Save Settings"
msgstr "Beállítások mentése"
-#: mailstream.php:301
+#: mailstream.php:311
msgid "Re:"
msgstr "Vá:"
-#: mailstream.php:314 mailstream.php:317
+#: mailstream.php:324 mailstream.php:327
msgid "Friendica post"
msgstr "Friendica-bejegyzés"
-#: mailstream.php:320
+#: mailstream.php:330
msgid "Diaspora post"
msgstr "Diaspora-bejegyzés"
-#: mailstream.php:330
+#: mailstream.php:340
msgid "Feed item"
msgstr "Hírforráselem"
-#: mailstream.php:333
+#: mailstream.php:343
msgid "Email"
msgstr "E-mail"
-#: mailstream.php:335
+#: mailstream.php:345
msgid "Friendica Item"
msgstr "Friendica-elem"
-#: mailstream.php:404
+#: mailstream.php:419
msgid "Upstream"
msgstr "Távoli"
-#: mailstream.php:405
+#: mailstream.php:420
+msgid "URI"
+msgstr "URI"
+
+#: mailstream.php:421
msgid "Local"
msgstr "Helyi"
-#: mailstream.php:481
+#: mailstream.php:499
msgid "Enabled"
msgstr "Engedélyezve"
-#: mailstream.php:486
+#: mailstream.php:504
msgid "Email Address"
msgstr "E-mail-cím"
-#: mailstream.php:488
+#: mailstream.php:506
msgid "Leave blank to use your account email address"
msgstr "Hagyja üresen a fiókja e-mail-címének használatához"
-#: mailstream.php:492
+#: mailstream.php:510
msgid "Exclude Likes"
msgstr "Kedvelések kizárása"
-#: mailstream.php:494
+#: mailstream.php:512
msgid "Check this to omit mailing \"Like\" notifications"
msgstr "Jelölje be ezt a „Tetszik” értesítések elküldésének kihagyásához"
-#: mailstream.php:498
+#: mailstream.php:516
msgid "Attach Images"
msgstr "Képek csatolása"
-#: mailstream.php:500
+#: mailstream.php:518
msgid ""
"Download images in posts and attach them to the email. Useful for reading "
"email while offline."
msgstr "Képek letöltése a bejegyzésekből és csatolás az e-mailhez. Hasznos az e-mailek kapcsolat nélküli olvasásakor."
-#: mailstream.php:507
+#: mailstream.php:525
msgid "Mail Stream Settings"
msgstr "Levelezőfolyam beállításai"
diff --git a/mailstream/lang/hu/strings.php b/mailstream/lang/hu/strings.php
index 5a7383bd..5b1e5a51 100644
--- a/mailstream/lang/hu/strings.php
+++ b/mailstream/lang/hu/strings.php
@@ -15,6 +15,7 @@ $a->strings['Feed item'] = 'Hírforráselem';
$a->strings['Email'] = 'E-mail';
$a->strings['Friendica Item'] = 'Friendica-elem';
$a->strings['Upstream'] = 'Távoli';
+$a->strings['URI'] = 'URI';
$a->strings['Local'] = 'Helyi';
$a->strings['Enabled'] = 'Engedélyezve';
$a->strings['Email Address'] = 'E-mail-cím';
diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php
index 542a1a42..92f29f93 100644
--- a/mailstream/mailstream.php
+++ b/mailstream/mailstream.php
@@ -66,10 +66,9 @@ function mailstream_module() {}
/**
* Adds an item in "addon features" in the admin menu of the site
*
- * @param App $a App object (unused)
* @param string $o HTML form data
*/
-function mailstream_addon_admin(App $a, string &$o)
+function mailstream_addon_admin(string &$o)
{
$frommail = DI::config()->get('mailstream', 'frommail');
$template = Renderer::getMarkupTemplate('admin.tpl', 'addon/mailstream/');
@@ -103,14 +102,14 @@ function mailstream_addon_admin_post()
*/
function mailstream_generate_id(string $uri): string
{
- $host = DI::baseUrl()->getHostname();
+ $host = DI::baseUrl()->getHost();
$resource = hash('md5', $uri);
$message_id = "<" . $resource . "@" . $host . ">";
Logger::debug('mailstream: Generated message ID ' . $message_id . ' for URI ' . $uri);
return $message_id;
}
-function mailstream_send_hook(App $a, array $data)
+function mailstream_send_hook(array $data)
{
$criteria = array('uid' => $data['uid'], 'contact-id' => $data['contact-id'], 'uri' => $data['uri']);
$item = Post::selectFirst([], $criteria);
@@ -119,13 +118,46 @@ function mailstream_send_hook(App $a, array $data)
return;
}
- $user = User::getById($item['uid']);
- if (empty($user)) {
- Logger::error('mailstream_send_hook could not fund user', ['uid' => $item['uid']]);
+ if ($item['deleted']) {
+ Logger::debug('mailstream_send_hook skipping deleted item', ['guid' => $item['guid']]);
return;
}
- if (!mailstream_send($data['message_id'], $item, $user)) {
+ $user = User::getById($item['uid']);
+ if (empty($user)) {
+ Logger::error('mailstream_send_hook could not find user', ['uid' => $item['uid']]);
+ return;
+ }
+
+ $author = DBA::selectFirst('contact', ['nick', 'blocked', 'uri-id'], ['id' => $data['author-id'], 'self' => false]);
+ if (!DBA::isResult($author)) {
+ Logger::error('mailstream_send_hook could not find author', ['guid' => $item['guid'], 'author-id' => $data['author-id']]);
+ return;
+ }
+ if ($author['blocked']) {
+ Logger::info('mailstream_send_hook author is blocked', ['guid' => $item['guid'], 'author-id' => $data['author-id']]);
+ return;
+ }
+ $collapsed = false;
+ $user_contact = DBA::selectFirst('user-contact', ['cid', 'blocked', 'ignored', 'collapsed'], ['uid' => $item['uid'], 'uri-id' => $item['author-uri-id']]);
+ if (!DBA::isResult($user_contact)) {
+ $user_contact = DBA::selectFirst('user-contact', ['cid', 'blocked', 'ignored', 'collapsed'], ['uid' => $item['uid'], 'cid' => $item['author-id']]);
+ }
+ if (DBA::isResult($user_contact)) {
+ if ($user_contact['blocked']) {
+ Logger::info('mailstream_send_hook author is blocked', ['guid' => $item['guid'], 'cid' => $user_contact['cid']]);
+ return;
+ }
+ if ($user_contact['ignored']) {
+ Logger::info('mailstream_send_hook author is ignored', ['guid' => $item['guid'], 'cid' => $user_contact['cid']]);
+ return;
+ }
+ if ($user_contact['collapsed']) {
+ $collapsed = true;
+ }
+ }
+
+ if (!mailstream_send($data['message_id'], $item, $user, $collapsed)) {
Logger::debug('mailstream_send_hook send failed, will retry', $data);
if (!Worker::defer()) {
Logger::error('mailstream_send_hook failed and could not defer', $data);
@@ -138,20 +170,19 @@ function mailstream_send_hook(App $a, array $data)
* mailstream is enabled and the necessary data is available, forks a
* workerqueue item to send the email.
*
- * @param App $a App object (unused)
* @param array $item content of the item (may or may not already be stored in the item table)
* @return void
*/
-function mailstream_post_hook(App $a, array &$item)
+function mailstream_post_hook(array &$item)
{
mailstream_check_version();
- if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) {
- Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]);
+ if ($item['uid'] === 0) {
+ Logger::debug('mailstream: root user, skipping item ' . $item['id']);
return;
}
- if (!$item['uid']) {
- Logger::debug('mailstream: no uid for item ' . $item['id']);
+ if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) {
+ Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]);
return;
}
if (!$item['contact-id']) {
@@ -171,6 +202,10 @@ function mailstream_post_hook(App $a, array &$item)
Logger::debug('mailstream: like item ' . $item['id']);
return;
}
+ if ($item['verb'] == Activity::DISLIKE) {
+ Logger::debug('mailstream: dislike item ' . $item['id']);
+ return;
+ }
}
$message_id = mailstream_generate_id($item['uri']);
@@ -178,6 +213,7 @@ function mailstream_post_hook(App $a, array &$item)
$send_hook_data = [
'uid' => $item['uid'],
'contact-id' => $item['contact-id'],
+ 'author-id' => $item['author-id'],
'uri' => $item['uri'],
'message_id' => $message_id,
'tries' => 0,
@@ -216,9 +252,19 @@ function mailstream_do_images(array &$item, array &$attachments)
}
$cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-');
- $curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar);
+ try {
+ $curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar);
+ if (!$curlResult->isSuccess()) {
+ Logger::debug('mailstream: fetch image url failed', [
+ 'url' => $url, 'item_id' => $item['id'], 'return_code' => $curlResult->getReturnCode()]);
+ continue;
+ }
+ } catch (InvalidArgumentException $e) {
+ Logger::error('mailstream_do_images exception fetching url', ['url' => $url, 'item_id' => $item['id']]);
+ continue;
+ }
$attachments[$url] = [
- 'data' => $curlResult->getBody(),
+ 'data' => $curlResult->getBodyString(),
'guid' => hash('crc32', $url),
'filename' => basename($components['path']),
'type' => $curlResult->getContentType()
@@ -255,12 +301,13 @@ function mailstream_sender(array $item): string
* Converts a bbcode-encoded subject line into a plaintext version suitable for the subject line of an email
*
* @param string $subject bbcode-encoded subject line
+ * @param int $uri_id
*
* @return string plaintext subject line
*/
-function mailstream_decode_subject(string $subject): string
+function mailstream_decode_subject(string $subject, int $uri_id): string
{
- $html = BBCode::convert($subject);
+ $html = BBCode::convertForUriId($uri_id, $subject);
if (!$html) {
return $subject;
}
@@ -295,7 +342,7 @@ function mailstream_decode_subject(string $subject): string
function mailstream_subject(array $item): string
{
if ($item['title']) {
- return mailstream_decode_subject($item['title']);
+ return mailstream_decode_subject($item['title'], $item['uri-id']);
}
$parent = $item['thr-parent'];
// Don't look more than 100 levels deep for a subject, in case of loops
@@ -308,7 +355,7 @@ function mailstream_subject(array $item): string
break;
}
if ($parent_item['title']) {
- return DI::l10n()->t('Re:') . ' ' . mailstream_decode_subject($parent_item['title']);
+ return DI::l10n()->t('Re:') . ' ' . mailstream_decode_subject($parent_item['title'], $item['uri-id']);
}
$parent = $parent_item['thr-parent'];
}
@@ -330,7 +377,7 @@ function mailstream_subject(array $item): string
return DI::l10n()->t("Diaspora post");
}
if ($contact['network'] === 'face') {
- $text = mailstream_decode_subject($item['body']);
+ $text = mailstream_decode_subject($item['body'], $item['uri-id']);
// For some reason these do show up in Facebook
$text = preg_replace('/\xA0$/', '', $text);
$subject = (strlen($text) > 150) ? (substr($text, 0, 140) . '...') : $text;
@@ -351,10 +398,11 @@ function mailstream_subject(array $item): string
* @param string $message_id ID of the message (RFC 1036)
* @param array $item content of the item
* @param array $user results from the user table
+ * @param bool $collapsed true if the content should be hidden
*
* @return bool True if this message has been completed. False if it should be retried.
*/
-function mailstream_send(string $message_id, array $item, array $user): bool
+function mailstream_send(string $message_id, array $item, array $user, bool $collapsed): bool
{
if (!is_array($item)) {
Logger::error('mailstream_send item is empty', ['message_id' => $message_id]);
@@ -373,10 +421,16 @@ function mailstream_send(string $message_id, array $item, array $user): bool
require_once (dirname(__file__) . '/phpmailer/class.phpmailer.php');
- $item['body'] = Post\Media::addAttachmentsToBody($item['uri-id'], $item['body']);
+ if ($collapsed) {
+ $item['body'] = DI::l10n()->t('Content from %s is collapsed', $item['author-name']);
+ } else {
+ $item['body'] = Post\Media::addAttachmentsToBody($item['uri-id'], $item['body']);
+ }
$attachments = [];
- mailstream_do_images($item, $attachments);
+ if (!$collapsed) {
+ mailstream_do_images($item, $attachments);
+ }
$frommail = DI::config()->get('mailstream', 'frommail');
if ($frommail == '') {
$frommail = 'friendica@localhost.local';
@@ -414,7 +468,7 @@ function mailstream_send(string $message_id, array $item, array $user): bool
$template = Renderer::getMarkupTemplate('mail.tpl', 'addon/mailstream/');
$mail->AltBody = BBCode::toPlaintext($item['body']);
$item['body'] = BBCode::convertForUriId($item['uri-id'], $item['body'], BBCode::CONNECTORS);
- $item['url'] = DI::baseUrl()->get() . '/display/' . $item['guid'];
+ $item['url'] = DI::baseUrl() . '/display/' . $item['guid'];
$mail->Body = Renderer::replaceMacros($template, [
'$upstream' => DI::l10n()->t('Upstream'),
'$uri' => DI::l10n()->t('URI'),
@@ -468,7 +522,7 @@ function mailstream_convert_table_entries()
'message_id' => $ms_item_id['message-id'],
'tries' => 0);
if (!$ms_item_id['message-id'] || !strlen($ms_item_id['message-id'])) {
- Logger::info('mailstream_convert_table_entries: item has no message-id.', 'item' => $ms_item_id['id'], 'uri' => $ms_item_id['uri']]);
+ Logger::info('mailstream_convert_table_entries: item has no message-id.', ['item' => $ms_item_id['id'], 'uri' => $ms_item_id['uri']]);
continue;
}
Logger::info('mailstream_convert_table_entries: convert item to workerqueue', $send_hook_data);
@@ -480,11 +534,10 @@ function mailstream_convert_table_entries()
/**
* Form for configuring mailstream features for a user
*
- * @param App $a App object
* @param array $data Hook data array
* @throws \Friendica\Network\HTTPException\ServiceUnavailableException
*/
-function mailstream_addon_settings(App &$a, array &$data)
+function mailstream_addon_settings(array &$data)
{
$enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'mailstream', 'enabled');
$address = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'mailstream', 'address');
@@ -528,11 +581,10 @@ function mailstream_addon_settings(App &$a, array &$data)
/**
* Process data submitted to user's mailstream features form
- * @param App $a
* @param array $post POST data
* @return void
*/
-function mailstream_addon_settings_post(App $a, array $post)
+function mailstream_addon_settings_post(array $post)
{
if (!DI::userSession()->getLocalUserId() || empty($post['mailstream-submit'])) {
return;
diff --git a/markdown/markdown.php b/markdown/markdown.php
index 236fb297..6f459244 100644
--- a/markdown/markdown.php
+++ b/markdown/markdown.php
@@ -64,6 +64,7 @@ function markdown_post_local_start(&$request) {
// (right chevrons are used for quoting in Markdown)
// See https://github.com/friendica/friendica/issues/10634
$text = strtr($text, ['<' => '<']);
+ $text = str_replace('[*]', '[li]', $text);
return Markdown::toBBCode($text);
});
diff --git a/mastodoncustomemojis/mastodoncustomemojis.php b/mastodoncustomemojis/mastodoncustomemojis.php
index c84f1a4f..561262f1 100644
--- a/mastodoncustomemojis/mastodoncustomemojis.php
+++ b/mastodoncustomemojis/mastodoncustomemojis.php
@@ -15,7 +15,6 @@ use Friendica\Core\Cache\Enum\Duration;
use Friendica\Core\Hook;
use Friendica\Core\Protocol;
use Friendica\DI;
-use Friendica\Util\Proxy as ProxyUtils;
function mastodoncustomemojis_install()
{
@@ -82,13 +81,13 @@ function mastodoncustomemojis_fetch_custom_emojis_for_url($api_base_url)
$fetchResult = DI::httpClient()->fetchFull($api_url);
if ($fetchResult->isSuccess()) {
- $emojis_array = json_decode($fetchResult->getBody(), true);
+ $emojis_array = json_decode($fetchResult->getBodyString(), true);
if (is_array($emojis_array) && count($emojis_array)) {
foreach ($emojis_array as $emoji) {
if (!empty($emoji['shortcode']) && !empty($emoji['static_url'])) {
$return['texts'][] = ':' . $emoji['shortcode'] . ':';
- $return['icons'][] = ' ';
+ $return['icons'][] = ' ';
}
}
}
diff --git a/monolog/composer.json b/monolog/composer.json
index 9c7f32c3..9cf42dbe 100644
--- a/monolog/composer.json
+++ b/monolog/composer.json
@@ -1,23 +1,26 @@
{
- "name": "friendica-addons/monolog",
- "description": "Monolog can send your logs to files, sockets, inboxes, database, etc..",
- "type": "friendica-addon",
- "authors": [
- {
- "name": "Philipp Holzer",
- "email": "admin@philipp.info",
- "homepage": "https://blog.philipp.info",
- "role": "Developer"
- }
- ],
- "require": {
- "php": ">=7.0",
- "monolog/monolog": "^3.2"
- },
- "license": "3-clause BSD license",
- "config": {
- "optimize-autoloader": true,
- "autoloader-suffix": "MonologAddon",
- "preferred-install": "dist"
- }
+ "name": "friendica-addons/monolog",
+ "description": "Monolog can send your logs to files, sockets, inboxes, database, etc..",
+ "type": "friendica-addon",
+ "authors": [
+ {
+ "name": "Philipp Holzer",
+ "email": "admin@philipp.info",
+ "homepage": "https://blog.philipp.info",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": ">=7.3",
+ "monolog/monolog": "^2.9"
+ },
+ "license": "3-clause BSD license",
+ "config": {
+ "platform": {
+ "php": "7.4"
+ },
+ "optimize-autoloader": true,
+ "autoloader-suffix": "MonologAddon",
+ "preferred-install": "dist"
+ }
}
diff --git a/monolog/composer.lock b/monolog/composer.lock
index 0566f721..5d1da32f 100644
--- a/monolog/composer.lock
+++ b/monolog/composer.lock
@@ -4,45 +4,46 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e812bcd051a73d1c9b19c91ec88a6a21",
+ "content-hash": "037f2db47e77c9af2960dde65ebafa8d",
"packages": [
{
"name": "monolog/monolog",
- "version": "3.2.0",
+ "version": "2.9.2",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81"
+ "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/305444bc6fb6c89e490f4b34fa6e979584d7fa81",
- "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f",
+ "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "psr/log": "^2.0 || ^3.0"
+ "php": ">=7.2",
+ "psr/log": "^1.0.1 || ^2.0 || ^3.0"
},
"provide": {
- "psr/log-implementation": "3.0.0"
+ "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
},
"require-dev": {
- "aws/aws-sdk-php": "^3.0",
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
"ext-json": "*",
- "graylog2/gelf-php": "^1.4.2",
+ "graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8",
"php-amqplib/php-amqplib": "~2.4 || ^3",
- "phpstan/phpstan": "^1.4",
- "phpstan/phpstan-deprecation-rules": "^1.0",
- "phpstan/phpstan-strict-rules": "^1.1",
- "phpunit/phpunit": "^9.5.16",
- "predis/predis": "^1.1",
+ "phpspec/prophecy": "^1.15",
+ "phpstan/phpstan": "^0.12.91",
+ "phpunit/phpunit": "^8.5.14",
+ "predis/predis": "^1.1 || ^2.0",
+ "rollbar/rollbar": "^1.3 || ^2 || ^3",
"ruflin/elastica": "^7",
+ "swiftmailer/swiftmailer": "^5.3|^6.0",
"symfony/mailer": "^5.4 || ^6",
"symfony/mime": "^5.4 || ^6"
},
@@ -65,7 +66,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.x-dev"
+ "dev-main": "2.x-dev"
}
},
"autoload": {
@@ -101,34 +102,34 @@
"type": "tidelift"
}
],
- "time": "2022-07-24T12:00:55+00:00"
+ "time": "2023-10-27T15:25:26+00:00"
},
{
"name": "psr/log",
- "version": "3.0.0",
+ "version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
- "php": ">=8.0.0"
+ "php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.x-dev"
+ "dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
- "Psr\\Log\\": "src"
+ "Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -148,7 +149,7 @@
"psr",
"psr-3"
],
- "time": "2021-07-14T16:46:02+00:00"
+ "time": "2021-05-03T11:20:27+00:00"
}
],
"packages-dev": [],
@@ -158,8 +159,11 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=7.0"
+ "php": ">=7.3"
},
"platform-dev": [],
+ "platform-overrides": {
+ "php": "7.4"
+ },
"plugin-api-version": "1.1.0"
}
diff --git a/monolog/monolog.php b/monolog/monolog.php
index efdcb3fe..b13efff9 100644
--- a/monolog/monolog.php
+++ b/monolog/monolog.php
@@ -5,62 +5,3 @@
* Version: 1.0
* Author: Philipp Holzer
*/
-
-use Friendica\App;
-use Friendica\Core\Hook;
-use Friendica\Addon\monolog\src\IntrospectionProcessor;
-use Friendica\DI;
-use Psr\Log\LogLevel;
-
-require_once __DIR__ . '/vendor/autoload.php';
-
-function monolog_install()
-{
- Hook::register('logger_instance' , __FILE__, 'monolog_instance');
-}
-
-function monolog_uninstall()
-{
- Hook::unregister('logger_instance', __FILE__, 'monolog_instance');
-}
-
-function monolog_instance(array &$data)
-{
- if ($data['name'] !== 'monolog') {
- return;
- }
-
- $loggerTimeZone = new \DateTimeZone('UTC');
-
- $logger = new Monolog\Logger($data['channel']);
- $logger->setTimezone($loggerTimeZone);
- $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor());
- $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor());
- $logger->pushProcessor(new Monolog\Processor\UidProcessor());
- $logger->pushProcessor(new IntrospectionProcessor($data['introspection'], LogLevel::DEBUG));
-
- $stream = DI::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 {
- $loglevel = Monolog\Logger::toMonologLevel($data['loglevel']);
-
- // fallback to notice if an invalid loglevel is set
- if (!is_int($loglevel)) {
- $loglevel = LogLevel::NOTICE;
- }
-
- $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 (\Throwable $e) {
- return;
- }
- }
-
- $data['storage'] = $logger;
-}
diff --git a/monolog/src/Factory/Monolog.php b/monolog/src/Factory/Monolog.php
new file mode 100644
index 00000000..c5c69824
--- /dev/null
+++ b/monolog/src/Factory/Monolog.php
@@ -0,0 +1,54 @@
+channel);
+ $logger->setTimezone($loggerTimeZone);
+ $logger->pushProcessor(new PsrLogMessageProcessor());
+ $logger->pushProcessor(new ProcessIdProcessor());
+ $logger->pushProcessor(new UidProcessor());
+ $logger->pushProcessor(new IntrospectionProcessor($this->introspection, LogLevel::DEBUG));
+
+ $logfile = $config->get('system', 'logfile');
+
+ // just add a stream in case it's either writable or not file
+ if (is_writable($logfile)) {
+ $loglevel = $loglevel ?? static::mapLegacyConfigDebugLevel($config->get('system', 'loglevel'));
+ $loglevel = Logger::toMonologLevel($loglevel);
+
+ // fallback to notice if an invalid loglevel is set
+ if (!is_int($loglevel)) {
+ $loglevel = LogLevel::NOTICE;
+ }
+
+ $fileHandler = new StreamHandler($logfile, $loglevel);
+
+ $formatter = new LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n");
+ $fileHandler->setFormatter($formatter);
+
+ $logger->pushHandler($fileHandler);
+ }
+
+ return $logger;
+ }
+}
diff --git a/monolog/src/DevelopHandler.php b/monolog/src/Monolog/DevelopHandler.php
similarity index 98%
rename from monolog/src/DevelopHandler.php
rename to monolog/src/Monolog/DevelopHandler.php
index e3d31e64..735ebac7 100644
--- a/monolog/src/DevelopHandler.php
+++ b/monolog/src/Monolog/DevelopHandler.php
@@ -19,7 +19,7 @@
*
*/
-namespace Friendica\Addon\monolog\src;
+namespace Friendica\Addon\monolog\src\Monolog;
use Friendica\App\Request;
use Monolog\Handler;
diff --git a/monolog/src/IntrospectionProcessor.php b/monolog/src/Monolog/IntrospectionProcessor.php
similarity index 86%
rename from monolog/src/IntrospectionProcessor.php
rename to monolog/src/Monolog/IntrospectionProcessor.php
index 8ba6023e..2df0e21a 100644
--- a/monolog/src/IntrospectionProcessor.php
+++ b/monolog/src/Monolog/IntrospectionProcessor.php
@@ -19,11 +19,10 @@
*
*/
-namespace Friendica\Addon\monolog\src;
+namespace Friendica\Addon\monolog\src\Monolog;
use Friendica\Core\Logger\Util\Introspection;
use Monolog\Logger;
-use Monolog\LogRecord;
use Monolog\Processor\ProcessorInterface;
/**
@@ -42,19 +41,19 @@ class IntrospectionProcessor implements ProcessorInterface
public function __construct(Introspection $introspection, $level = Logger::DEBUG)
{
$this->level = Logger::toMonologLevel($level);
- $introspection->addClasses(['Monolog\\']);
+ $introspection->addClasses(['Monolog\\', static::class]);
$this->introspection = $introspection;
}
- public function __invoke(LogRecord $record): LogRecord
+ public function __invoke(array $record): array
{
// return if the level is not high enough
- if ($record->level < $this->level) {
+ if ($record['level'] < $this->level) {
return $record;
}
// we should have the call source now
- $record->extra = array_merge(
- $record->extra,
+ $record['extra'] = array_merge(
+ $record['extra'],
$this->introspection->getRecord()
);
diff --git a/monolog/static/dependencies.config.php b/monolog/static/dependencies.config.php
new file mode 100644
index 00000000..e3066594
--- /dev/null
+++ b/monolog/static/dependencies.config.php
@@ -0,0 +1,29 @@
+.
+ *
+ */
+
+return [
+ \Monolog\Logger::class => [
+ 'instanceOf' => \Friendica\Addon\monolog\src\Factory\Monolog::class,
+ 'call' => [
+ ['create', [], \Dice\Dice::CHAIN_CALL],
+ ],
+ ],
+];
diff --git a/monolog/static/strategies.config.php b/monolog/static/strategies.config.php
new file mode 100644
index 00000000..87153839
--- /dev/null
+++ b/monolog/static/strategies.config.php
@@ -0,0 +1,26 @@
+.
+ *
+ */
+
+return [
+ \Psr\Log\LoggerInterface::class => [
+ \Monolog\Logger::class => ['monolog'],
+ ],
+];
diff --git a/monolog/vendor/composer/autoload_classmap.php b/monolog/vendor/composer/autoload_classmap.php
index 70609203..c12d7340 100644
--- a/monolog/vendor/composer/autoload_classmap.php
+++ b/monolog/vendor/composer/autoload_classmap.php
@@ -26,7 +26,6 @@ return array(
'Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
'Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
'Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
- 'Monolog\\Formatter\\SyslogFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php',
'Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
'Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
'Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
@@ -92,6 +91,7 @@ return array(
'Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
'Monolog\\Handler\\SqsHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php',
'Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
+ 'Monolog\\Handler\\SwiftMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
'Monolog\\Handler\\SymfonyMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php',
'Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
'Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
@@ -121,12 +121,4 @@ return array(
'Monolog\\SignalHandler' => $vendorDir . '/monolog/monolog/src/Monolog/SignalHandler.php',
'Monolog\\Test\\TestCase' => $vendorDir . '/monolog/monolog/src/Monolog/Test/TestCase.php',
'Monolog\\Utils' => $vendorDir . '/monolog/monolog/src/Monolog/Utils.php',
- 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/src/AbstractLogger.php',
- 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/src/InvalidArgumentException.php',
- 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/src/LogLevel.php',
- 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/src/LoggerAwareInterface.php',
- 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/src/LoggerAwareTrait.php',
- 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/src/LoggerInterface.php',
- 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/src/LoggerTrait.php',
- 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/src/NullLogger.php',
);
diff --git a/monolog/vendor/composer/autoload_psr4.php b/monolog/vendor/composer/autoload_psr4.php
index afcfb31e..9cb5b63d 100644
--- a/monolog/vendor/composer/autoload_psr4.php
+++ b/monolog/vendor/composer/autoload_psr4.php
@@ -6,6 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
- 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
);
diff --git a/monolog/vendor/composer/autoload_static.php b/monolog/vendor/composer/autoload_static.php
index 85bd86fd..a44984ec 100644
--- a/monolog/vendor/composer/autoload_static.php
+++ b/monolog/vendor/composer/autoload_static.php
@@ -20,7 +20,7 @@ class ComposerStaticInitMonologAddon
public static $prefixDirsPsr4 = array (
'Psr\\Log\\' =>
array (
- 0 => __DIR__ . '/..' . '/psr/log/src',
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
),
'Monolog\\' =>
array (
@@ -49,7 +49,6 @@ class ComposerStaticInitMonologAddon
'Monolog\\Formatter\\MongoDBFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
'Monolog\\Formatter\\NormalizerFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
'Monolog\\Formatter\\ScalarFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
- 'Monolog\\Formatter\\SyslogFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php',
'Monolog\\Formatter\\WildfireFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
'Monolog\\Handler\\AbstractHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
'Monolog\\Handler\\AbstractProcessingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
@@ -115,6 +114,7 @@ class ComposerStaticInitMonologAddon
'Monolog\\Handler\\SocketHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
'Monolog\\Handler\\SqsHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php',
'Monolog\\Handler\\StreamHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
+ 'Monolog\\Handler\\SwiftMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
'Monolog\\Handler\\SymfonyMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php',
'Monolog\\Handler\\SyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
'Monolog\\Handler\\SyslogUdpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
@@ -144,14 +144,6 @@ class ComposerStaticInitMonologAddon
'Monolog\\SignalHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/SignalHandler.php',
'Monolog\\Test\\TestCase' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Test/TestCase.php',
'Monolog\\Utils' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Utils.php',
- 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/src/AbstractLogger.php',
- 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/src/InvalidArgumentException.php',
- 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/src/LogLevel.php',
- 'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareInterface.php',
- 'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareTrait.php',
- 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerInterface.php',
- 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerTrait.php',
- 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/src/NullLogger.php',
);
public static function getInitializer(ClassLoader $loader)
diff --git a/monolog/vendor/composer/installed.json b/monolog/vendor/composer/installed.json
index c01706ed..2b129417 100644
--- a/monolog/vendor/composer/installed.json
+++ b/monolog/vendor/composer/installed.json
@@ -1,42 +1,43 @@
[
{
"name": "monolog/monolog",
- "version": "3.2.0",
- "version_normalized": "3.2.0.0",
+ "version": "2.9.2",
+ "version_normalized": "2.9.2.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81"
+ "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/305444bc6fb6c89e490f4b34fa6e979584d7fa81",
- "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f",
+ "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "psr/log": "^2.0 || ^3.0"
+ "php": ">=7.2",
+ "psr/log": "^1.0.1 || ^2.0 || ^3.0"
},
"provide": {
- "psr/log-implementation": "3.0.0"
+ "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
},
"require-dev": {
- "aws/aws-sdk-php": "^3.0",
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
"ext-json": "*",
- "graylog2/gelf-php": "^1.4.2",
+ "graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8",
"php-amqplib/php-amqplib": "~2.4 || ^3",
- "phpstan/phpstan": "^1.4",
- "phpstan/phpstan-deprecation-rules": "^1.0",
- "phpstan/phpstan-strict-rules": "^1.1",
- "phpunit/phpunit": "^9.5.16",
- "predis/predis": "^1.1",
+ "phpspec/prophecy": "^1.15",
+ "phpstan/phpstan": "^0.12.91",
+ "phpunit/phpunit": "^8.5.14",
+ "predis/predis": "^1.1 || ^2.0",
+ "rollbar/rollbar": "^1.3 || ^2 || ^3",
"ruflin/elastica": "^7",
+ "swiftmailer/swiftmailer": "^5.3|^6.0",
"symfony/mailer": "^5.4 || ^6",
"symfony/mime": "^5.4 || ^6"
},
@@ -56,11 +57,11 @@
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
},
- "time": "2022-07-24T12:00:55+00:00",
+ "time": "2023-10-27T15:25:26+00:00",
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.x-dev"
+ "dev-main": "2.x-dev"
}
},
"installation-source": "dist",
@@ -100,33 +101,33 @@
},
{
"name": "psr/log",
- "version": "3.0.0",
- "version_normalized": "3.0.0.0",
+ "version": "1.1.4",
+ "version_normalized": "1.1.4.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
- "php": ">=8.0.0"
+ "php": ">=5.3.0"
},
- "time": "2021-07-14T16:46:02+00:00",
+ "time": "2021-05-03T11:20:27+00:00",
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.x-dev"
+ "dev-master": "1.1.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
- "Psr\\Log\\": "src"
+ "Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
diff --git a/monolog/vendor/monolog/monolog/CHANGELOG.md b/monolog/vendor/monolog/monolog/CHANGELOG.md
index fa0acea3..aca1bdd0 100644
--- a/monolog/vendor/monolog/monolog/CHANGELOG.md
+++ b/monolog/vendor/monolog/monolog/CHANGELOG.md
@@ -1,70 +1,23 @@
-### 3.2.0 (2022-07-24)
+### 2.9.2 (2023-10-27)
- * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734)
- * Marked `Logger` `@final` as it should not be extended, prefer composition or talk to us if you are missing something
- * Added RFC 5424 level (`7` to `0`) support to `Logger::log` and `Logger::addRecord` to increase interoperability (#1723)
- * Added `SyslogFormatter` to output syslog-like files which can be consumed by tools like [lnav](https://lnav.org/) (#1689)
- * Added support for `__toString` for objects which are not json serializable in `JsonFormatter` (#1733)
- * Added `GoogleCloudLoggingFormatter` (#1719)
- * Added support for Predis 2.x (#1732)
- * Added `AmqpHandler->setExtraAttributes` to allow configuring attributes when using an AMQPExchange (#1724)
- * Fixed serialization/unserialization of handlers to make sure private properties are included (#1727)
- * Fixed allowInlineLineBreaks in LineFormatter causing issues with windows paths containing `\n` or `\r` sequences (#1720)
- * Fixed max normalization depth not being taken into account when formatting exceptions with a deep chain of previous exceptions (#1726)
- * Fixed PHP 8.2 deprecation warnings (#1722)
- * Fixed rare race condition or filesystem issue where StreamHandler is unable to create the directory the log should go into yet it exists already (#1678)
+ * Fixed display_errors parsing in ErrorHandler which did not support string values (#1804)
+ * Fixed bug where the previous error handler would not be restored in some cases where StreamHandler fails (#1815)
+ * Fixed normalization error when normalizing incomplete classes (#1833)
-### 3.1.0 (2022-06-09)
+### 2.9.1 (2023-02-06)
- * Added `$datetime` parameter to `Logger::addRecord` as low level API to allow logging into the past or future (#1682)
- * Added `Logger::useLoggingLoopDetection` to allow disabling cyclic logging detection in concurrent frameworks (#1681)
- * Fixed handling of fatal errors if callPrevious is disabled in ErrorHandler (#1670)
- * Fixed interop issue by removing the need for a return type in ProcessorInterface (#1680)
- * Marked the reusable `Monolog\Test\TestCase` class as `@internal` to make sure PHPStorm does not show it above PHPUnit, you may still use it to test your own handlers/etc though (#1677)
- * Fixed RotatingFileHandler issue when the date format contained slashes (#1671)
+ * Fixed Logger not being serializable anymore (#1792)
-### 3.0.0 (2022-05-10)
+### 2.9.0 (2023-02-05)
-Changes from RC1
-
-- The `Monolog\LevelName` enum does not exist anymore, use `Monolog\Level->getName()` instead.
-
-### 3.0.0-RC1 (2022-05-08)
-
-This is mostly a cleanup release offering stronger type guarantees for integrators with the
-array->object/enum changes, but there is no big new feature for end users.
-
-See [UPGRADE notes](UPGRADE.md#300) for details on all breaking changes especially if you are extending/implementing Monolog classes/interfaces.
-
-Noteworthy BC Breaks:
-
-- The minimum supported PHP version is now `8.1.0`.
-- Log records have been converted from an array to a [`Monolog\LogRecord` object](src/Monolog/LogRecord.php)
- with public (and mostly readonly) properties. e.g. instead of doing
- `$record['context']` use `$record->context`.
- In formatters or handlers if you rather need an array to work with you can use `$record->toArray()`
- to get back a Monolog 1/2 style record array. This will contain the enum values instead of enum cases
- in the `level` and `level_name` keys to be more backwards compatible and use simpler data types.
-- `FormatterInterface`, `HandlerInterface`, `ProcessorInterface`, etc. changed to contain `LogRecord $record`
- instead of `array $record` parameter types. If you want to support multiple Monolog versions this should
- be possible by type-hinting nothing, or `array|LogRecord` if you support PHP 8.0+. You can then code
- against the $record using Monolog 2 style as LogRecord implements ArrayAccess for BC.
- The interfaces do not require a `LogRecord` return type even where it would be applicable, but if you only
- support Monolog 3 in integration code I would recommend you use `LogRecord` return types wherever fitting
- to ensure forward compatibility as it may be added in Monolog 4.
-- Log levels are now enums [`Monolog\Level`](src/Monolog/Level.php) and [`Monolog\LevelName`](src/Monolog/LevelName.php)
-- Removed deprecated SwiftMailerHandler, migrate to SymfonyMailerHandler instead.
-- `ResettableInterface::reset()` now requires a void return type.
-- All properties have had types added, which may require you to do so as well if you extended
- a Monolog class and declared the same property.
-
-New deprecations:
-
-- `Logger::DEBUG`, `Logger::ERROR`, etc. are now deprecated in favor of the `Monolog\Level` enum.
- e.g. instead of `Logger::WARNING` use `Level::Warning` if you need to pass the enum case
- to Monolog or one of its handlers, or `Level::Warning->value` if you need the integer
- value equal to what `Logger::WARNING` was giving you.
-- `Logger::getLevelName()` is now deprecated.
+ * Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748)
+ * Added support for enum context values in PsrLogMessageProcessor (#1773)
+ * Added graylog2/gelf-php 2.x support (#1747)
+ * Improved `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739)
+ * Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791)
+ * Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758)
+ * Fixed infinite loop detection within Fibers (#1753)
+ * Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781)
### 2.8.0 (2022-07-24)
diff --git a/monolog/vendor/monolog/monolog/README.md b/monolog/vendor/monolog/monolog/README.md
index 87c7f664..bfcae0c0 100644
--- a/monolog/vendor/monolog/monolog/README.md
+++ b/monolog/vendor/monolog/monolog/README.md
@@ -3,8 +3,6 @@
[](https://packagist.org/packages/monolog/monolog)
[](https://packagist.org/packages/monolog/monolog)
-> ⚠ This is the **documentation for Monolog 3.x**, if you are using older releases
-> see the documentation for [Monolog 2.x](https://github.com/Seldaek/monolog/blob/2.x/README.md) or [Monolog 1.x](https://github.com/Seldaek/monolog/blob/1.x/README.md) ⚠
Monolog sends your logs to files, sockets, inboxes, databases and various
web services. See the complete list of handlers below. Special handlers
@@ -30,13 +28,12 @@ $ composer require monolog/monolog
```php
pushHandler(new StreamHandler('path/to/your.log', Level::Warning));
+$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
// add records to the log
$log->warning('Foo');
@@ -53,7 +50,7 @@ $log->error('Bar');
## Support Monolog Financially
-Get supported Monolog and help fund the project with the [Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-monolog-monolog?utm_source=packagist-monolog-monolog&utm_medium=referral&utm_campaign=enterprise) or via [GitHub sponsorship](https://github.com/sponsors/Seldaek).
+Get supported Monolog and help fund the project with the [Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-monolog-monolog?utm_source=packagist-monolog-monolog&utm_medium=referral&utm_campaign=enterprise) or via [GitHub sponsorship](https://github.com/sponsors/Seldaek).
Tidelift delivers commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
@@ -67,13 +64,11 @@ can also add your own there if you publish one.
### Requirements
-- Monolog `^3.0` works with PHP 8.1 or above.
-- Monolog `^2.5` works with PHP 7.2 or above.
-- Monolog `^1.25` works with PHP 5.3 up to 8.1, but is not very maintained anymore and will not receive PHP support fixes anymore.
+- Monolog `^2.0` works with PHP 7.2 or above, use Monolog `^1.25` for PHP 5.3+ support.
### Support
-Monolog 1.x support is somewhat limited at this point and only important fixes will be done. You should migrate to Monolog 2 or 3 where possible to benefit from all the latest features and fixes.
+Monolog 1.x support is somewhat limited at this point and only important fixes will be done. You should migrate to Monolog 2 where possible to benefit from all the latest features and fixes.
### Submitting bugs and feature requests
diff --git a/monolog/vendor/monolog/monolog/UPGRADE.md b/monolog/vendor/monolog/monolog/UPGRADE.md
new file mode 100644
index 00000000..84e15e6b
--- /dev/null
+++ b/monolog/vendor/monolog/monolog/UPGRADE.md
@@ -0,0 +1,72 @@
+### 2.0.0
+
+- `Monolog\Logger::API` can be used to distinguish between a Monolog `1` and `2`
+ install of Monolog when writing integration code.
+
+- Removed non-PSR-3 methods to add records, all the `add*` (e.g. `addWarning`)
+ methods as well as `emerg`, `crit`, `err` and `warn`.
+
+- DateTime are now formatted with a timezone and microseconds (unless disabled).
+ Various formatters and log output might be affected, which may mess with log parsing
+ in some cases.
+
+- The `datetime` in every record array is now a DateTimeImmutable, not that you
+ should have been modifying these anyway.
+
+- The timezone is now set per Logger instance and not statically, either
+ via ->setTimezone or passed in the constructor. Calls to Logger::setTimezone
+ should be converted.
+
+- `HandlerInterface` has been split off and two new interfaces now exist for
+ more granular controls: `ProcessableHandlerInterface` and
+ `FormattableHandlerInterface`. Handlers not extending `AbstractHandler`
+ should make sure to implement the relevant interfaces.
+
+- `HandlerInterface` now requires the `close` method to be implemented. This
+ only impacts you if you implement the interface yourself, but you can extend
+ the new `Monolog\Handler\Handler` base class too.
+
+- There is no more default handler configured on empty Logger instances, if
+ you were relying on that you will not get any output anymore, make sure to
+ configure the handler you need.
+
+#### LogglyFormatter
+
+- The records' `datetime` is not sent anymore. Only `timestamp` is sent to Loggly.
+
+#### AmqpHandler
+
+- Log levels are not shortened to 4 characters anymore. e.g. a warning record
+ will be sent using the `warning.channel` routing key instead of `warn.channel`
+ as in 1.x.
+- The exchange name does not default to 'log' anymore, and it is completely ignored
+ now for the AMQP extension users. Only PHPAmqpLib uses it if provided.
+
+#### RotatingFileHandler
+
+- The file name format must now contain `{date}` and the date format must be set
+ to one of the predefined FILE_PER_* constants to avoid issues with file rotation.
+ See `setFilenameFormat`.
+
+#### LogstashFormatter
+
+- Removed Logstash V0 support
+- Context/extra prefix has been removed in favor of letting users configure the exact key being sent
+- Context/extra data are now sent as an object instead of single keys
+
+#### HipChatHandler
+
+- Removed deprecated HipChat handler, migrate to Slack and use SlackWebhookHandler or SlackHandler instead
+
+#### SlackbotHandler
+
+- Removed deprecated SlackbotHandler handler, use SlackWebhookHandler or SlackHandler instead
+
+#### RavenHandler
+
+- Removed deprecated RavenHandler handler, use sentry/sentry 2.x and their Sentry\Monolog\Handler instead
+
+#### ElasticSearchHandler
+
+- As support for the official Elasticsearch library was added, the former ElasticSearchHandler has been
+ renamed to ElasticaHandler and the new one added as ElasticsearchHandler.
diff --git a/monolog/vendor/monolog/monolog/composer.json b/monolog/vendor/monolog/monolog/composer.json
index 3a48e6db..b9437d6d 100644
--- a/monolog/vendor/monolog/monolog/composer.json
+++ b/monolog/vendor/monolog/monolog/composer.json
@@ -13,25 +13,26 @@
}
],
"require": {
- "php": ">=8.1",
- "psr/log": "^2.0 || ^3.0"
+ "php": ">=7.2",
+ "psr/log": "^1.0.1 || ^2.0 || ^3.0"
},
"require-dev": {
"ext-json": "*",
- "aws/aws-sdk-php": "^3.0",
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7 || ^8",
- "graylog2/gelf-php": "^1.4.2",
+ "graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8",
"php-amqplib/php-amqplib": "~2.4 || ^3",
- "phpstan/phpstan": "^1.4",
- "phpstan/phpstan-deprecation-rules": "^1.0",
- "phpstan/phpstan-strict-rules": "^1.1",
- "phpunit/phpunit": "^9.5.16",
- "predis/predis": "^1.1",
+ "phpspec/prophecy": "^1.15",
+ "phpstan/phpstan": "^0.12.91",
+ "phpunit/phpunit": "^8.5.14",
+ "predis/predis": "^1.1 || ^2.0",
+ "rollbar/rollbar": "^1.3 || ^2 || ^3",
"ruflin/elastica": "^7",
+ "swiftmailer/swiftmailer": "^5.3|^6.0",
"symfony/mailer": "^5.4 || ^6",
"symfony/mime": "^5.4 || ^6"
},
@@ -58,11 +59,11 @@
"psr-4": {"Monolog\\": "tests/Monolog"}
},
"provide": {
- "psr/log-implementation": "3.0.0"
+ "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
},
"extra": {
"branch-alias": {
- "dev-main": "3.x-dev"
+ "dev-main": "2.x-dev"
}
},
"scripts": {
@@ -72,6 +73,9 @@
"config": {
"lock": false,
"sort-packages": true,
- "platform-check": false
+ "platform-check": false,
+ "allow-plugins": {
+ "composer/package-versions-deprecated": true
+ }
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php
index f8b25021..188bbb0d 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php
@@ -13,24 +13,34 @@ namespace Monolog\Attribute;
/**
* A reusable attribute to help configure a class or a method as a processor.
- *
+ *
* Using it offers no guarantee: it needs to be leveraged by a Monolog third-party consumer.
- *
+ *
* Using it with the Monolog library only has no effect at all: processors should still be turned into a callable if
* needed and manually pushed to the loggers and to the processable handlers.
*/
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class AsMonologProcessor
{
+ /** @var string|null */
+ public $channel = null;
+ /** @var string|null */
+ public $handler = null;
+ /** @var string|null */
+ public $method = null;
+
/**
- * @param string|null $channel The logging channel the processor should be pushed to.
- * @param string|null $handler The handler the processor should be pushed to.
- * @param string|null $method The method that processes the records (if the attribute is used at the class level).
+ * @param string|null $channel The logging channel the processor should be pushed to.
+ * @param string|null $handler The handler the processor should be pushed to.
+ * @param string|null $method The method that processes the records (if the attribute is used at the class level).
*/
public function __construct(
- public readonly ?string $channel = null,
- public readonly ?string $handler = null,
- public readonly ?string $method = null
+ ?string $channel = null,
+ ?string $handler = null,
+ ?string $method = null
) {
+ $this->channel = $channel;
+ $this->handler = $handler;
+ $this->method = $method;
}
-}
+}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php b/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php
index 274b73ea..6a1ba9b2 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php
@@ -21,7 +21,10 @@ use DateTimeZone;
*/
class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
{
- private bool $useMicroseconds;
+ /**
+ * @var bool
+ */
+ private $useMicroseconds;
public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null)
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php
index 2ed46035..1406d34e 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php
@@ -11,7 +11,6 @@
namespace Monolog;
-use Closure;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
@@ -26,33 +25,35 @@ use Psr\Log\LogLevel;
*/
class ErrorHandler
{
- private Closure|null $previousExceptionHandler = null;
+ /** @var LoggerInterface */
+ private $logger;
+ /** @var ?callable */
+ private $previousExceptionHandler = null;
/** @var array an array of class name to LogLevel::* constant mapping */
- private array $uncaughtExceptionLevelMap = [];
-
- /** @var Closure|true|null */
- private Closure|bool|null $previousErrorHandler = null;
+ private $uncaughtExceptionLevelMap = [];
+ /** @var callable|true|null */
+ private $previousErrorHandler = null;
/** @var array an array of E_* constant to LogLevel::* constant mapping */
- private array $errorLevelMap = [];
-
- private bool $handleOnlyReportedErrors = true;
-
- private bool $hasFatalErrorHandler = false;
-
- private string $fatalLevel = LogLevel::ALERT;
-
- private string|null $reservedMemory = null;
+ private $errorLevelMap = [];
+ /** @var bool */
+ private $handleOnlyReportedErrors = true;
+ /** @var bool */
+ private $hasFatalErrorHandler = false;
+ /** @var LogLevel::* */
+ private $fatalLevel = LogLevel::ALERT;
+ /** @var ?string */
+ private $reservedMemory = null;
/** @var ?array{type: int, message: string, file: string, line: int, trace: mixed} */
- private array|null $lastFatalData = null;
+ private $lastFatalData = null;
+ /** @var int[] */
+ private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
- private const FATAL_ERRORS = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
-
- public function __construct(
- private LoggerInterface $logger
- ) {
+ public function __construct(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
}
/**
@@ -60,6 +61,7 @@ class ErrorHandler
*
* By default it will handle errors, exceptions and fatal errors
*
+ * @param LoggerInterface $logger
* @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
* @param array|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
* @param LogLevel::*|null|false $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling
@@ -97,8 +99,8 @@ class ErrorHandler
$this->uncaughtExceptionLevelMap[$class] = $level;
}
}
- if ($callPrevious && null !== $prev) {
- $this->previousExceptionHandler = $prev(...);
+ if ($callPrevious && $prev) {
+ $this->previousExceptionHandler = $prev;
}
return $this;
@@ -110,10 +112,10 @@ class ErrorHandler
*/
public function registerErrorHandler(array $levelMap = [], bool $callPrevious = true, int $errorTypes = -1, bool $handleOnlyReportedErrors = true): self
{
- $prev = set_error_handler($this->handleError(...), $errorTypes);
+ $prev = set_error_handler([$this, 'handleError'], $errorTypes);
$this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
if ($callPrevious) {
- $this->previousErrorHandler = $prev !== null ? $prev(...) : true;
+ $this->previousErrorHandler = $prev ?: true;
} else {
$this->previousErrorHandler = null;
}
@@ -129,7 +131,7 @@ class ErrorHandler
*/
public function registerFatalHandler($level = null, int $reservedMemorySize = 20): self
{
- register_shutdown_function($this->handleFatalError(...));
+ register_shutdown_function([$this, 'handleFatalError']);
$this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
$this->fatalLevel = null === $level ? LogLevel::ALERT : $level;
@@ -173,7 +175,10 @@ class ErrorHandler
];
}
- private function handleException(\Throwable $e): never
+ /**
+ * @phpstan-return never
+ */
+ private function handleException(\Throwable $e): void
{
$level = LogLevel::ERROR;
foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) {
@@ -189,25 +194,30 @@ class ErrorHandler
['exception' => $e]
);
- if (null !== $this->previousExceptionHandler) {
+ if ($this->previousExceptionHandler) {
($this->previousExceptionHandler)($e);
}
- if (!headers_sent() && !(bool) ini_get('display_errors')) {
+ if (!headers_sent() && in_array(strtolower((string) ini_get('display_errors')), ['0', '', 'false', 'off', 'none', 'no'], true)) {
http_response_code(500);
}
exit(255);
}
- private function handleError(int $code, string $message, string $file = '', int $line = 0): bool
+ /**
+ * @private
+ *
+ * @param mixed[] $context
+ */
+ public function handleError(int $code, string $message, string $file = '', int $line = 0, ?array $context = []): bool
{
- if ($this->handleOnlyReportedErrors && 0 === (error_reporting() & $code)) {
+ if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) {
return false;
}
// fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
- if (!$this->hasFatalErrorHandler || !in_array($code, self::FATAL_ERRORS, true)) {
+ if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
$level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL;
$this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
} else {
@@ -218,9 +228,8 @@ class ErrorHandler
if ($this->previousErrorHandler === true) {
return false;
- }
- if ($this->previousErrorHandler instanceof Closure) {
- return (bool) ($this->previousErrorHandler)($code, $message, $file, $line);
+ } elseif ($this->previousErrorHandler) {
+ return (bool) ($this->previousErrorHandler)($code, $message, $file, $line, $context);
}
return true;
@@ -238,7 +247,8 @@ class ErrorHandler
} else {
$lastError = error_get_last();
}
- if (is_array($lastError) && in_array($lastError['type'], self::FATAL_ERRORS, true)) {
+
+ if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) {
$trace = $lastError['trace'] ?? null;
$this->logger->log(
$this->fatalLevel,
@@ -254,25 +264,44 @@ class ErrorHandler
}
}
- private static function codeToString(int $code): string
+ /**
+ * @param int $code
+ */
+ private static function codeToString($code): string
{
- return match ($code) {
- E_ERROR => 'E_ERROR',
- E_WARNING => 'E_WARNING',
- E_PARSE => 'E_PARSE',
- E_NOTICE => 'E_NOTICE',
- E_CORE_ERROR => 'E_CORE_ERROR',
- E_CORE_WARNING => 'E_CORE_WARNING',
- E_COMPILE_ERROR => 'E_COMPILE_ERROR',
- E_COMPILE_WARNING => 'E_COMPILE_WARNING',
- E_USER_ERROR => 'E_USER_ERROR',
- E_USER_WARNING => 'E_USER_WARNING',
- E_USER_NOTICE => 'E_USER_NOTICE',
- E_STRICT => 'E_STRICT',
- E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
- E_DEPRECATED => 'E_DEPRECATED',
- E_USER_DEPRECATED => 'E_USER_DEPRECATED',
- default => 'Unknown PHP error',
- };
+ switch ($code) {
+ case E_ERROR:
+ return 'E_ERROR';
+ case E_WARNING:
+ return 'E_WARNING';
+ case E_PARSE:
+ return 'E_PARSE';
+ case E_NOTICE:
+ return 'E_NOTICE';
+ case E_CORE_ERROR:
+ return 'E_CORE_ERROR';
+ case E_CORE_WARNING:
+ return 'E_CORE_WARNING';
+ case E_COMPILE_ERROR:
+ return 'E_COMPILE_ERROR';
+ case E_COMPILE_WARNING:
+ return 'E_COMPILE_WARNING';
+ case E_USER_ERROR:
+ return 'E_USER_ERROR';
+ case E_USER_WARNING:
+ return 'E_USER_WARNING';
+ case E_USER_NOTICE:
+ return 'E_USER_NOTICE';
+ case E_STRICT:
+ return 'E_STRICT';
+ case E_RECOVERABLE_ERROR:
+ return 'E_RECOVERABLE_ERROR';
+ case E_DEPRECATED:
+ return 'E_DEPRECATED';
+ case E_USER_DEPRECATED:
+ return 'E_USER_DEPRECATED';
+ }
+
+ return 'Unknown PHP error';
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php
index 3f1d4582..aa1884b9 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php
@@ -11,8 +11,7 @@
namespace Monolog\Formatter;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* Formats a log message according to the ChromePHP array format
@@ -24,55 +23,52 @@ class ChromePHPFormatter implements FormatterInterface
/**
* Translates Monolog log levels to Wildfire levels.
*
- * @return 'log'|'info'|'warn'|'error'
+ * @var array
*/
- private function toWildfireLevel(Level $level): string
- {
- return match ($level) {
- Level::Debug => 'log',
- Level::Info => 'info',
- Level::Notice => 'info',
- Level::Warning => 'warn',
- Level::Error => 'error',
- Level::Critical => 'error',
- Level::Alert => 'error',
- Level::Emergency => 'error',
- };
- }
+ private $logLevels = [
+ Logger::DEBUG => 'log',
+ Logger::INFO => 'info',
+ Logger::NOTICE => 'info',
+ Logger::WARNING => 'warn',
+ Logger::ERROR => 'error',
+ Logger::CRITICAL => 'error',
+ Logger::ALERT => 'error',
+ Logger::EMERGENCY => 'error',
+ ];
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function format(LogRecord $record)
+ public function format(array $record)
{
// Retrieve the line and file if set and remove them from the formatted extra
$backtrace = 'unknown';
- if (isset($record->extra['file'], $record->extra['line'])) {
- $backtrace = $record->extra['file'].' : '.$record->extra['line'];
- unset($record->extra['file'], $record->extra['line']);
+ if (isset($record['extra']['file'], $record['extra']['line'])) {
+ $backtrace = $record['extra']['file'].' : '.$record['extra']['line'];
+ unset($record['extra']['file'], $record['extra']['line']);
}
- $message = ['message' => $record->message];
- if (\count($record->context) > 0) {
- $message['context'] = $record->context;
+ $message = ['message' => $record['message']];
+ if ($record['context']) {
+ $message['context'] = $record['context'];
}
- if (\count($record->extra) > 0) {
- $message['extra'] = $record->extra;
+ if ($record['extra']) {
+ $message['extra'] = $record['extra'];
}
if (count($message) === 1) {
$message = reset($message);
}
return [
- $record->channel,
+ $record['channel'],
$message,
$backtrace,
- $this->toWildfireLevel($record->level),
+ $this->logLevels[$record['level']],
];
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function formatBatch(array $records)
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php
index 160510ad..6c8a9ab5 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php
@@ -12,24 +12,25 @@
namespace Monolog\Formatter;
use Elastica\Document;
-use Monolog\LogRecord;
/**
* Format a log message into an Elastica Document
*
* @author Jelle Vink
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class ElasticaFormatter extends NormalizerFormatter
{
/**
* @var string Elastic search index name
*/
- protected string $index;
+ protected $index;
/**
- * @var string|null Elastic search document type
+ * @var ?string Elastic search document type
*/
- protected string|null $type;
+ protected $type;
/**
* @param string $index Elastic Search index name
@@ -45,9 +46,9 @@ class ElasticaFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function format(LogRecord $record)
+ public function format(array $record)
{
$record = parent::format($record);
@@ -71,13 +72,14 @@ class ElasticaFormatter extends NormalizerFormatter
/**
* Convert a log message into an Elastica Document
*
- * @param mixed[] $record
+ * @phpstan-param Record $record
*/
protected function getDocument(array $record): Document
{
$document = new Document();
$document->setData($record);
if (method_exists($document, 'setType')) {
+ /** @phpstan-ignore-next-line */
$document->setType($this->type);
}
$document->setIndex($this->index);
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php
index 6c3eb9b2..b792b819 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php
@@ -12,7 +12,6 @@
namespace Monolog\Formatter;
use DateTimeInterface;
-use Monolog\LogRecord;
/**
* Format a log message into an Elasticsearch record
@@ -24,12 +23,12 @@ class ElasticsearchFormatter extends NormalizerFormatter
/**
* @var string Elasticsearch index name
*/
- protected string $index;
+ protected $index;
/**
* @var string Elasticsearch record type
*/
- protected string $type;
+ protected $type;
/**
* @param string $index Elasticsearch index name
@@ -45,9 +44,9 @@ class ElasticsearchFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function format(LogRecord $record)
+ public function format(array $record)
{
$record = parent::format($record);
@@ -56,6 +55,8 @@ class ElasticsearchFormatter extends NormalizerFormatter
/**
* Getter index
+ *
+ * @return string
*/
public function getIndex(): string
{
@@ -64,6 +65,8 @@ class ElasticsearchFormatter extends NormalizerFormatter
/**
* Getter type
+ *
+ * @return string
*/
public function getType(): string
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php
index b8f7be52..867ae586 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php
@@ -11,18 +11,23 @@
namespace Monolog\Formatter;
-use Monolog\LogRecord;
-
/**
* formats the record to be used in the FlowdockHandler
*
* @author Dominik Liebler
+ * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
*/
class FlowdockFormatter implements FormatterInterface
{
- private string $source;
+ /**
+ * @var string
+ */
+ private $source;
- private string $sourceEmail;
+ /**
+ * @var string
+ */
+ private $sourceEmail;
public function __construct(string $source, string $sourceEmail)
{
@@ -31,41 +36,43 @@ class FlowdockFormatter implements FormatterInterface
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*
* @return mixed[]
*/
- public function format(LogRecord $record): array
+ public function format(array $record): array
{
$tags = [
'#logs',
- '#' . $record->level->toPsrLogLevel(),
- '#' . $record->channel,
+ '#' . strtolower($record['level_name']),
+ '#' . $record['channel'],
];
- foreach ($record->extra as $value) {
+ foreach ($record['extra'] as $value) {
$tags[] = '#' . $value;
}
$subject = sprintf(
'in %s: %s - %s',
$this->source,
- $record->level->getName(),
- $this->getShortMessage($record->message)
+ $record['level_name'],
+ $this->getShortMessage($record['message'])
);
- return [
+ $record['flowdock'] = [
'source' => $this->source,
'from_address' => $this->sourceEmail,
'subject' => $subject,
- 'content' => $record->message,
+ 'content' => $record['message'],
'tags' => $tags,
'project' => $this->source,
];
+
+ return $record;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*
* @return mixed[][]
*/
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php
index 9bd2c160..29b14d30 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php
@@ -12,7 +12,6 @@
namespace Monolog\Formatter;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* Class FluentdFormatter
@@ -40,7 +39,7 @@ class FluentdFormatter implements FormatterInterface
/**
* @var bool $levelTag should message level be a part of the fluentd tag
*/
- protected bool $levelTag = false;
+ protected $levelTag = false;
public function __construct(bool $levelTag = false)
{
@@ -56,25 +55,25 @@ class FluentdFormatter implements FormatterInterface
return $this->levelTag;
}
- public function format(LogRecord $record): string
+ public function format(array $record): string
{
- $tag = $record->channel;
+ $tag = $record['channel'];
if ($this->levelTag) {
- $tag .= '.' . $record->level->toPsrLogLevel();
+ $tag .= '.' . strtolower($record['level_name']);
}
$message = [
- 'message' => $record->message,
- 'context' => $record->context,
- 'extra' => $record->extra,
+ 'message' => $record['message'],
+ 'context' => $record['context'],
+ 'extra' => $record['extra'],
];
if (!$this->levelTag) {
- $message['level'] = $record->level->value;
- $message['level_name'] = $record->level->getName();
+ $message['level'] = $record['level'];
+ $message['level_name'] = $record['level_name'];
}
- return Utils::jsonEncode([$tag, $record->datetime->getTimestamp(), $message]);
+ return Utils::jsonEncode([$tag, $record['datetime']->getTimestamp(), $message]);
}
public function formatBatch(array $records): string
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php
index 3413a4b0..19617ec5 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php
@@ -11,28 +11,32 @@
namespace Monolog\Formatter;
-use Monolog\LogRecord;
-
/**
* Interface for formatters
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
interface FormatterInterface
{
/**
* Formats a log record.
*
- * @param LogRecord $record A record to format
- * @return mixed The formatted record
+ * @param array $record A record to format
+ * @return mixed The formatted record
+ *
+ * @phpstan-param Record $record
*/
- public function format(LogRecord $record);
+ public function format(array $record);
/**
* Formats a set of log records.
*
- * @param array $records A set of records to format
- * @return mixed The formatted set of records
+ * @param array $records A set of records to format
+ * @return mixed The formatted set of records
+ *
+ * @phpstan-param Record[] $records
*/
public function formatBatch(array $records);
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php
index 33116a26..3b3e1e7f 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php
@@ -11,16 +11,17 @@
namespace Monolog\Formatter;
-use Monolog\Level;
+use Monolog\Logger;
use Gelf\Message;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* Serializes a log message to GELF
* @see http://docs.graylog.org/en/latest/pages/gelf.html
*
* @author Matt Lehner
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
*/
class GelfMessageFormatter extends NormalizerFormatter
{
@@ -29,39 +30,45 @@ class GelfMessageFormatter extends NormalizerFormatter
/**
* @var string the name of the system for the Gelf log message
*/
- protected string $systemName;
+ protected $systemName;
/**
* @var string a prefix for 'extra' fields from the Monolog record (optional)
*/
- protected string $extraPrefix;
+ protected $extraPrefix;
/**
* @var string a prefix for 'context' fields from the Monolog record (optional)
*/
- protected string $contextPrefix;
+ protected $contextPrefix;
/**
* @var int max length per field
*/
- protected int $maxLength;
+ protected $maxLength;
+
+ /**
+ * @var int
+ */
+ private $gelfVersion = 2;
/**
* Translates Monolog log levels to Graylog2 log priorities.
+ *
+ * @var array
+ *
+ * @phpstan-var array
*/
- private function getGraylog2Priority(Level $level): int
- {
- return match ($level) {
- Level::Debug => 7,
- Level::Info => 6,
- Level::Notice => 5,
- Level::Warning => 4,
- Level::Error => 3,
- Level::Critical => 2,
- Level::Alert => 1,
- Level::Emergency => 0,
- };
- }
+ private $logLevels = [
+ Logger::DEBUG => 7,
+ Logger::INFO => 6,
+ Logger::NOTICE => 5,
+ Logger::WARNING => 4,
+ Logger::ERROR => 3,
+ Logger::CRITICAL => 2,
+ Logger::ALERT => 1,
+ Logger::EMERGENCY => 0,
+ ];
public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null)
{
@@ -71,52 +78,64 @@ class GelfMessageFormatter extends NormalizerFormatter
parent::__construct('U.u');
- $this->systemName = (null === $systemName || $systemName === '') ? (string) gethostname() : $systemName;
+ $this->systemName = (is_null($systemName) || $systemName === '') ? (string) gethostname() : $systemName;
- $this->extraPrefix = null === $extraPrefix ? '' : $extraPrefix;
+ $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix;
$this->contextPrefix = $contextPrefix;
- $this->maxLength = null === $maxLength ? self::DEFAULT_MAX_LENGTH : $maxLength;
+ $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength;
+
+ if (method_exists(Message::class, 'setFacility')) {
+ $this->gelfVersion = 1;
+ }
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function format(LogRecord $record): Message
+ public function format(array $record): Message
{
$context = $extra = [];
- if (isset($record->context)) {
+ if (isset($record['context'])) {
/** @var mixed[] $context */
- $context = parent::normalize($record->context);
+ $context = parent::normalize($record['context']);
}
- if (isset($record->extra)) {
+ if (isset($record['extra'])) {
/** @var mixed[] $extra */
- $extra = parent::normalize($record->extra);
+ $extra = parent::normalize($record['extra']);
+ }
+
+ if (!isset($record['datetime'], $record['message'], $record['level'])) {
+ throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given');
}
$message = new Message();
$message
- ->setTimestamp($record->datetime)
- ->setShortMessage($record->message)
+ ->setTimestamp($record['datetime'])
+ ->setShortMessage((string) $record['message'])
->setHost($this->systemName)
- ->setLevel($this->getGraylog2Priority($record->level));
+ ->setLevel($this->logLevels[$record['level']]);
// message length + system name length + 200 for padding / metadata
- $len = 200 + strlen($record->message) + strlen($this->systemName);
+ $len = 200 + strlen((string) $record['message']) + strlen($this->systemName);
if ($len > $this->maxLength) {
- $message->setShortMessage(Utils::substr($record->message, 0, $this->maxLength));
+ $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength));
}
- if (isset($record->channel)) {
- $message->setAdditional('facility', $record->channel);
- }
- if (isset($extra['line'])) {
- $message->setAdditional('line', $extra['line']);
- unset($extra['line']);
- }
- if (isset($extra['file'])) {
- $message->setAdditional('file', $extra['file']);
- unset($extra['file']);
+ if ($this->gelfVersion === 1) {
+ if (isset($record['channel'])) {
+ $message->setFacility($record['channel']);
+ }
+ if (isset($extra['line'])) {
+ $message->setLine($extra['line']);
+ unset($extra['line']);
+ }
+ if (isset($extra['file'])) {
+ $message->setFile($extra['file']);
+ unset($extra['file']);
+ }
+ } else {
+ $message->setAdditional('facility', $record['channel']);
}
foreach ($extra as $key => $val) {
@@ -141,10 +160,13 @@ class GelfMessageFormatter extends NormalizerFormatter
$message->setAdditional($this->contextPrefix . $key, $val);
}
- if (!$message->hasAdditional('file') && isset($context['exception']['file'])) {
- if (1 === preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
- $message->setAdditional('file', $matches[1]);
- $message->setAdditional('line', $matches[2]);
+ if ($this->gelfVersion === 1) {
+ /** @phpstan-ignore-next-line */
+ if (null === $message->getFile() && isset($context['exception']['file'])) {
+ if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
+ $message->setFile($matches[1]);
+ $message->setLine($matches[2]);
+ }
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php
index d37d1e0c..ca52ebf4 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php
@@ -17,23 +17,24 @@ use Monolog\LogRecord;
/**
* Encodes message information into JSON in a format compatible with Cloud logging.
*
+ * @see https://cloud.google.com/logging/docs/structured-logging
* @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
*
* @author Luís Cobucci
*/
final class GoogleCloudLoggingFormatter extends JsonFormatter
{
- protected function normalizeRecord(LogRecord $record): array
+ /** {@inheritdoc} **/
+ public function format(array $record): string
{
- $normalized = parent::normalizeRecord($record);
-
// Re-key level for GCP logging
- $normalized['severity'] = $normalized['level_name'];
- $normalized['timestamp'] = $record->datetime->format(DateTimeInterface::RFC3339_EXTENDED);
+ $record['severity'] = $record['level_name'];
+ $record['time'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED);
// Remove keys that are not used by GCP
- unset($normalized['level'], $normalized['level_name'], $normalized['datetime']);
+ unset($record['level'], $record['level_name'], $record['datetime']);
- return $normalized;
+ return parent::format($record);
}
}
+
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php
index bf1c61da..10a4311c 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php
@@ -11,9 +11,8 @@
namespace Monolog\Formatter;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* Formats incoming records into an HTML table
@@ -26,20 +25,19 @@ class HtmlFormatter extends NormalizerFormatter
{
/**
* Translates Monolog log levels to html color priorities.
+ *
+ * @var array
*/
- protected function getLevelColor(Level $level): string
- {
- return match ($level) {
- Level::Debug => '#CCCCCC',
- Level::Info => '#28A745',
- Level::Notice => '#17A2B8',
- Level::Warning => '#FFC107',
- Level::Error => '#FD7E14',
- Level::Critical => '#DC3545',
- Level::Alert => '#821722',
- Level::Emergency => '#000000',
- };
- }
+ protected $logLevels = [
+ Logger::DEBUG => '#CCCCCC',
+ Logger::INFO => '#28A745',
+ Logger::NOTICE => '#17A2B8',
+ Logger::WARNING => '#FFC107',
+ Logger::ERROR => '#FD7E14',
+ Logger::CRITICAL => '#DC3545',
+ Logger::ALERT => '#821722',
+ Logger::EMERGENCY => '#000000',
+ ];
/**
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
@@ -69,13 +67,15 @@ class HtmlFormatter extends NormalizerFormatter
/**
* Create a HTML h1 tag
*
- * @param string $title Text to be in the h1
+ * @param string $title Text to be in the h1
+ * @param int $level Error level
+ * @return string
*/
- protected function addTitle(string $title, Level $level): string
+ protected function addTitle(string $title, int $level): string
{
$title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8');
- return ''.$title.' ';
+ return ''.$title.' ';
}
/**
@@ -83,25 +83,25 @@ class HtmlFormatter extends NormalizerFormatter
*
* @return string The formatted record
*/
- public function format(LogRecord $record): string
+ public function format(array $record): string
{
- $output = $this->addTitle($record->level->getName(), $record->level);
+ $output = $this->addTitle($record['level_name'], $record['level']);
$output .= '';
- $output .= $this->addRow('Message', $record->message);
- $output .= $this->addRow('Time', $this->formatDate($record->datetime));
- $output .= $this->addRow('Channel', $record->channel);
- if (\count($record->context) > 0) {
+ $output .= $this->addRow('Message', (string) $record['message']);
+ $output .= $this->addRow('Time', $this->formatDate($record['datetime']));
+ $output .= $this->addRow('Channel', $record['channel']);
+ if ($record['context']) {
$embeddedTable = '';
- foreach ($record->context as $key => $value) {
+ foreach ($record['context'] as $key => $value) {
$embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
}
$embeddedTable .= '
';
$output .= $this->addRow('Context', $embeddedTable, false);
}
- if (\count($record->extra) > 0) {
+ if ($record['extra']) {
$embeddedTable = '';
- foreach ($record->extra as $key => $value) {
+ foreach ($record['extra'] as $key => $value) {
$embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
}
$embeddedTable .= '
';
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
index b2fc5bcb..b737d82e 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
@@ -11,9 +11,7 @@
namespace Monolog\Formatter;
-use Stringable;
use Throwable;
-use Monolog\LogRecord;
/**
* Encodes whatever record data is passed to it as json
@@ -21,6 +19,8 @@ use Monolog\LogRecord;
* This can be useful to log to databases or remote APIs
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class JsonFormatter extends NormalizerFormatter
{
@@ -28,13 +28,13 @@ class JsonFormatter extends NormalizerFormatter
public const BATCH_MODE_NEWLINES = 2;
/** @var self::BATCH_MODE_* */
- protected int $batchMode;
-
- protected bool $appendNewline;
-
- protected bool $ignoreEmptyContextAndExtra;
-
- protected bool $includeStacktraces = false;
+ protected $batchMode;
+ /** @var bool */
+ protected $appendNewline;
+ /** @var bool */
+ protected $ignoreEmptyContextAndExtra;
+ /** @var bool */
+ protected $includeStacktraces = false;
/**
* @param self::BATCH_MODE_* $batchMode
@@ -70,11 +70,11 @@ class JsonFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function format(LogRecord $record): string
+ public function format(array $record): string
{
- $normalized = parent::format($record);
+ $normalized = $this->normalize($record);
if (isset($normalized['context']) && $normalized['context'] === []) {
if ($this->ignoreEmptyContextAndExtra) {
@@ -95,16 +95,23 @@ class JsonFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function formatBatch(array $records): string
{
- return match ($this->batchMode) {
- static::BATCH_MODE_NEWLINES => $this->formatBatchNewlines($records),
- default => $this->formatBatchJson($records),
- };
+ switch ($this->batchMode) {
+ case static::BATCH_MODE_NEWLINES:
+ return $this->formatBatchNewlines($records);
+
+ case static::BATCH_MODE_JSON:
+ default:
+ return $this->formatBatchJson($records);
+ }
}
+ /**
+ * @return self
+ */
public function includeStacktraces(bool $include = true): self
{
$this->includeStacktraces = $include;
@@ -115,7 +122,7 @@ class JsonFormatter extends NormalizerFormatter
/**
* Return a JSON-encoded array of records.
*
- * @phpstan-param LogRecord[] $records
+ * @phpstan-param Record[] $records
*/
protected function formatBatchJson(array $records): string
{
@@ -126,24 +133,30 @@ class JsonFormatter extends NormalizerFormatter
* Use new lines to separate records instead of a
* JSON-encoded array.
*
- * @phpstan-param LogRecord[] $records
+ * @phpstan-param Record[] $records
*/
protected function formatBatchNewlines(array $records): string
{
+ $instance = $this;
+
$oldNewline = $this->appendNewline;
$this->appendNewline = false;
- $formatted = array_map(fn (LogRecord $record) => $this->format($record), $records);
+ array_walk($records, function (&$value, $key) use ($instance) {
+ $value = $instance->format($value);
+ });
$this->appendNewline = $oldNewline;
- return implode("\n", $formatted);
+ return implode("\n", $records);
}
/**
* Normalizes given $data.
*
- * @return null|scalar|array|object
+ * @param mixed $data
+ *
+ * @return mixed
*/
- protected function normalize(mixed $data, int $depth = 0): mixed
+ protected function normalize($data, int $depth = 0)
{
if ($depth > $this->maxNormalizeDepth) {
return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization';
@@ -179,7 +192,7 @@ class JsonFormatter extends NormalizerFormatter
return $data;
}
- if ($data instanceof Stringable) {
+ if (method_exists($data, '__toString')) {
return $data->__toString();
}
@@ -197,7 +210,7 @@ class JsonFormatter extends NormalizerFormatter
* Normalizes given exception with or without its own stack trace based on
* `includeStacktraces` property.
*
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function normalizeException(Throwable $e, int $depth = 0): array
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php
index 19fb72c5..e6e78983 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php
@@ -11,9 +11,7 @@
namespace Monolog\Formatter;
-use Closure;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* Formats incoming records into a one-line string
@@ -27,16 +25,22 @@ class LineFormatter extends NormalizerFormatter
{
public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
- protected string $format;
- protected bool $allowInlineLineBreaks;
- protected bool $ignoreEmptyContextAndExtra;
- protected bool $includeStacktraces;
- protected Closure|null $stacktracesParser = null;
+ /** @var string */
+ protected $format;
+ /** @var bool */
+ protected $allowInlineLineBreaks;
+ /** @var bool */
+ protected $ignoreEmptyContextAndExtra;
+ /** @var bool */
+ protected $includeStacktraces;
+ /** @var ?callable */
+ protected $stacktracesParser;
/**
- * @param string|null $format The format of the message
- * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
- * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
+ * @param string|null $format The format of the message
+ * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
+ * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
+ * @param bool $ignoreEmptyContextAndExtra
*/
public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = false)
{
@@ -47,7 +51,7 @@ class LineFormatter extends NormalizerFormatter
parent::__construct($dateFormat);
}
- public function includeStacktraces(bool $include = true, ?Closure $parser = null): self
+ public function includeStacktraces(bool $include = true, ?callable $parser = null): self
{
$this->includeStacktraces = $include;
if ($this->includeStacktraces) {
@@ -73,13 +77,14 @@ class LineFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function format(LogRecord $record): string
+ public function format(array $record): string
{
$vars = parent::format($record);
$output = $this->format;
+
foreach ($vars['extra'] as $var => $val) {
if (false !== strpos($output, '%extra.'.$var.'%')) {
$output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output);
@@ -95,12 +100,12 @@ class LineFormatter extends NormalizerFormatter
}
if ($this->ignoreEmptyContextAndExtra) {
- if (\count($vars['context']) === 0) {
+ if (empty($vars['context'])) {
unset($vars['context']);
$output = str_replace('%context%', '', $output);
}
- if (\count($vars['extra']) === 0) {
+ if (empty($vars['extra'])) {
unset($vars['extra']);
$output = str_replace('%extra%', '', $output);
}
@@ -117,7 +122,6 @@ class LineFormatter extends NormalizerFormatter
$output = preg_replace('/%(?:extra|context)\..+?%/', '', $output);
if (null === $output) {
$pcreErrorCode = preg_last_error();
-
throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
}
}
@@ -147,11 +151,11 @@ class LineFormatter extends NormalizerFormatter
{
$str = $this->formatException($e);
- if (($previous = $e->getPrevious()) instanceof \Throwable) {
+ if ($previous = $e->getPrevious()) {
do {
$depth++;
if ($depth > $this->maxNormalizeDepth) {
- $str .= '\n[previous exception] Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
+ $str .= "\n[previous exception] Over " . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
break;
}
@@ -228,7 +232,7 @@ class LineFormatter extends NormalizerFormatter
{
$trace = $e->getTraceAsString();
- if ($this->stacktracesParser !== null) {
+ if ($this->stacktracesParser) {
$trace = $this->stacktracesParserCustom($trace);
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php
index 5f0b6a45..29841aa3 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php
@@ -11,8 +11,6 @@
namespace Monolog\Formatter;
-use Monolog\LogRecord;
-
/**
* Encodes message information into JSON in a format compatible with Loggly.
*
@@ -35,13 +33,13 @@ class LogglyFormatter extends JsonFormatter
* @see https://www.loggly.com/docs/automated-parsing/#json
* @see \Monolog\Formatter\JsonFormatter::format()
*/
- protected function normalizeRecord(LogRecord $record): array
+ public function format(array $record): string
{
- $recordData = parent::normalizeRecord($record);
+ if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) {
+ $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO");
+ unset($record["datetime"]);
+ }
- $recordData["timestamp"] = $record->datetime->format("Y-m-d\TH:i:s.uO");
- unset($recordData["datetime"]);
-
- return $recordData;
+ return parent::format($record);
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php
index 10ad0d9c..b0451aba 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php
@@ -11,8 +11,6 @@
namespace Monolog\Formatter;
-use Monolog\LogRecord;
-
/**
* Encodes message information into JSON in a format compatible with Logmatic.
*
@@ -22,9 +20,15 @@ class LogmaticFormatter extends JsonFormatter
{
protected const MARKERS = ["sourcecode", "php"];
- protected string $hostname = '';
+ /**
+ * @var string
+ */
+ protected $hostname = '';
- protected string $appName = '';
+ /**
+ * @var string
+ */
+ protected $appname = '';
public function setHostname(string $hostname): self
{
@@ -33,9 +37,9 @@ class LogmaticFormatter extends JsonFormatter
return $this;
}
- public function setAppName(string $appName): self
+ public function setAppname(string $appname): self
{
- $this->appName = $appName;
+ $this->appname = $appname;
return $this;
}
@@ -46,19 +50,17 @@ class LogmaticFormatter extends JsonFormatter
* @see http://doc.logmatic.io/docs/basics-to-send-data
* @see \Monolog\Formatter\JsonFormatter::format()
*/
- public function normalizeRecord(LogRecord $record): array
+ public function format(array $record): string
{
- $record = parent::normalizeRecord($record);
-
- if ($this->hostname !== '') {
+ if (!empty($this->hostname)) {
$record["hostname"] = $this->hostname;
}
- if ($this->appName !== '') {
- $record["appname"] = $this->appName;
+ if (!empty($this->appname)) {
+ $record["appname"] = $this->appname;
}
$record["@marker"] = static::MARKERS;
- return $record;
+ return parent::format($record);
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php
index d0e8749e..f8de0d33 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php
@@ -11,8 +11,6 @@
namespace Monolog\Formatter;
-use Monolog\LogRecord;
-
/**
* Serializes a log message to Logstash Event Format
*
@@ -26,22 +24,22 @@ class LogstashFormatter extends NormalizerFormatter
/**
* @var string the name of the system for the Logstash log message, used to fill the @source field
*/
- protected string $systemName;
+ protected $systemName;
/**
* @var string an application name for the Logstash log message, used to fill the @type field
*/
- protected string $applicationName;
+ protected $applicationName;
/**
* @var string the key for 'extra' fields from the Monolog record
*/
- protected string $extraKey;
+ protected $extraKey;
/**
* @var string the key for 'context' fields from the Monolog record
*/
- protected string $contextKey;
+ protected $contextKey;
/**
* @param string $applicationName The application that sends the data, used as the "type" field of logstash
@@ -61,38 +59,41 @@ class LogstashFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function format(LogRecord $record): string
+ public function format(array $record): string
{
- $recordData = parent::format($record);
+ $record = parent::format($record);
+ if (empty($record['datetime'])) {
+ $record['datetime'] = gmdate('c');
+ }
$message = [
- '@timestamp' => $recordData['datetime'],
+ '@timestamp' => $record['datetime'],
'@version' => 1,
'host' => $this->systemName,
];
- if (isset($recordData['message'])) {
- $message['message'] = $recordData['message'];
+ if (isset($record['message'])) {
+ $message['message'] = $record['message'];
}
- if (isset($recordData['channel'])) {
- $message['type'] = $recordData['channel'];
- $message['channel'] = $recordData['channel'];
+ if (isset($record['channel'])) {
+ $message['type'] = $record['channel'];
+ $message['channel'] = $record['channel'];
}
- if (isset($recordData['level_name'])) {
- $message['level'] = $recordData['level_name'];
+ if (isset($record['level_name'])) {
+ $message['level'] = $record['level_name'];
}
- if (isset($recordData['level'])) {
- $message['monolog_level'] = $recordData['level'];
+ if (isset($record['level'])) {
+ $message['monolog_level'] = $record['level'];
}
- if ('' !== $this->applicationName) {
+ if ($this->applicationName) {
$message['type'] = $this->applicationName;
}
- if (\count($recordData['extra']) > 0) {
- $message[$this->extraKey] = $recordData['extra'];
+ if (!empty($record['extra'])) {
+ $message[$this->extraKey] = $record['extra'];
}
- if (\count($recordData['context']) > 0) {
- $message[$this->contextKey] = $recordData['context'];
+ if (!empty($record['context'])) {
+ $message[$this->contextKey] = $record['context'];
}
return $this->toJson($message) . "\n";
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php
index a3bdd4f8..fca69a89 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php
@@ -14,7 +14,6 @@ namespace Monolog\Formatter;
use MongoDB\BSON\Type;
use MongoDB\BSON\UTCDateTime;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* Formats a record for use with the MongoDBHandler.
@@ -23,12 +22,15 @@ use Monolog\LogRecord;
*/
class MongoDBFormatter implements FormatterInterface
{
- private bool $exceptionTraceAsString;
- private int $maxNestingLevel;
- private bool $isLegacyMongoExt;
+ /** @var bool */
+ private $exceptionTraceAsString;
+ /** @var int */
+ private $maxNestingLevel;
+ /** @var bool */
+ private $isLegacyMongoExt;
/**
- * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record->context is 2
+ * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2
* @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings
*/
public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true)
@@ -40,20 +42,20 @@ class MongoDBFormatter implements FormatterInterface
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*
* @return mixed[]
*/
- public function format(LogRecord $record): array
+ public function format(array $record): array
{
/** @var mixed[] $res */
- $res = $this->formatArray($record->toArray());
+ $res = $this->formatArray($record);
return $res;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*
* @return array
*/
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php
index 1323587b..f926a842 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php
@@ -14,7 +14,6 @@ namespace Monolog\Formatter;
use Monolog\DateTimeImmutable;
use Monolog\Utils;
use Throwable;
-use Monolog\LogRecord;
/**
* Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
@@ -25,11 +24,15 @@ class NormalizerFormatter implements FormatterInterface
{
public const SIMPLE_DATE = "Y-m-d\TH:i:sP";
- protected string $dateFormat;
- protected int $maxNormalizeDepth = 9;
- protected int $maxNormalizeItemCount = 1000;
+ /** @var string */
+ protected $dateFormat;
+ /** @var int */
+ protected $maxNormalizeDepth = 9;
+ /** @var int */
+ protected $maxNormalizeItemCount = 1000;
- private int $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS;
+ /** @var int */
+ private $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS;
/**
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
@@ -43,25 +46,17 @@ class NormalizerFormatter implements FormatterInterface
}
/**
- * @inheritDoc
- */
- public function format(LogRecord $record)
- {
- return $this->normalizeRecord($record);
- }
-
- /**
- * Normalize an arbitrary value to a scalar|array|null
+ * {@inheritDoc}
*
- * @return null|scalar|array
+ * @param mixed[] $record
*/
- public function normalizeValue(mixed $data): mixed
+ public function format(array $record)
{
- return $this->normalize($data);
+ return $this->normalize($record);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function formatBatch(array $records)
{
@@ -129,25 +124,10 @@ class NormalizerFormatter implements FormatterInterface
}
/**
- * Provided as extension point
- *
- * Because normalize is called with sub-values of context data etc, normalizeRecord can be
- * extended when data needs to be appended on the record array but not to other normalized data.
- *
- * @return array
+ * @param mixed $data
+ * @return null|scalar|array
*/
- protected function normalizeRecord(LogRecord $record): array
- {
- /** @var array $normalized */
- $normalized = $this->normalize($record->toArray());
-
- return $normalized;
- }
-
- /**
- * @return null|scalar|array
- */
- protected function normalize(mixed $data, int $depth = 0): mixed
+ protected function normalize($data, int $depth = 0)
{
if ($depth > $this->maxNormalizeDepth) {
return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
@@ -192,14 +172,17 @@ class NormalizerFormatter implements FormatterInterface
}
if ($data instanceof \JsonSerializable) {
- /** @var null|scalar|array $value */
+ /** @var null|scalar|array $value */
$value = $data->jsonSerialize();
+ } elseif (\get_class($data) === '__PHP_Incomplete_Class') {
+ $accessor = new \ArrayObject($data);
+ $value = (string) $accessor['__PHP_Incomplete_Class_Name'];
} elseif (method_exists($data, '__toString')) {
/** @var string $value */
$value = $data->__toString();
} else {
// the rest is normalized by json encoding and decoding it
- /** @var null|scalar|array $value */
+ /** @var null|scalar|array $value */
$value = json_decode($this->toJson($data, true), true);
}
@@ -253,12 +236,12 @@ class NormalizerFormatter implements FormatterInterface
$trace = $e->getTrace();
foreach ($trace as $frame) {
- if (isset($frame['file'], $frame['line'])) {
+ if (isset($frame['file'])) {
$data['trace'][] = $frame['file'].':'.$frame['line'];
}
}
- if (($previous = $e->getPrevious()) instanceof \Throwable) {
+ if ($previous = $e->getPrevious()) {
$data['previous'] = $this->normalizeException($previous, $depth + 1);
}
@@ -277,7 +260,10 @@ class NormalizerFormatter implements FormatterInterface
return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors);
}
- protected function formatDate(\DateTimeInterface $date): string
+ /**
+ * @return string
+ */
+ protected function formatDate(\DateTimeInterface $date)
{
// in case the date format isn't custom then we defer to the custom DateTimeImmutable
// formatting logic, which will pick the right format based on whether useMicroseconds is on
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php
index 4bc20a08..187bc550 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php
@@ -11,10 +11,8 @@
namespace Monolog\Formatter;
-use Monolog\LogRecord;
-
/**
- * Formats data into an associative array of scalar (+ null) values.
+ * Formats data into an associative array of scalar values.
* Objects and arrays will be JSON encoded.
*
* @author Andrew Lawson
@@ -22,21 +20,25 @@ use Monolog\LogRecord;
class ScalarFormatter extends NormalizerFormatter
{
/**
- * @inheritDoc
+ * {@inheritDoc}
*
* @phpstan-return array $record
*/
- public function format(LogRecord $record): array
+ public function format(array $record): array
{
$result = [];
- foreach ($record->toArray() as $key => $value) {
- $result[$key] = $this->toScalar($value);
+ foreach ($record as $key => $value) {
+ $result[$key] = $this->normalizeValue($value);
}
return $result;
}
- protected function toScalar(mixed $value): string|int|float|bool|null
+ /**
+ * @param mixed $value
+ * @return scalar|null
+ */
+ protected function normalizeValue($value)
{
$normalized = $this->normalize($value);
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php
deleted file mode 100644
index 6ed7e92e..00000000
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php
+++ /dev/null
@@ -1,66 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Monolog\Formatter;
-
-use Monolog\Level;
-use Monolog\LogRecord;
-
-/**
- * Serializes a log message according to RFC 5424
- *
- * @author Dalibor Karlović
- * @author Renat Gabdullin
- */
-class SyslogFormatter extends LineFormatter
-{
- private const SYSLOG_FACILITY_USER = 1;
- private const FORMAT = "<%extra.priority%>1 %datetime% %extra.hostname% %extra.app-name% %extra.procid% %channel% %extra.structured-data% %level_name%: %message% %context% %extra%\n";
- private const NILVALUE = '-';
-
- private string $hostname;
- private int $procid;
-
- public function __construct(private string $applicationName = self::NILVALUE)
- {
- parent::__construct(self::FORMAT, 'Y-m-d\TH:i:s.uP', true, true);
- $this->hostname = (string) gethostname();
- $this->procid = (int) getmypid();
- }
-
- public function format(LogRecord $record): string
- {
- $record->extra = $this->formatExtra($record);
-
- return parent::format($record);
- }
-
- /**
- * @param LogRecord $record
- * @return array
- */
- private function formatExtra(LogRecord $record): array
- {
- $extra = $record->extra;
- $extra['app-name'] = $this->applicationName;
- $extra['hostname'] = $this->hostname;
- $extra['procid'] = $this->procid;
- $extra['priority'] = self::calculatePriority($record->level);
- $extra['structured-data'] = self::NILVALUE;
-
- return $extra;
- }
-
- private static function calculatePriority(Level $level): int
- {
- return (self::SYSLOG_FACILITY_USER * 8) + $level->toRFC5424Level();
- }
-}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php
index 8ef7b7d1..6539b347 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php
@@ -11,8 +11,7 @@
namespace Monolog\Formatter;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* Serializes a log message according to Wildfire's header requirements
@@ -20,9 +19,27 @@ use Monolog\LogRecord;
* @author Eric Clemmons (@ericclemmons)
* @author Christophe Coevoet
* @author Kirill chEbba Chebunin
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
*/
class WildfireFormatter extends NormalizerFormatter
{
+ /**
+ * Translates Monolog log levels to Wildfire levels.
+ *
+ * @var array
+ */
+ private $logLevels = [
+ Logger::DEBUG => 'LOG',
+ Logger::INFO => 'INFO',
+ Logger::NOTICE => 'INFO',
+ Logger::WARNING => 'WARN',
+ Logger::ERROR => 'ERROR',
+ Logger::CRITICAL => 'ERROR',
+ Logger::ALERT => 'ERROR',
+ Logger::EMERGENCY => 'ERROR',
+ ];
+
/**
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
*/
@@ -35,61 +52,46 @@ class WildfireFormatter extends NormalizerFormatter
}
/**
- * Translates Monolog log levels to Wildfire levels.
+ * {@inheritDoc}
*
- * @return 'LOG'|'INFO'|'WARN'|'ERROR'
+ * @return string
*/
- private function toWildfireLevel(Level $level): string
- {
- return match ($level) {
- Level::Debug => 'LOG',
- Level::Info => 'INFO',
- Level::Notice => 'INFO',
- Level::Warning => 'WARN',
- Level::Error => 'ERROR',
- Level::Critical => 'ERROR',
- Level::Alert => 'ERROR',
- Level::Emergency => 'ERROR',
- };
- }
-
- /**
- * @inheritDoc
- */
- public function format(LogRecord $record): string
+ public function format(array $record): string
{
// Retrieve the line and file if set and remove them from the formatted extra
$file = $line = '';
- if (isset($record->extra['file'])) {
- $file = $record->extra['file'];
- unset($record->extra['file']);
+ if (isset($record['extra']['file'])) {
+ $file = $record['extra']['file'];
+ unset($record['extra']['file']);
}
- if (isset($record->extra['line'])) {
- $line = $record->extra['line'];
- unset($record->extra['line']);
+ if (isset($record['extra']['line'])) {
+ $line = $record['extra']['line'];
+ unset($record['extra']['line']);
}
- $message = ['message' => $record->message];
+ /** @var mixed[] $record */
+ $record = $this->normalize($record);
+ $message = ['message' => $record['message']];
$handleError = false;
- if (count($record->context) > 0) {
- $message['context'] = $this->normalize($record->context);
+ if ($record['context']) {
+ $message['context'] = $record['context'];
$handleError = true;
}
- if (count($record->extra) > 0) {
- $message['extra'] = $this->normalize($record->extra);
+ if ($record['extra']) {
+ $message['extra'] = $record['extra'];
$handleError = true;
}
if (count($message) === 1) {
$message = reset($message);
}
- if (is_array($message) && isset($message['context']['table'])) {
+ if (isset($record['context']['table'])) {
$type = 'TABLE';
- $label = $record->channel .': '. $record->message;
- $message = $message['context']['table'];
+ $label = $record['channel'] .': '. $record['message'];
+ $message = $record['context']['table'];
} else {
- $type = $this->toWildfireLevel($record->level);
- $label = $record->channel;
+ $type = $this->logLevels[$record['level']];
+ $label = $record['channel'];
}
// Create JSON object describing the appearance of the message in the console
@@ -112,7 +114,7 @@ class WildfireFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*
* @phpstan-return never
*/
@@ -122,11 +124,11 @@ class WildfireFormatter extends NormalizerFormatter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*
- * @return null|scalar|array|object
+ * @return null|scalar|array|object
*/
- protected function normalize(mixed $data, int $depth = 0): mixed
+ protected function normalize($data, int $depth = 0)
{
if (is_object($data) && !$data instanceof \DateTimeInterface) {
return $data;
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php
index 3399a54e..a5cdaa71 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php
@@ -11,50 +11,55 @@
namespace Monolog\Handler;
-use Monolog\Level;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Psr\Log\LogLevel;
-use Monolog\LogRecord;
/**
* Base Handler class providing basic level/bubble support
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
abstract class AbstractHandler extends Handler implements ResettableInterface
{
- protected Level $level = Level::Debug;
- protected bool $bubble = true;
+ /**
+ * @var int
+ * @phpstan-var Level
+ */
+ protected $level = Logger::DEBUG;
+ /** @var bool */
+ protected $bubble = true;
/**
- * @param int|string|Level|LogLevel::* $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
+ * @param int|string $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
*
- * @phpstan-param value-of|value-of|Level|LogLevel::* $level
+ * @phpstan-param Level|LevelName|LogLevel::* $level
*/
- public function __construct(int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct($level = Logger::DEBUG, bool $bubble = true)
{
$this->setLevel($level);
$this->bubble = $bubble;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function isHandling(LogRecord $record): bool
+ public function isHandling(array $record): bool
{
- return $record->level->value >= $this->level->value;
+ return $record['level'] >= $this->level;
}
/**
* Sets minimum logging level at which this handler will be triggered.
*
- * @param Level|LogLevel::* $level Level or level name
- *
- * @phpstan-param value-of|value-of|Level|LogLevel::* $level
+ * @param Level|LevelName|LogLevel::* $level Level or level name
+ * @return self
*/
- public function setLevel(int|string|Level $level): self
+ public function setLevel($level): self
{
$this->level = Logger::toMonologLevel($level);
@@ -63,8 +68,12 @@ abstract class AbstractHandler extends Handler implements ResettableInterface
/**
* Gets minimum logging level at which this handler will be triggered.
+ *
+ * @return int
+ *
+ * @phpstan-return Level
*/
- public function getLevel(): Level
+ public function getLevel(): int
{
return $this->level;
}
@@ -72,8 +81,9 @@ abstract class AbstractHandler extends Handler implements ResettableInterface
/**
* Sets the bubbling behavior.
*
- * @param bool $bubble true means that this handler allows bubbling.
- * false means that bubbling is not permitted.
+ * @param bool $bubble true means that this handler allows bubbling.
+ * false means that bubbling is not permitted.
+ * @return self
*/
public function setBubble(bool $bubble): self
{
@@ -94,9 +104,9 @@ abstract class AbstractHandler extends Handler implements ResettableInterface
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function reset(): void
+ public function reset()
{
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php
index de13a76b..77e533fc 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php
@@ -11,8 +11,6 @@
namespace Monolog\Handler;
-use Monolog\LogRecord;
-
/**
* Base Handler class providing the Handler structure, including processors and formatters
*
@@ -20,6 +18,11 @@ use Monolog\LogRecord;
*
* @author Jordi Boggiano
* @author Christophe Coevoet
+ *
+ * @phpstan-import-type LevelName from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed}
*/
abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
@@ -27,19 +30,20 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc
use FormattableHandlerTrait;
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
}
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
+ /** @var Record $record */
$record = $this->processRecord($record);
}
- $record->formatted = $this->getFormatter()->format($record);
+ $record['formatted'] = $this->getFormatter()->format($record);
$this->write($record);
@@ -47,11 +51,16 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc
}
/**
- * Writes the (already formatted) record down to the log of the implementing handler
+ * Writes the record down to the log of the implementing handler
+ *
+ * @phpstan-param FormattedRecord $record
*/
- abstract protected function write(LogRecord $record): void;
+ abstract protected function write(array $record): void;
- public function reset(): void
+ /**
+ * @return void
+ */
+ public function reset()
{
parent::reset();
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php
index 695a1c07..5e5ad1c1 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php
@@ -11,59 +11,70 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
/**
* Common syslog functionality
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
*/
abstract class AbstractSyslogHandler extends AbstractProcessingHandler
{
- protected int $facility;
+ /** @var int */
+ protected $facility;
+
+ /**
+ * Translates Monolog log levels to syslog log priorities.
+ * @var array
+ * @phpstan-var array
+ */
+ protected $logLevels = [
+ Logger::DEBUG => LOG_DEBUG,
+ Logger::INFO => LOG_INFO,
+ Logger::NOTICE => LOG_NOTICE,
+ Logger::WARNING => LOG_WARNING,
+ Logger::ERROR => LOG_ERR,
+ Logger::CRITICAL => LOG_CRIT,
+ Logger::ALERT => LOG_ALERT,
+ Logger::EMERGENCY => LOG_EMERG,
+ ];
/**
* List of valid log facility names.
* @var array
*/
- protected array $facilities = [
- 'auth' => \LOG_AUTH,
- 'authpriv' => \LOG_AUTHPRIV,
- 'cron' => \LOG_CRON,
- 'daemon' => \LOG_DAEMON,
- 'kern' => \LOG_KERN,
- 'lpr' => \LOG_LPR,
- 'mail' => \LOG_MAIL,
- 'news' => \LOG_NEWS,
- 'syslog' => \LOG_SYSLOG,
- 'user' => \LOG_USER,
- 'uucp' => \LOG_UUCP,
+ protected $facilities = [
+ 'auth' => LOG_AUTH,
+ 'authpriv' => LOG_AUTHPRIV,
+ 'cron' => LOG_CRON,
+ 'daemon' => LOG_DAEMON,
+ 'kern' => LOG_KERN,
+ 'lpr' => LOG_LPR,
+ 'mail' => LOG_MAIL,
+ 'news' => LOG_NEWS,
+ 'syslog' => LOG_SYSLOG,
+ 'user' => LOG_USER,
+ 'uucp' => LOG_UUCP,
];
- /**
- * Translates Monolog log levels to syslog log priorities.
- */
- protected function toSyslogPriority(Level $level): int
- {
- return $level->toRFC5424Level();
- }
-
/**
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
*/
- public function __construct(string|int $facility = \LOG_USER, int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct($facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true)
{
parent::__construct($level, $bubble);
if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
- $this->facilities['local0'] = \LOG_LOCAL0;
- $this->facilities['local1'] = \LOG_LOCAL1;
- $this->facilities['local2'] = \LOG_LOCAL2;
- $this->facilities['local3'] = \LOG_LOCAL3;
- $this->facilities['local4'] = \LOG_LOCAL4;
- $this->facilities['local5'] = \LOG_LOCAL5;
- $this->facilities['local6'] = \LOG_LOCAL6;
- $this->facilities['local7'] = \LOG_LOCAL7;
+ $this->facilities['local0'] = LOG_LOCAL0;
+ $this->facilities['local1'] = LOG_LOCAL1;
+ $this->facilities['local2'] = LOG_LOCAL2;
+ $this->facilities['local3'] = LOG_LOCAL3;
+ $this->facilities['local4'] = LOG_LOCAL4;
+ $this->facilities['local5'] = LOG_LOCAL5;
+ $this->facilities['local6'] = LOG_LOCAL6;
+ $this->facilities['local7'] = LOG_LOCAL7;
} else {
$this->facilities['local0'] = 128; // LOG_LOCAL0
$this->facilities['local1'] = 136; // LOG_LOCAL1
@@ -86,7 +97,7 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php
index b25e4f13..994872ce 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php
@@ -11,38 +11,24 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Channel\AMQPChannel;
use AMQPExchange;
-use Monolog\LogRecord;
+/**
+ * @phpstan-import-type Record from \Monolog\Logger
+ */
class AmqpHandler extends AbstractProcessingHandler
{
- protected AMQPExchange|AMQPChannel $exchange;
-
- /** @var array */
- private array $extraAttributes = [];
-
- protected string $exchangeName;
-
/**
- * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
- * @param string|null $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
+ * @var AMQPExchange|AMQPChannel $exchange
*/
- public function __construct(AMQPExchange|AMQPChannel $exchange, ?string $exchangeName = null, int|string|Level $level = Level::Debug, bool $bubble = true)
- {
- if ($exchange instanceof AMQPChannel) {
- $this->exchangeName = (string) $exchangeName;
- } elseif ($exchangeName !== null) {
- @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED);
- }
- $this->exchange = $exchange;
-
- parent::__construct($level, $bubble);
- }
+ protected $exchange;
+ /** @var array */
+ private $extraAttributes = [];
/**
* @return array
@@ -59,7 +45,7 @@ class AmqpHandler extends AbstractProcessingHandler
* message_id, user_id, app_id, delivery_mode,
* priority, timestamp, expiration, type
* or reply_to, headers.
- * @return $this
+ * @return AmqpHandler
*/
public function setExtraAttributes(array $extraAttributes): self
{
@@ -68,11 +54,34 @@ class AmqpHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * @var string
*/
- protected function write(LogRecord $record): void
+ protected $exchangeName;
+
+ /**
+ * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
+ * @param string|null $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
+ */
+ public function __construct($exchange, ?string $exchangeName = null, $level = Logger::DEBUG, bool $bubble = true)
{
- $data = $record->formatted;
+ if ($exchange instanceof AMQPChannel) {
+ $this->exchangeName = (string) $exchangeName;
+ } elseif (!$exchange instanceof AMQPExchange) {
+ throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required');
+ } elseif ($exchangeName) {
+ @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED);
+ }
+ $this->exchange = $exchange;
+
+ parent::__construct($level, $bubble);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function write(array $record): void
+ {
+ $data = $record["formatted"];
$routingKey = $this->getRoutingKey($record);
if ($this->exchange instanceof AMQPExchange) {
@@ -80,7 +89,7 @@ class AmqpHandler extends AbstractProcessingHandler
'delivery_mode' => 2,
'content_type' => 'application/json',
];
- if (\count($this->extraAttributes) > 0) {
+ if ($this->extraAttributes) {
$attributes = array_merge($attributes, $this->extraAttributes);
}
$this->exchange->publish(
@@ -99,7 +108,7 @@ class AmqpHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
@@ -114,6 +123,7 @@ class AmqpHandler extends AbstractProcessingHandler
continue;
}
+ /** @var Record $record */
$record = $this->processRecord($record);
$data = $this->getFormatter()->format($record);
@@ -129,27 +139,30 @@ class AmqpHandler extends AbstractProcessingHandler
/**
* Gets the routing key for the AMQP exchange
+ *
+ * @phpstan-param Record $record
*/
- protected function getRoutingKey(LogRecord $record): string
+ protected function getRoutingKey(array $record): string
{
- $routingKey = sprintf('%s.%s', $record->level->name, $record->channel);
+ $routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']);
return strtolower($routingKey);
}
private function createAmqpMessage(string $data): AMQPMessage
{
- return new AMQPMessage(
- $data,
- [
- 'delivery_mode' => 2,
- 'content_type' => 'application/json',
- ]
- );
+ $attributes = [
+ 'delivery_mode' => 2,
+ 'content_type' => 'application/json',
+ ];
+ if ($this->extraAttributes) {
+ $attributes = array_merge($attributes, $this->extraAttributes);
+ }
+ return new AMQPMessage($data, $attributes);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php
index 28564b3f..95bbfed4 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php
@@ -14,30 +14,35 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Utils;
-use Monolog\LogRecord;
+use Monolog\Logger;
use function count;
use function headers_list;
use function stripos;
+use function trigger_error;
+
+use const E_USER_DEPRECATED;
/**
* Handler sending logs to browser's javascript console with no browser extension required
*
* @author Olivier Poitrey
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class BrowserConsoleHandler extends AbstractProcessingHandler
{
- protected static bool $initialized = false;
-
- /** @var LogRecord[] */
- protected static array $records = [];
+ /** @var bool */
+ protected static $initialized = false;
+ /** @var FormattedRecord[] */
+ protected static $records = [];
protected const FORMAT_HTML = 'html';
protected const FORMAT_JS = 'js';
protected const FORMAT_UNKNOWN = 'unknown';
/**
- * @inheritDoc
+ * {@inheritDoc}
*
* Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format.
*
@@ -51,9 +56,9 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
// Accumulate records
static::$records[] = $record;
@@ -76,11 +81,11 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
return;
}
- if (count(static::$records) > 0) {
+ if (count(static::$records)) {
if ($format === self::FORMAT_HTML) {
- static::writeOutput('');
- } else { // js format
- static::writeOutput(self::generateScript());
+ static::writeOutput('');
+ } elseif ($format === self::FORMAT_JS) {
+ static::writeOutput(static::generateScript());
}
static::resetStatic();
}
@@ -91,7 +96,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
self::resetStatic();
}
- public function reset(): void
+ public function reset()
{
parent::reset();
@@ -169,18 +174,18 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
{
$script = [];
foreach (static::$records as $record) {
- $context = self::dump('Context', $record->context);
- $extra = self::dump('Extra', $record->extra);
+ $context = static::dump('Context', $record['context']);
+ $extra = static::dump('Extra', $record['extra']);
- if (\count($context) === 0 && \count($extra) === 0) {
- $script[] = self::call_array('log', self::handleStyles($record->formatted));
+ if (empty($context) && empty($extra)) {
+ $script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted']));
} else {
$script = array_merge(
$script,
- [self::call_array('groupCollapsed', self::handleStyles($record->formatted))],
+ [static::call_array('groupCollapsed', static::handleStyles($record['formatted']))],
$context,
$extra,
- [self::call('groupEnd')]
+ [static::call('groupEnd')]
);
}
}
@@ -188,6 +193,20 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
}
+ private static function getConsoleMethodForLevel(int $level): string
+ {
+ return [
+ Logger::DEBUG => 'debug',
+ Logger::INFO => 'info',
+ Logger::NOTICE => 'info',
+ Logger::WARNING => 'warn',
+ Logger::ERROR => 'error',
+ Logger::CRITICAL => 'error',
+ Logger::ALERT => 'error',
+ Logger::EMERGENCY => 'error',
+ ][$level] ?? 'log';
+ }
+
/**
* @return string[]
*/
@@ -199,14 +218,14 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
foreach (array_reverse($matches) as $match) {
$args[] = '"font-weight: normal"';
- $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0]));
+ $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
$pos = $match[0][1];
$format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + strlen($match[0][0]));
}
- $args[] = self::quote('font-weight: normal');
- $args[] = self::quote($format);
+ $args[] = static::quote('font-weight: normal');
+ $args[] = static::quote($format);
return array_reverse($args);
}
@@ -232,7 +251,6 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
if (null === $style) {
$pcreErrorCode = preg_last_error();
-
throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
}
@@ -247,16 +265,16 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
{
$script = [];
$dict = array_filter($dict);
- if (\count($dict) === 0) {
+ if (empty($dict)) {
return $script;
}
- $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));
+ $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title));
foreach ($dict as $key => $value) {
$value = json_encode($value);
if (empty($value)) {
- $value = self::quote('');
+ $value = static::quote('');
}
- $script[] = self::call('log', self::quote('%s: %o'), self::quote((string) $key), $value);
+ $script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value);
}
return $script;
@@ -277,7 +295,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
throw new \UnexpectedValueException('Expected the first arg to be a string, got: '.var_export($method, true));
}
- return self::call_array($method, $args);
+ return static::call_array($method, $args);
}
/**
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php
index ff89faa8..fcce5d63 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php
@@ -11,10 +11,9 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
-use Monolog\LogRecord;
/**
* Buffers all records until closing the handler and then pass them as batch.
@@ -23,30 +22,32 @@ use Monolog\LogRecord;
* sending one per log message.
*
* @author Christophe Coevoet
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
use ProcessableHandlerTrait;
- protected HandlerInterface $handler;
-
- protected int $bufferSize = 0;
-
- protected int $bufferLimit;
-
- protected bool $flushOnOverflow;
-
- /** @var LogRecord[] */
- protected array $buffer = [];
-
- protected bool $initialized = false;
+ /** @var HandlerInterface */
+ protected $handler;
+ /** @var int */
+ protected $bufferSize = 0;
+ /** @var int */
+ protected $bufferLimit;
+ /** @var bool */
+ protected $flushOnOverflow;
+ /** @var Record[] */
+ protected $buffer = [];
+ /** @var bool */
+ protected $initialized = false;
/**
* @param HandlerInterface $handler Handler.
* @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
* @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
*/
- public function __construct(HandlerInterface $handler, int $bufferLimit = 0, int|string|Level $level = Level::Debug, bool $bubble = true, bool $flushOnOverflow = false)
+ public function __construct(HandlerInterface $handler, int $bufferLimit = 0, $level = Logger::DEBUG, bool $bubble = true, bool $flushOnOverflow = false)
{
parent::__construct($level, $bubble);
$this->handler = $handler;
@@ -55,11 +56,11 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
- if ($record->level->isLowerThan($this->level)) {
+ if ($record['level'] < $this->level) {
return false;
}
@@ -78,7 +79,8 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
}
}
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
+ /** @var Record $record */
$record = $this->processRecord($record);
}
@@ -106,7 +108,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function close(): void
{
@@ -124,7 +126,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
$this->buffer = [];
}
- public function reset(): void
+ public function reset()
{
$this->flush();
@@ -138,7 +140,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -152,7 +154,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function getFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php
index 3742d47d..234ecf61 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php
@@ -13,10 +13,8 @@ namespace Monolog\Handler;
use Monolog\Formatter\ChromePHPFormatter;
use Monolog\Formatter\FormatterInterface;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
-use Monolog\LogRecord;
-use Monolog\DateTimeImmutable;
/**
* Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
@@ -24,6 +22,8 @@ use Monolog\DateTimeImmutable;
* This also works out of the box with Firefox 43+
*
* @author Christophe Coevoet
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class ChromePHPHandler extends AbstractProcessingHandler
{
@@ -44,25 +44,29 @@ class ChromePHPHandler extends AbstractProcessingHandler
*/
protected const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}';
- protected static bool $initialized = false;
+ /** @var bool */
+ protected static $initialized = false;
/**
* Tracks whether we sent too much data
*
* Chrome limits the headers to 4KB, so when we sent 3KB we stop sending
+ *
+ * @var bool
*/
- protected static bool $overflowed = false;
+ protected static $overflowed = false;
/** @var mixed[] */
- protected static array $json = [
+ protected static $json = [
'version' => self::VERSION,
'columns' => ['label', 'log', 'backtrace', 'type'],
'rows' => [],
];
- protected static bool $sendHeaders = true;
+ /** @var bool */
+ protected static $sendHeaders = true;
- public function __construct(int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct($level = Logger::DEBUG, bool $bubble = true)
{
parent::__construct($level, $bubble);
if (!function_exists('json_encode')) {
@@ -71,7 +75,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
@@ -82,15 +86,15 @@ class ChromePHPHandler extends AbstractProcessingHandler
$messages = [];
foreach ($records as $record) {
- if ($record->level < $this->level) {
+ if ($record['level'] < $this->level) {
continue;
}
-
+ /** @var Record $message */
$message = $this->processRecord($record);
$messages[] = $message;
}
- if (\count($messages) > 0) {
+ if (!empty($messages)) {
$messages = $this->getFormatter()->formatBatch($messages);
self::$json['rows'] = array_merge(self::$json['rows'], $messages);
$this->send();
@@ -98,7 +102,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
@@ -111,13 +115,13 @@ class ChromePHPHandler extends AbstractProcessingHandler
* @see sendHeader()
* @see send()
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
if (!$this->isWebRequest()) {
return;
}
- self::$json['rows'][] = $record->formatted;
+ self::$json['rows'][] = $record['formatted'];
$this->send();
}
@@ -149,12 +153,15 @@ class ChromePHPHandler extends AbstractProcessingHandler
if (strlen($data) > 3 * 1024) {
self::$overflowed = true;
- $record = new LogRecord(
- message: 'Incomplete logs, chrome header size limit reached',
- level: Level::Warning,
- channel: 'monolog',
- datetime: new DateTimeImmutable(true),
- );
+ $record = [
+ 'message' => 'Incomplete logs, chrome header size limit reached',
+ 'context' => [],
+ 'level' => Logger::WARNING,
+ 'level_name' => Logger::getLevelName(Logger::WARNING),
+ 'channel' => 'monolog',
+ 'datetime' => new \DateTimeImmutable(),
+ 'extra' => [],
+ ];
self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
$json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true);
$data = base64_encode($json);
@@ -180,7 +187,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
*/
protected function headersAccepted(): bool
{
- if (!isset($_SERVER['HTTP_USER_AGENT'])) {
+ if (empty($_SERVER['HTTP_USER_AGENT'])) {
return false;
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php
index 8d9c10e7..52657613 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php
@@ -13,42 +13,22 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* CouchDB handler
*
* @author Markus Bachmann
- * @phpstan-type Options array{
- * host: string,
- * port: int,
- * dbname: string,
- * username: string|null,
- * password: string|null
- * }
- * @phpstan-type InputOptions array{
- * host?: string,
- * port?: int,
- * dbname?: string,
- * username?: string|null,
- * password?: string|null
- * }
*/
class CouchDBHandler extends AbstractProcessingHandler
{
- /**
- * @var mixed[]
- * @phpstan-var Options
- */
- private array $options;
+ /** @var mixed[] */
+ private $options;
/**
* @param mixed[] $options
- *
- * @phpstan-param InputOptions $options
*/
- public function __construct(array $options = [], int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct(array $options = [], $level = Logger::DEBUG, bool $bubble = true)
{
$this->options = array_merge([
'host' => 'localhost',
@@ -62,12 +42,12 @@ class CouchDBHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
$basicAuth = null;
- if (null !== $this->options['username'] && null !== $this->options['password']) {
+ if ($this->options['username']) {
$basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']);
}
@@ -75,7 +55,7 @@ class CouchDBHandler extends AbstractProcessingHandler
$context = stream_context_create([
'http' => [
'method' => 'POST',
- 'content' => $record->formatted,
+ 'content' => $record['formatted'],
'ignore_errors' => true,
'max_redirects' => 0,
'header' => 'Content-type: application/json',
@@ -88,7 +68,7 @@ class CouchDBHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php
index 8388f5ad..3535a4fc 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php
@@ -11,9 +11,8 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* Logs to Cube.
@@ -24,13 +23,18 @@ use Monolog\LogRecord;
*/
class CubeHandler extends AbstractProcessingHandler
{
- private ?\Socket $udpConnection = null;
- private ?\CurlHandle $httpConnection = null;
- private string $scheme;
- private string $host;
- private int $port;
+ /** @var resource|\Socket|null */
+ private $udpConnection = null;
+ /** @var resource|\CurlHandle|null */
+ private $httpConnection = null;
+ /** @var string */
+ private $scheme;
+ /** @var string */
+ private $host;
+ /** @var int */
+ private $port;
/** @var string[] */
- private array $acceptedSchemes = ['http', 'udp'];
+ private $acceptedSchemes = ['http', 'udp'];
/**
* Create a Cube handler
@@ -39,7 +43,7 @@ class CubeHandler extends AbstractProcessingHandler
* A valid url must consist of three parts : protocol://host:port
* Only valid protocols used by Cube are http and udp
*/
- public function __construct(string $url, int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct(string $url, $level = Logger::DEBUG, bool $bubble = true)
{
$urlInfo = parse_url($url);
@@ -47,7 +51,7 @@ class CubeHandler extends AbstractProcessingHandler
throw new \UnexpectedValueException('URL "'.$url.'" is not valid');
}
- if (!in_array($urlInfo['scheme'], $this->acceptedSchemes, true)) {
+ if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
throw new \UnexpectedValueException(
'Invalid protocol (' . $urlInfo['scheme'] . ').'
. ' Valid options are ' . implode(', ', $this->acceptedSchemes)
@@ -56,7 +60,7 @@ class CubeHandler extends AbstractProcessingHandler
$this->scheme = $urlInfo['scheme'];
$this->host = $urlInfo['host'];
- $this->port = $urlInfo['port'];
+ $this->port = (int) $urlInfo['port'];
parent::__construct($level, $bubble);
}
@@ -107,24 +111,24 @@ class CubeHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $date = $record->datetime;
+ $date = $record['datetime'];
$data = ['time' => $date->format('Y-m-d\TH:i:s.uO')];
- $context = $record->context;
+ unset($record['datetime']);
- if (isset($context['type'])) {
- $data['type'] = $context['type'];
- unset($context['type']);
+ if (isset($record['context']['type'])) {
+ $data['type'] = $record['context']['type'];
+ unset($record['context']['type']);
} else {
- $data['type'] = $record->channel;
+ $data['type'] = $record['channel'];
}
- $data['data'] = $context;
- $data['data']['level'] = $record->level;
+ $data['data'] = $record['context'];
+ $data['data']['level'] = $record['level'];
if ($this->scheme === 'http') {
$this->writeHttp(Utils::jsonEncode($data));
@@ -135,20 +139,16 @@ class CubeHandler extends AbstractProcessingHandler
private function writeUdp(string $data): void
{
- if (null === $this->udpConnection) {
+ if (!$this->udpConnection) {
$this->connectUdp();
}
- if (null === $this->udpConnection) {
- throw new \LogicException('No UDP socket could be opened');
- }
-
socket_send($this->udpConnection, $data, strlen($data), 0);
}
private function writeHttp(string $data): void
{
- if (null === $this->httpConnection) {
+ if (!$this->httpConnection) {
$this->connectHttp();
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php
index 4decf0e6..7213e8ee 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php
@@ -21,7 +21,7 @@ use CurlHandle;
final class Util
{
/** @var array */
- private static array $retriableErrorCodes = [
+ private static $retriableErrorCodes = [
CURLE_COULDNT_RESOLVE_HOST,
CURLE_COULDNT_CONNECT,
CURLE_HTTP_NOT_FOUND,
@@ -34,17 +34,19 @@ final class Util
/**
* Executes a CURL request with optional retries and exception on failure
*
- * @param CurlHandle $ch curl handler
- * @return bool|string @see curl_exec
+ * @param resource|CurlHandle $ch curl handler
+ * @param int $retries
+ * @param bool $closeAfterDone
+ * @return bool|string @see curl_exec
*/
- public static function execute(CurlHandle $ch, int $retries = 5, bool $closeAfterDone = true)
+ public static function execute($ch, int $retries = 5, bool $closeAfterDone = true)
{
while ($retries--) {
$curlResponse = curl_exec($ch);
if ($curlResponse === false) {
$curlErrno = curl_errno($ch);
- if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || $retries === 0) {
+ if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) {
$curlError = curl_error($ch);
if ($closeAfterDone) {
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php
index 35549121..9b85ae7e 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php
@@ -11,10 +11,8 @@
namespace Monolog\Handler;
-use Monolog\Level;
use Monolog\Logger;
use Psr\Log\LogLevel;
-use Monolog\LogRecord;
/**
* Simple handler wrapper that deduplicates log records across multiple requests
@@ -35,29 +33,45 @@ use Monolog\LogRecord;
* same way.
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
*/
class DeduplicationHandler extends BufferHandler
{
- protected string $deduplicationStore;
-
- protected Level $deduplicationLevel;
-
- protected int $time;
-
- private bool $gc = false;
+ /**
+ * @var string
+ */
+ protected $deduplicationStore;
/**
- * @param HandlerInterface $handler Handler.
- * @param string $deduplicationStore The file/path where the deduplication log should be kept
- * @param int|string|Level|LogLevel::* $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
- * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- *
- * @phpstan-param value-of|value-of|Level|LogLevel::* $deduplicationLevel
+ * @var Level
*/
- public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, int|string|Level $deduplicationLevel = Level::Error, int $time = 60, bool $bubble = true)
+ protected $deduplicationLevel;
+
+ /**
+ * @var int
+ */
+ protected $time;
+
+ /**
+ * @var bool
+ */
+ private $gc = false;
+
+ /**
+ * @param HandlerInterface $handler Handler.
+ * @param string $deduplicationStore The file/path where the deduplication log should be kept
+ * @param string|int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
+ * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $deduplicationLevel
+ */
+ public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true)
{
- parent::__construct($handler, 0, Level::Debug, $bubble, false);
+ parent::__construct($handler, 0, Logger::DEBUG, $bubble, false);
$this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) .'.log' : $deduplicationStore;
$this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel);
@@ -73,8 +87,8 @@ class DeduplicationHandler extends BufferHandler
$passthru = null;
foreach ($this->buffer as $record) {
- if ($record->level->value >= $this->deduplicationLevel->value) {
- $passthru = $passthru === true || !$this->isDuplicate($record);
+ if ($record['level'] >= $this->deduplicationLevel) {
+ $passthru = $passthru || !$this->isDuplicate($record);
if ($passthru) {
$this->appendRecord($record);
}
@@ -93,7 +107,10 @@ class DeduplicationHandler extends BufferHandler
}
}
- private function isDuplicate(LogRecord $record): bool
+ /**
+ * @phpstan-param Record $record
+ */
+ private function isDuplicate(array $record): bool
{
if (!file_exists($this->deduplicationStore)) {
return false;
@@ -105,13 +122,13 @@ class DeduplicationHandler extends BufferHandler
}
$yesterday = time() - 86400;
- $timestampValidity = $record->datetime->getTimestamp() - $this->time;
- $expectedMessage = preg_replace('{[\r\n].*}', '', $record->message);
+ $timestampValidity = $record['datetime']->getTimestamp() - $this->time;
+ $expectedMessage = preg_replace('{[\r\n].*}', '', $record['message']);
for ($i = count($store) - 1; $i >= 0; $i--) {
list($timestamp, $level, $message) = explode(':', $store[$i], 3);
- if ($level === $record->level->getName() && $message === $expectedMessage && $timestamp > $timestampValidity) {
+ if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) {
return true;
}
@@ -131,7 +148,7 @@ class DeduplicationHandler extends BufferHandler
$handle = fopen($this->deduplicationStore, 'rw+');
- if (false === $handle) {
+ if (!$handle) {
throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore);
}
@@ -142,7 +159,7 @@ class DeduplicationHandler extends BufferHandler
while (!feof($handle)) {
$log = fgets($handle);
- if (is_string($log) && '' !== $log && substr($log, 0, 10) >= $timestampValidity) {
+ if ($log && substr($log, 0, 10) >= $timestampValidity) {
$validLogs[] = $log;
}
}
@@ -159,8 +176,11 @@ class DeduplicationHandler extends BufferHandler
$this->gc = false;
}
- private function appendRecord(LogRecord $record): void
+ /**
+ * @phpstan-param Record $record
+ */
+ private function appendRecord(array $record): void
{
- file_put_contents($this->deduplicationStore, $record->datetime->getTimestamp() . ':' . $record->level->getName() . ':' . preg_replace('{[\r\n].*}', '', $record->message) . "\n", FILE_APPEND);
+ file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND);
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php
index eab9f108..ebd52c3a 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php
@@ -11,11 +11,10 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
use Doctrine\CouchDB\CouchDBClient;
-use Monolog\LogRecord;
/**
* CouchDB handler for Doctrine CouchDB ODM
@@ -24,20 +23,21 @@ use Monolog\LogRecord;
*/
class DoctrineCouchDBHandler extends AbstractProcessingHandler
{
- private CouchDBClient $client;
+ /** @var CouchDBClient */
+ private $client;
- public function __construct(CouchDBClient $client, int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct(CouchDBClient $client, $level = Logger::DEBUG, bool $bubble = true)
{
$this->client = $client;
parent::__construct($level, $bubble);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $this->client->postDocument($record->formatted);
+ $this->client->postDocument($record['formatted']);
}
protected function getDefaultFormatter(): FormatterInterface
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php
index f1c5a959..21840bf6 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php
@@ -16,8 +16,7 @@ use Aws\DynamoDb\DynamoDbClient;
use Monolog\Formatter\FormatterInterface;
use Aws\DynamoDb\Marshaler;
use Monolog\Formatter\ScalarFormatter;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
@@ -29,15 +28,35 @@ class DynamoDbHandler extends AbstractProcessingHandler
{
public const DATE_FORMAT = 'Y-m-d\TH:i:s.uO';
- protected DynamoDbClient $client;
+ /**
+ * @var DynamoDbClient
+ */
+ protected $client;
- protected string $table;
+ /**
+ * @var string
+ */
+ protected $table;
- protected Marshaler $marshaler;
+ /**
+ * @var int
+ */
+ protected $version;
- public function __construct(DynamoDbClient $client, string $table, int|string|Level $level = Level::Debug, bool $bubble = true)
+ /**
+ * @var Marshaler
+ */
+ protected $marshaler;
+
+ public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true)
{
- $this->marshaler = new Marshaler;
+ /** @phpstan-ignore-next-line */
+ if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) {
+ $this->version = 3;
+ $this->marshaler = new Marshaler;
+ } else {
+ $this->version = 2;
+ }
$this->client = $client;
$this->table = $table;
@@ -46,12 +65,17 @@ class DynamoDbHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $filtered = $this->filterEmptyFields($record->formatted);
- $formatted = $this->marshaler->marshalItem($filtered);
+ $filtered = $this->filterEmptyFields($record['formatted']);
+ if ($this->version === 3) {
+ $formatted = $this->marshaler->marshalItem($filtered);
+ } else {
+ /** @phpstan-ignore-next-line */
+ $formatted = $this->client->formatAttributes($filtered);
+ }
$this->client->putItem([
'TableName' => $this->table,
@@ -66,12 +90,12 @@ class DynamoDbHandler extends AbstractProcessingHandler
protected function filterEmptyFields(array $record): array
{
return array_filter($record, function ($value) {
- return [] !== $value;
+ return !empty($value) || false === $value || 0 === $value;
});
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php
index d9b85b4d..fc92ca42 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php
@@ -14,10 +14,9 @@ namespace Monolog\Handler;
use Elastica\Document;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\ElasticaFormatter;
-use Monolog\Level;
+use Monolog\Logger;
use Elastica\Client;
use Elastica\Exception\ExceptionInterface;
-use Monolog\LogRecord;
/**
* Elastic Search handler
@@ -34,34 +33,24 @@ use Monolog\LogRecord;
* $log->pushHandler($handler);
*
* @author Jelle Vink
- * @phpstan-type Options array{
- * index: string,
- * type: string,
- * ignore_error: bool
- * }
- * @phpstan-type InputOptions array{
- * index?: string,
- * type?: string,
- * ignore_error?: bool
- * }
*/
class ElasticaHandler extends AbstractProcessingHandler
{
- protected Client $client;
+ /**
+ * @var Client
+ */
+ protected $client;
/**
* @var mixed[] Handler config options
- * @phpstan-var Options
*/
- protected array $options;
+ protected $options = [];
/**
* @param Client $client Elastica Client object
* @param mixed[] $options Handler configuration
- *
- * @phpstan-param InputOptions $options
*/
- public function __construct(Client $client, array $options = [], int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
{
parent::__construct($level, $bubble);
$this->client = $client;
@@ -76,15 +65,15 @@ class ElasticaHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $this->bulkSend([$record->formatted]);
+ $this->bulkSend([$record['formatted']]);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -97,8 +86,6 @@ class ElasticaHandler extends AbstractProcessingHandler
/**
* @return mixed[]
- *
- * @phpstan-return Options
*/
public function getOptions(): array
{
@@ -106,7 +93,7 @@ class ElasticaHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
@@ -114,7 +101,7 @@ class ElasticaHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php
index c288824a..e88375c0 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php
@@ -14,13 +14,12 @@ namespace Monolog\Handler;
use Elastic\Elasticsearch\Response\Elasticsearch;
use Throwable;
use RuntimeException;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\ElasticsearchFormatter;
use InvalidArgumentException;
use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException;
use Elasticsearch\Client;
-use Monolog\LogRecord;
use Elastic\Elasticsearch\Exception\InvalidArgumentException as ElasticInvalidArgumentException;
use Elastic\Elasticsearch\Client as Client8;
@@ -44,26 +43,18 @@ use Elastic\Elasticsearch\Client as Client8;
* $log->pushHandler($handler);
*
* @author Avtandil Kikabidze
- * @phpstan-type Options array{
- * index: string,
- * type: string,
- * ignore_error: bool
- * }
- * @phpstan-type InputOptions array{
- * index?: string,
- * type?: string,
- * ignore_error?: bool
- * }
*/
class ElasticsearchHandler extends AbstractProcessingHandler
{
- protected Client|Client8 $client;
+ /**
+ * @var Client|Client8
+ */
+ protected $client;
/**
* @var mixed[] Handler config options
- * @phpstan-var Options
*/
- protected array $options;
+ protected $options = [];
/**
* @var bool
@@ -73,11 +64,13 @@ class ElasticsearchHandler extends AbstractProcessingHandler
/**
* @param Client|Client8 $client Elasticsearch Client object
* @param mixed[] $options Handler configuration
- *
- * @phpstan-param InputOptions $options
*/
- public function __construct(Client|Client8 $client, array $options = [], int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct($client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
{
+ if (!$client instanceof Client && !$client instanceof Client8) {
+ throw new \TypeError('Elasticsearch\Client or Elastic\Elasticsearch\Client instance required');
+ }
+
parent::__construct($level, $bubble);
$this->client = $client;
$this->options = array_merge(
@@ -99,15 +92,15 @@ class ElasticsearchHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $this->bulkSend([$record->formatted]);
+ $this->bulkSend([$record['formatted']]);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -122,8 +115,6 @@ class ElasticsearchHandler extends AbstractProcessingHandler
* Getter options
*
* @return mixed[]
- *
- * @phpstan-return Options
*/
public function getOptions(): array
{
@@ -131,7 +122,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
@@ -139,7 +130,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
@@ -150,7 +141,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler
/**
* Use Elasticsearch bulk API to send list of documents
*
- * @param array> $records Records + _index/_type keys
+ * @param array[] $records Records + _index/_type keys
* @throws \RuntimeException
*/
protected function bulkSend(array $records): void
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php
index 477d7e45..f2e22036 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php
@@ -13,9 +13,8 @@ namespace Monolog\Handler;
use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* Stores to PHP error_log() handler.
@@ -27,14 +26,16 @@ class ErrorLogHandler extends AbstractProcessingHandler
public const OPERATING_SYSTEM = 0;
public const SAPI = 4;
- protected int $messageType;
- protected bool $expandNewlines;
+ /** @var int */
+ protected $messageType;
+ /** @var bool */
+ protected $expandNewlines;
/**
* @param int $messageType Says where the error should go.
* @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
*/
- public function __construct(int $messageType = self::OPERATING_SYSTEM, int|string|Level $level = Level::Debug, bool $bubble = true, bool $expandNewlines = false)
+ public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, bool $bubble = true, bool $expandNewlines = false)
{
parent::__construct($level, $bubble);
@@ -60,7 +61,7 @@ class ErrorLogHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
@@ -68,20 +69,19 @@ class ErrorLogHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
if (!$this->expandNewlines) {
- error_log((string) $record->formatted, $this->messageType);
+ error_log((string) $record['formatted'], $this->messageType);
return;
}
- $lines = preg_split('{[\r\n]+}', (string) $record->formatted);
+ $lines = preg_split('{[\r\n]+}', (string) $record['formatted']);
if ($lines === false) {
$pcreErrorCode = preg_last_error();
-
throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / '. Utils::pcreLastErrorMessage($pcreErrorCode));
}
foreach ($lines as $line) {
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php
index 1776eb51..d4e234ce 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php
@@ -12,7 +12,6 @@
namespace Monolog\Handler;
use Throwable;
-use Monolog\LogRecord;
/**
* Forwards records to at most one handler
@@ -20,15 +19,18 @@ use Monolog\LogRecord;
* If a handler fails, the exception is suppressed and the record is forwarded to the next handler.
*
* As soon as one handler handles a record successfully, the handling stops there.
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class FallbackGroupHandler extends GroupHandler
{
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
+ /** @var Record $record */
$record = $this->processRecord($record);
}
foreach ($this->handlers as $handler) {
@@ -44,15 +46,16 @@ class FallbackGroupHandler extends GroupHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
$processed = [];
foreach ($records as $record) {
$processed[] = $this->processRecord($record);
}
+ /** @var Record[] $records */
$records = $processed;
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php
index 00381ab4..718f17ef 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php
@@ -11,13 +11,10 @@
namespace Monolog\Handler;
-use Closure;
-use Monolog\Level;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel;
-use Monolog\LogRecord;
/**
* Simple handler wrapper that filters records based on a list of levels
@@ -26,99 +23,110 @@ use Monolog\LogRecord;
*
* @author Hennadiy Verkh
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
use ProcessableHandlerTrait;
/**
- * Handler or factory Closure($record, $this)
+ * Handler or factory callable($record, $this)
*
- * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface
+ * @var callable|HandlerInterface
+ * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
*/
- protected Closure|HandlerInterface $handler;
+ protected $handler;
/**
* Minimum level for logs that are passed to handler
*
- * @var bool[] Map of Level value => true
- * @phpstan-var array, true>
+ * @var int[]
+ * @phpstan-var array
*/
- protected array $acceptedLevels;
+ protected $acceptedLevels;
/**
* Whether the messages that are handled can bubble up the stack or not
+ *
+ * @var bool
*/
- protected bool $bubble;
+ protected $bubble;
/**
- * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler
+ * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler
*
- * @param Closure|HandlerInterface $handler Handler or factory Closure($record|null, $filterHandler).
- * @param int|string|Level|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
- * @param int|string|Level|LogLevel::* $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler).
+ * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
+ * @param int|string $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*
- * @phpstan-param value-of|value-of|Level|LogLevel::*|array|value-of|Level|LogLevel::*> $minLevelOrList
- * @phpstan-param value-of|value-of|Level|LogLevel::* $maxLevel
+ * @phpstan-param Level|LevelName|LogLevel::*|array $minLevelOrList
+ * @phpstan-param Level|LevelName|LogLevel::* $maxLevel
*/
- public function __construct(Closure|HandlerInterface $handler, int|string|Level|array $minLevelOrList = Level::Debug, int|string|Level $maxLevel = Level::Emergency, bool $bubble = true)
+ public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true)
{
$this->handler = $handler;
$this->bubble = $bubble;
$this->setAcceptedLevels($minLevelOrList, $maxLevel);
+
+ if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
+ throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
+ }
}
/**
- * @phpstan-return list List of levels
+ * @phpstan-return array
*/
public function getAcceptedLevels(): array
{
- return array_map(fn (int $level) => Level::from($level), array_keys($this->acceptedLevels));
+ return array_flip($this->acceptedLevels);
}
/**
- * @param int|string|Level|LogLevel::*|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided
- * @param int|string|Level|LogLevel::* $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array
+ * @param int|string|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided
+ * @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array
*
- * @phpstan-param value-of|value-of|Level|LogLevel::*|array|value-of|Level|LogLevel::*> $minLevelOrList
- * @phpstan-param value-of|value-of|Level|LogLevel::* $maxLevel
+ * @phpstan-param Level|LevelName|LogLevel::*|array $minLevelOrList
+ * @phpstan-param Level|LevelName|LogLevel::* $maxLevel
*/
- public function setAcceptedLevels(int|string|Level|array $minLevelOrList = Level::Debug, int|string|Level $maxLevel = Level::Emergency): self
+ public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY): self
{
if (is_array($minLevelOrList)) {
- $acceptedLevels = array_map(Logger::toMonologLevel(...), $minLevelOrList);
+ $acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList);
} else {
$minLevelOrList = Logger::toMonologLevel($minLevelOrList);
$maxLevel = Logger::toMonologLevel($maxLevel);
- $acceptedLevels = array_values(array_filter(Level::cases(), fn (Level $level) => $level->value >= $minLevelOrList->value && $level->value <= $maxLevel->value));
- }
- $this->acceptedLevels = [];
- foreach ($acceptedLevels as $level) {
- $this->acceptedLevels[$level->value] = true;
+ $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) {
+ return $level >= $minLevelOrList && $level <= $maxLevel;
+ }));
}
+ $this->acceptedLevels = array_flip($acceptedLevels);
return $this;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function isHandling(LogRecord $record): bool
+ public function isHandling(array $record): bool
{
- return isset($this->acceptedLevels[$record->level->value]);
+ return isset($this->acceptedLevels[$record['level']]);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
}
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
+ /** @var Record $record */
$record = $this->processRecord($record);
}
@@ -128,7 +136,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
@@ -147,23 +155,26 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
/**
* Return the nested handler
*
- * If the handler was provided as a factory, this will trigger the handler's instantiation.
+ * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
+ *
+ * @return HandlerInterface
+ *
+ * @phpstan-param Record $record
*/
- public function getHandler(LogRecord $record = null): HandlerInterface
+ public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
- $handler = ($this->handler)($record, $this);
- if (!$handler instanceof HandlerInterface) {
- throw new \RuntimeException("The factory Closure should return a HandlerInterface");
+ $this->handler = ($this->handler)($record, $this);
+ if (!$this->handler instanceof HandlerInterface) {
+ throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
- $this->handler = $handler;
}
return $this->handler;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -178,7 +189,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function getFormatter(): FormatterInterface
{
@@ -190,7 +201,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
}
- public function reset(): void
+ public function reset()
{
$this->resetProcessors();
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
index e8a1b0b0..0aa5607b 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php
@@ -11,17 +11,19 @@
namespace Monolog\Handler\FingersCrossed;
-use Monolog\LogRecord;
-
/**
* Interface for activation strategies for the FingersCrossedHandler.
*
* @author Johannes M. Schmitt
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
interface ActivationStrategyInterface
{
/**
* Returns whether the given record activates the handler.
+ *
+ * @phpstan-param Record $record
*/
- public function isHandlerActivated(LogRecord $record): bool;
+ public function isHandlerActivated(array $record): bool;
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php
index 383e19af..7b9abb58 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php
@@ -11,10 +11,8 @@
namespace Monolog\Handler\FingersCrossed;
-use Monolog\Level;
use Monolog\Logger;
use Psr\Log\LogLevel;
-use Monolog\LogRecord;
/**
* Channel and Error level based monolog activation strategy. Allows to trigger activation
@@ -25,45 +23,55 @@ use Monolog\LogRecord;
*
*
* $activationStrategy = new ChannelLevelActivationStrategy(
- * Level::Critical,
+ * Logger::CRITICAL,
* array(
- * 'request' => Level::Alert,
- * 'sensitive' => Level::Error,
+ * 'request' => Logger::ALERT,
+ * 'sensitive' => Logger::ERROR,
* )
* );
* $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy);
*
*
* @author Mike Meessen
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class ChannelLevelActivationStrategy implements ActivationStrategyInterface
{
- private Level $defaultActionLevel;
+ /**
+ * @var Level
+ */
+ private $defaultActionLevel;
/**
* @var array
*/
- private array $channelToActionLevel;
+ private $channelToActionLevel;
/**
- * @param int|string|Level|LogLevel::* $defaultActionLevel The default action level to be used if the record's category doesn't match any
- * @param array $channelToActionLevel An array that maps channel names to action levels.
+ * @param int|string $defaultActionLevel The default action level to be used if the record's category doesn't match any
+ * @param array $channelToActionLevel An array that maps channel names to action levels.
*
- * @phpstan-param value-of|value-of|Level|LogLevel::* $defaultActionLevel
- * @phpstan-param array|value-of|Level|LogLevel::*> $channelToActionLevel
+ * @phpstan-param array $channelToActionLevel
+ * @phpstan-param Level|LevelName|LogLevel::* $defaultActionLevel
*/
- public function __construct(int|string|Level $defaultActionLevel, array $channelToActionLevel = [])
+ public function __construct($defaultActionLevel, array $channelToActionLevel = [])
{
$this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel);
- $this->channelToActionLevel = array_map(Logger::toMonologLevel(...), $channelToActionLevel);
+ $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel);
}
- public function isHandlerActivated(LogRecord $record): bool
+ /**
+ * @phpstan-param Record $record
+ */
+ public function isHandlerActivated(array $record): bool
{
- if (isset($this->channelToActionLevel[$record->channel])) {
- return $record->level->value >= $this->channelToActionLevel[$record->channel]->value;
+ if (isset($this->channelToActionLevel[$record['channel']])) {
+ return $record['level'] >= $this->channelToActionLevel[$record['channel']];
}
- return $record->level->value >= $this->defaultActionLevel->value;
+ return $record['level'] >= $this->defaultActionLevel;
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php
index c3ca2967..5ec88eab 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php
@@ -11,8 +11,6 @@
namespace Monolog\Handler\FingersCrossed;
-use Monolog\Level;
-use Monolog\LogRecord;
use Monolog\Logger;
use Psr\Log\LogLevel;
@@ -20,23 +18,29 @@ use Psr\Log\LogLevel;
* Error level based activation strategy.
*
* @author Johannes M. Schmitt
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class ErrorLevelActivationStrategy implements ActivationStrategyInterface
{
- private Level $actionLevel;
+ /**
+ * @var Level
+ */
+ private $actionLevel;
/**
- * @param int|string|Level $actionLevel Level or name or value
+ * @param int|string $actionLevel Level or name or value
*
- * @phpstan-param value-of|value-of|Level|LogLevel::* $actionLevel
+ * @phpstan-param Level|LevelName|LogLevel::* $actionLevel
*/
- public function __construct(int|string|Level $actionLevel)
+ public function __construct($actionLevel)
{
$this->actionLevel = Logger::toMonologLevel($actionLevel);
}
- public function isHandlerActivated(LogRecord $record): bool
+ public function isHandlerActivated(array $record): bool
{
- return $record->level->value >= $this->actionLevel->value;
+ return $record['level'] >= $this->actionLevel;
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php
index ce2a3a8e..0627b445 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php
@@ -11,15 +11,12 @@
namespace Monolog\Handler;
-use Closure;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
-use Monolog\Level;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel;
-use Monolog\LogRecord;
/**
* Buffers all records until a certain level is reached
@@ -36,50 +33,55 @@ use Monolog\LogRecord;
* Monolog\Handler\FingersCrossed\ namespace.
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
use ProcessableHandlerTrait;
/**
- * Handler or factory Closure($record, $this)
- *
- * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface
+ * @var callable|HandlerInterface
+ * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
*/
- protected Closure|HandlerInterface $handler;
-
- protected ActivationStrategyInterface $activationStrategy;
-
- protected bool $buffering = true;
-
- protected int $bufferSize;
-
- /** @var LogRecord[] */
- protected array $buffer = [];
-
- protected bool $stopBuffering;
-
- protected Level|null $passthruLevel = null;
-
- protected bool $bubble;
+ protected $handler;
+ /** @var ActivationStrategyInterface */
+ protected $activationStrategy;
+ /** @var bool */
+ protected $buffering = true;
+ /** @var int */
+ protected $bufferSize;
+ /** @var Record[] */
+ protected $buffer = [];
+ /** @var bool */
+ protected $stopBuffering;
+ /**
+ * @var ?int
+ * @phpstan-var ?Level
+ */
+ protected $passthruLevel;
+ /** @var bool */
+ protected $bubble;
/**
- * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler
+ * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler
*
- * @param Closure|HandlerInterface $handler Handler or factory Closure($record|null, $fingersCrossedHandler).
- * @param int|string|Level|LogLevel::* $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated
- * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
- * @param int|string|Level|LogLevel::*|null $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
+ * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler).
+ * @param int|string|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated
+ * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
+ * @param int|string $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
*
- * @phpstan-param value-of|value-of|Level|LogLevel::*|ActivationStrategyInterface $activationStrategy
- * @phpstan-param value-of|value-of|Level|LogLevel::* $passthruLevel
+ * @phpstan-param Level|LevelName|LogLevel::* $passthruLevel
+ * @phpstan-param Level|LevelName|LogLevel::*|ActivationStrategyInterface $activationStrategy
*/
- public function __construct(Closure|HandlerInterface $handler, int|string|Level|ActivationStrategyInterface $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, int|string|Level|null $passthruLevel = null)
+ public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null)
{
if (null === $activationStrategy) {
- $activationStrategy = new ErrorLevelActivationStrategy(Level::Warning);
+ $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING);
}
// convert simple int activationStrategy to an object
@@ -96,12 +98,16 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
if ($passthruLevel !== null) {
$this->passthruLevel = Logger::toMonologLevel($passthruLevel);
}
+
+ if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
+ throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
+ }
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function isHandling(LogRecord $record): bool
+ public function isHandling(array $record): bool
{
return true;
}
@@ -120,11 +126,12 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
+ /** @var Record $record */
$record = $this->processRecord($record);
}
@@ -144,7 +151,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function close(): void
{
@@ -153,7 +160,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
$this->getHandler()->close();
}
- public function reset(): void
+ public function reset()
{
$this->flushBuffer();
@@ -183,7 +190,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
if (null !== $this->passthruLevel) {
$level = $this->passthruLevel;
$this->buffer = array_filter($this->buffer, function ($record) use ($level) {
- return $record->level >= $level;
+ return $record['level'] >= $level;
});
if (count($this->buffer) > 0) {
$this->getHandler(end($this->buffer))->handleBatch($this->buffer);
@@ -197,23 +204,26 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
/**
* Return the nested handler
*
- * If the handler was provided as a factory, this will trigger the handler's instantiation.
+ * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
+ *
+ * @return HandlerInterface
+ *
+ * @phpstan-param Record $record
*/
- public function getHandler(LogRecord $record = null): HandlerInterface
+ public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
- $handler = ($this->handler)($record, $this);
- if (!$handler instanceof HandlerInterface) {
- throw new \RuntimeException("The factory Closure should return a HandlerInterface");
+ $this->handler = ($this->handler)($record, $this);
+ if (!$this->handler instanceof HandlerInterface) {
+ throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
- $this->handler = $handler;
}
return $this->handler;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -228,7 +238,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function getFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php
index 6b9e5103..72718de6 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php
@@ -13,12 +13,13 @@ namespace Monolog\Handler;
use Monolog\Formatter\WildfireFormatter;
use Monolog\Formatter\FormatterInterface;
-use Monolog\LogRecord;
/**
* Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
*
* @author Eric Clemmons (@ericclemmons)
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class FirePHPHandler extends AbstractProcessingHandler
{
@@ -46,15 +47,18 @@ class FirePHPHandler extends AbstractProcessingHandler
/**
* Whether or not Wildfire vendor-specific headers have been generated & sent yet
+ * @var bool
*/
- protected static bool $initialized = false;
+ protected static $initialized = false;
/**
* Shared static message index between potentially multiple handlers
+ * @var int
*/
- protected static int $messageIndex = 1;
+ protected static $messageIndex = 1;
- protected static bool $sendHeaders = true;
+ /** @var bool */
+ protected static $sendHeaders = true;
/**
* Base header creation function used by init headers & record headers
@@ -81,19 +85,21 @@ class FirePHPHandler extends AbstractProcessingHandler
* @phpstan-return non-empty-array
*
* @see createHeader()
+ *
+ * @phpstan-param FormattedRecord $record
*/
- protected function createRecordHeader(LogRecord $record): array
+ protected function createRecordHeader(array $record): array
{
// Wildfire is extensible to support multiple protocols & plugins in a single request,
// but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
return $this->createHeader(
[1, 1, 1, self::$messageIndex++],
- $record->formatted
+ $record['formatted']
);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
@@ -134,7 +140,7 @@ class FirePHPHandler extends AbstractProcessingHandler
* @see sendHeader()
* @see sendInitHeaders()
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
if (!self::$sendHeaders || !$this->isWebRequest()) {
return;
@@ -165,7 +171,7 @@ class FirePHPHandler extends AbstractProcessingHandler
*/
protected function headersAccepted(): bool
{
- if (isset($_SERVER['HTTP_USER_AGENT']) && 1 === preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) {
+ if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) {
return true;
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php
index 9f44ba71..85c95b9d 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php
@@ -13,8 +13,7 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* Sends logs to Fleep.io using Webhook integrations
@@ -23,6 +22,8 @@ use Monolog\LogRecord;
*
* @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation
* @author Ando Roots
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class FleepHookHandler extends SocketHandler
{
@@ -33,7 +34,7 @@ class FleepHookHandler extends SocketHandler
/**
* @var string Webhook token (specifies the conversation where logs are sent)
*/
- protected string $token;
+ protected $token;
/**
* Construct a new Fleep.io Handler.
@@ -41,12 +42,12 @@ class FleepHookHandler extends SocketHandler
* For instructions on how to create a new web hook in your conversations
* see https://fleep.io/integrations/webhooks/
*
- * @param string $token Webhook token
+ * @param string $token Webhook token
* @throws MissingExtensionException
*/
public function __construct(
string $token,
- $level = Level::Debug,
+ $level = Logger::DEBUG,
bool $bubble = true,
bool $persistent = false,
float $timeout = 0.0,
@@ -88,16 +89,16 @@ class FleepHookHandler extends SocketHandler
/**
* Handles a log record
*/
- public function write(LogRecord $record): void
+ public function write(array $record): void
{
parent::write($record);
$this->closeSocket();
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function generateDataStream(LogRecord $record): string
+ protected function generateDataStream(array $record): string
{
$content = $this->buildContent($record);
@@ -120,11 +121,13 @@ class FleepHookHandler extends SocketHandler
/**
* Builds the body of API call
+ *
+ * @phpstan-param FormattedRecord $record
*/
- private function buildContent(LogRecord $record): string
+ private function buildContent(array $record): string
{
$dataArray = [
- 'message' => $record->formatted,
+ 'message' => $record['formatted'],
];
return http_build_query($dataArray);
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php
index 13581548..5715d580 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php
@@ -11,11 +11,10 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\FlowdockFormatter;
use Monolog\Formatter\FormatterInterface;
-use Monolog\LogRecord;
/**
* Sends notifications through the Flowdock push API
@@ -27,17 +26,23 @@ use Monolog\LogRecord;
*
* @author Dominik Liebler
* @see https://www.flowdock.com/api/push
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
+ * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4
*/
class FlowdockHandler extends SocketHandler
{
- protected string $apiToken;
+ /**
+ * @var string
+ */
+ protected $apiToken;
/**
* @throws MissingExtensionException if OpenSSL is missing
*/
public function __construct(
string $apiToken,
- $level = Level::Debug,
+ $level = Logger::DEBUG,
bool $bubble = true,
bool $persistent = false,
float $timeout = 0.0,
@@ -63,7 +68,7 @@ class FlowdockHandler extends SocketHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -83,9 +88,9 @@ class FlowdockHandler extends SocketHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
parent::write($record);
@@ -93,9 +98,9 @@ class FlowdockHandler extends SocketHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function generateDataStream(LogRecord $record): string
+ protected function generateDataStream(array $record): string
{
$content = $this->buildContent($record);
@@ -104,10 +109,12 @@ class FlowdockHandler extends SocketHandler
/**
* Builds the body of API call
+ *
+ * @phpstan-param FormattedRecord $record
*/
- private function buildContent(LogRecord $record): string
+ private function buildContent(array $record): string
{
- return Utils::jsonEncode($record->formatted);
+ return Utils::jsonEncode($record['formatted']['flowdock']);
}
/**
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php
index 72da59e1..fc1693cd 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php
@@ -23,12 +23,15 @@ interface FormattableHandlerInterface
/**
* Sets the formatter.
*
- * @return HandlerInterface self
+ * @param FormatterInterface $formatter
+ * @return HandlerInterface self
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface;
/**
* Gets the formatter.
+ *
+ * @return FormatterInterface
*/
public function getFormatter(): FormatterInterface;
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php
index c044e078..b60bdce0 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php
@@ -21,10 +21,13 @@ use Monolog\Formatter\LineFormatter;
*/
trait FormattableHandlerTrait
{
- protected FormatterInterface|null $formatter = null;
+ /**
+ * @var ?FormatterInterface
+ */
+ protected $formatter;
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -34,11 +37,11 @@ trait FormattableHandlerTrait
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function getFormatter(): FormatterInterface
{
- if (null === $this->formatter) {
+ if (!$this->formatter) {
$this->formatter = $this->getDefaultFormatter();
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php
index ba5bb975..4ff26c4c 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php
@@ -12,10 +12,9 @@
namespace Monolog\Handler;
use Gelf\PublisherInterface;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\GelfMessageFormatter;
use Monolog\Formatter\FormatterInterface;
-use Monolog\LogRecord;
/**
* Handler to send messages to a Graylog2 (http://www.graylog2.org) server
@@ -28,12 +27,12 @@ class GelfHandler extends AbstractProcessingHandler
/**
* @var PublisherInterface the publisher object that sends the message to the server
*/
- protected PublisherInterface $publisher;
+ protected $publisher;
/**
* @param PublisherInterface $publisher a gelf publisher object
*/
- public function __construct(PublisherInterface $publisher, int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true)
{
parent::__construct($level, $bubble);
@@ -41,15 +40,15 @@ class GelfHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $this->publisher->publish($record->formatted);
+ $this->publisher->publish($record['formatted']);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php
index 7ab8bd97..3c9dc4b3 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php
@@ -13,20 +13,22 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\ResettableInterface;
-use Monolog\LogRecord;
/**
* Forwards records to multiple handlers
*
* @author Lenar Lõhmus
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface
{
use ProcessableHandlerTrait;
/** @var HandlerInterface[] */
- protected array $handlers;
- protected bool $bubble;
+ protected $handlers;
+ /** @var bool */
+ protected $bubble;
/**
* @param HandlerInterface[] $handlers Array of Handlers.
@@ -45,9 +47,9 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function isHandling(LogRecord $record): bool
+ public function isHandling(array $record): bool
{
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
@@ -59,11 +61,12 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
+ /** @var Record $record */
$record = $this->processRecord($record);
}
@@ -75,15 +78,16 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
- if (\count($this->processors) > 0) {
+ if ($this->processors) {
$processed = [];
foreach ($records as $record) {
$processed[] = $this->processRecord($record);
}
+ /** @var Record[] $records */
$records = $processed;
}
@@ -92,7 +96,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
}
}
- public function reset(): void
+ public function reset()
{
$this->resetProcessors();
@@ -113,7 +117,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php
index e89f969b..34b4935d 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php
@@ -19,7 +19,7 @@ namespace Monolog\Handler;
abstract class Handler implements HandlerInterface
{
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
@@ -29,7 +29,7 @@ abstract class Handler implements HandlerInterface
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function close(): void
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php
index 83905c32..affcc51f 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php
@@ -11,12 +11,13 @@
namespace Monolog\Handler;
-use Monolog\LogRecord;
-
/**
* Interface that all Monolog Handlers must implement
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
*/
interface HandlerInterface
{
@@ -29,9 +30,13 @@ interface HandlerInterface
* is no guarantee that handle() will not be called, and isHandling() might not be called
* for a given record.
*
- * @param LogRecord $record Partial log record having only a level initialized
+ * @param array $record Partial log record containing only a level key
+ *
+ * @return bool
+ *
+ * @phpstan-param array{level: Level} $record
*/
- public function isHandling(LogRecord $record): bool;
+ public function isHandling(array $record): bool;
/**
* Handles a record.
@@ -43,16 +48,20 @@ interface HandlerInterface
* Unless the bubbling is interrupted (by returning true), the Logger class will keep on
* calling further handlers in the stack with a given log record.
*
- * @param LogRecord $record The record to handle
- * @return bool true means that this handler handled the record, and that bubbling is not permitted.
- * false means the record was either not processed or that this handler allows bubbling.
+ * @param array $record The record to handle
+ * @return bool true means that this handler handled the record, and that bubbling is not permitted.
+ * false means the record was either not processed or that this handler allows bubbling.
+ *
+ * @phpstan-param Record $record
*/
- public function handle(LogRecord $record): bool;
+ public function handle(array $record): bool;
/**
* Handles a set of records at once.
*
- * @param array $records The records to handle
+ * @param array $records The records to handle (an array of record arrays)
+ *
+ * @phpstan-param Record[] $records
*/
public function handleBatch(array $records): void;
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php
index 541ec254..d4351b9f 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php
@@ -13,7 +13,6 @@ namespace Monolog\Handler;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
-use Monolog\LogRecord;
/**
* This simple wrapper class can be used to extend handlers functionality.
@@ -22,7 +21,7 @@ use Monolog\LogRecord;
*
* Inherit from this class and override handle() like this:
*
- * public function handle(LogRecord $record)
+ * public function handle(array $record)
* {
* if ($record meets certain conditions) {
* return false;
@@ -34,7 +33,10 @@ use Monolog\LogRecord;
*/
class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface
{
- protected HandlerInterface $handler;
+ /**
+ * @var HandlerInterface
+ */
+ protected $handler;
public function __construct(HandlerInterface $handler)
{
@@ -42,23 +44,23 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function isHandling(LogRecord $record): bool
+ public function isHandling(array $record): bool
{
return $this->handler->isHandling($record);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
return $this->handler->handle($record);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
@@ -66,7 +68,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function close(): void
{
@@ -74,7 +76,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function pushProcessor(callable $callback): HandlerInterface
{
@@ -88,7 +90,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function popProcessor(): callable
{
@@ -100,7 +102,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -114,7 +116,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function getFormatter(): FormatterInterface
{
@@ -125,7 +127,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F
throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
}
- public function reset(): void
+ public function reset()
{
if ($this->handler instanceof ResettableInterface) {
$this->handler->reset();
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php
index ee7f81f6..000ccea4 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php
@@ -11,9 +11,8 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
-use Monolog\LogRecord;
/**
* IFTTTHandler uses cURL to trigger IFTTT Maker actions
@@ -28,14 +27,16 @@ use Monolog\LogRecord;
*/
class IFTTTHandler extends AbstractProcessingHandler
{
- private string $eventName;
- private string $secretKey;
+ /** @var string */
+ private $eventName;
+ /** @var string */
+ private $secretKey;
/**
* @param string $eventName The name of the IFTTT Maker event that should be triggered
* @param string $secretKey A valid IFTTT secret key
*/
- public function __construct(string $eventName, string $secretKey, int|string|Level $level = Level::Error, bool $bubble = true)
+ public function __construct(string $eventName, string $secretKey, $level = Logger::ERROR, bool $bubble = true)
{
if (!extension_loaded('curl')) {
throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler');
@@ -48,14 +49,14 @@ class IFTTTHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function write(LogRecord $record): void
+ public function write(array $record): void
{
$postData = [
- "value1" => $record->channel,
+ "value1" => $record["channel"],
"value2" => $record["level_name"],
- "value3" => $record->message,
+ "value3" => $record["message"],
];
$postString = Utils::jsonEncode($postData);
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php
index abb2f88f..71f64a26 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php
@@ -11,8 +11,7 @@
namespace Monolog\Handler;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* Inspired on LogEntriesHandler.
@@ -22,12 +21,15 @@ use Monolog\LogRecord;
*/
class InsightOpsHandler extends SocketHandler
{
- protected string $logToken;
+ /**
+ * @var string
+ */
+ protected $logToken;
/**
- * @param string $token Log token supplied by InsightOps
- * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
- * @param bool $useSSL Whether or not SSL encryption should be used
+ * @param string $token Log token supplied by InsightOps
+ * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
+ * @param bool $useSSL Whether or not SSL encryption should be used
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
@@ -35,7 +37,7 @@ class InsightOpsHandler extends SocketHandler
string $token,
string $region = 'us',
bool $useSSL = true,
- $level = Level::Debug,
+ $level = Logger::DEBUG,
bool $bubble = true,
bool $persistent = false,
float $timeout = 0.0,
@@ -65,10 +67,10 @@ class InsightOpsHandler extends SocketHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function generateDataStream(LogRecord $record): string
+ protected function generateDataStream(array $record): string
{
- return $this->logToken . ' ' . $record->formatted;
+ return $this->logToken . ' ' . $record['formatted'];
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php
index 00259834..25fcd159 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php
@@ -11,27 +11,29 @@
namespace Monolog\Handler;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* @author Robert Kaufmann III
*/
class LogEntriesHandler extends SocketHandler
{
- protected string $logToken;
+ /**
+ * @var string
+ */
+ protected $logToken;
/**
- * @param string $token Log token supplied by LogEntries
- * @param bool $useSSL Whether or not SSL encryption should be used.
- * @param string $host Custom hostname to send the data to if needed
+ * @param string $token Log token supplied by LogEntries
+ * @param bool $useSSL Whether or not SSL encryption should be used.
+ * @param string $host Custom hostname to send the data to if needed
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
public function __construct(
string $token,
bool $useSSL = true,
- $level = Level::Debug,
+ $level = Logger::DEBUG,
bool $bubble = true,
string $host = 'data.logentries.com',
bool $persistent = false,
@@ -59,10 +61,10 @@ class LogEntriesHandler extends SocketHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function generateDataStream(LogRecord $record): string
+ protected function generateDataStream(array $record): string
{
- return $this->logToken . ' ' . $record->formatted;
+ return $this->logToken . ' ' . $record['formatted'];
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php
index 2d8e66f1..6d13db37 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php
@@ -11,12 +11,11 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogglyFormatter;
use function array_key_exists;
use CurlHandle;
-use Monolog\LogRecord;
/**
* Sends errors to Loggly.
@@ -34,21 +33,22 @@ class LogglyHandler extends AbstractProcessingHandler
/**
* Caches the curl handlers for every given endpoint.
*
- * @var CurlHandle[]
+ * @var resource[]|CurlHandle[]
*/
- protected array $curlHandlers = [];
+ protected $curlHandlers = [];
- protected string $token;
+ /** @var string */
+ protected $token;
/** @var string[] */
- protected array $tag = [];
+ protected $tag = [];
/**
* @param string $token API token supplied by Loggly
*
* @throws MissingExtensionException If the curl extension is missing
*/
- public function __construct(string $token, int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
{
if (!extension_loaded('curl')) {
throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler');
@@ -61,8 +61,12 @@ class LogglyHandler extends AbstractProcessingHandler
/**
* Loads and returns the shared curl handler for the given endpoint.
+ *
+ * @param string $endpoint
+ *
+ * @return resource|CurlHandle
*/
- protected function getCurlHandler(string $endpoint): CurlHandle
+ protected function getCurlHandler(string $endpoint)
{
if (!array_key_exists($endpoint, $this->curlHandlers)) {
$this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint);
@@ -73,8 +77,12 @@ class LogglyHandler extends AbstractProcessingHandler
/**
* Starts a fresh curl session for the given endpoint and returns its handler.
+ *
+ * @param string $endpoint
+ *
+ * @return resource|CurlHandle
*/
- private function loadCurlHandle(string $endpoint): CurlHandle
+ private function loadCurlHandle(string $endpoint)
{
$url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token);
@@ -90,13 +98,10 @@ class LogglyHandler extends AbstractProcessingHandler
/**
* @param string[]|string $tag
*/
- public function setTag(string|array $tag): self
+ public function setTag($tag): self
{
- if ('' === $tag || [] === $tag) {
- $this->tag = [];
- } else {
- $this->tag = is_array($tag) ? $tag : [$tag];
- }
+ $tag = !empty($tag) ? $tag : [];
+ $this->tag = is_array($tag) ? $tag : [$tag];
return $this;
}
@@ -104,9 +109,9 @@ class LogglyHandler extends AbstractProcessingHandler
/**
* @param string[]|string $tag
*/
- public function addTag(string|array $tag): self
+ public function addTag($tag): self
{
- if ('' !== $tag) {
+ if (!empty($tag)) {
$tag = is_array($tag) ? $tag : [$tag];
$this->tag = array_unique(array_merge($this->tag, $tag));
}
@@ -114,9 +119,9 @@ class LogglyHandler extends AbstractProcessingHandler
return $this;
}
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $this->send($record->formatted, static::ENDPOINT_SINGLE);
+ $this->send($record["formatted"], static::ENDPOINT_SINGLE);
}
public function handleBatch(array $records): void
@@ -124,10 +129,10 @@ class LogglyHandler extends AbstractProcessingHandler
$level = $this->level;
$records = array_filter($records, function ($record) use ($level) {
- return ($record->level >= $level);
+ return ($record['level'] >= $level);
});
- if (\count($records) > 0) {
+ if ($records) {
$this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH);
}
}
@@ -138,7 +143,7 @@ class LogglyHandler extends AbstractProcessingHandler
$headers = ['Content-Type: application/json'];
- if (\count($this->tag) > 0) {
+ if (!empty($this->tag)) {
$headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag);
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php
index 876b1a95..859a4690 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php
@@ -11,36 +11,44 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogmaticFormatter;
-use Monolog\LogRecord;
/**
* @author Julien Breux
*/
class LogmaticHandler extends SocketHandler
{
- private string $logToken;
-
- private string $hostname;
-
- private string $appName;
+ /**
+ * @var string
+ */
+ private $logToken;
/**
- * @param string $token Log token supplied by Logmatic.
- * @param string $hostname Host name supplied by Logmatic.
- * @param string $appName Application name supplied by Logmatic.
- * @param bool $useSSL Whether or not SSL encryption should be used.
+ * @var string
+ */
+ private $hostname;
+
+ /**
+ * @var string
+ */
+ private $appname;
+
+ /**
+ * @param string $token Log token supplied by Logmatic.
+ * @param string $hostname Host name supplied by Logmatic.
+ * @param string $appname Application name supplied by Logmatic.
+ * @param bool $useSSL Whether or not SSL encryption should be used.
*
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
*/
public function __construct(
string $token,
string $hostname = '',
- string $appName = '',
+ string $appname = '',
bool $useSSL = true,
- $level = Level::Debug,
+ $level = Logger::DEBUG,
bool $bubble = true,
bool $persistent = false,
float $timeout = 0.0,
@@ -68,29 +76,29 @@ class LogmaticHandler extends SocketHandler
$this->logToken = $token;
$this->hostname = $hostname;
- $this->appName = $appName;
+ $this->appname = $appname;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function generateDataStream(LogRecord $record): string
+ protected function generateDataStream(array $record): string
{
- return $this->logToken . ' ' . $record->formatted;
+ return $this->logToken . ' ' . $record['formatted'];
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
$formatter = new LogmaticFormatter();
- if ($this->hostname !== '') {
+ if (!empty($this->hostname)) {
$formatter->setHostname($this->hostname);
}
- if ($this->appName !== '') {
- $formatter->setAppName($this->appName);
+ if (!empty($this->appname)) {
+ $formatter->setAppname($this->appname);
}
return $formatter;
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php
index b6c82277..97f34320 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php
@@ -13,32 +13,33 @@ namespace Monolog\Handler;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\HtmlFormatter;
-use Monolog\LogRecord;
/**
* Base class for all mail handlers
*
* @author Gyula Sallai
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
abstract class MailHandler extends AbstractProcessingHandler
{
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function handleBatch(array $records): void
{
$messages = [];
foreach ($records as $record) {
- if ($record->level->isLowerThan($this->level)) {
+ if ($record['level'] < $this->level) {
continue;
}
-
+ /** @var Record $message */
$message = $this->processRecord($record);
$messages[] = $message;
}
- if (\count($messages) > 0) {
+ if (!empty($messages)) {
$this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
}
}
@@ -49,26 +50,27 @@ abstract class MailHandler extends AbstractProcessingHandler
* @param string $content formatted email body to be sent
* @param array $records the array of log records that formed this content
*
- * @phpstan-param non-empty-array $records
+ * @phpstan-param Record[] $records
*/
abstract protected function send(string $content, array $records): void;
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- $this->send((string) $record->formatted, [$record]);
+ $this->send((string) $record['formatted'], [$record]);
}
/**
- * @phpstan-param non-empty-array $records
+ * @phpstan-param non-empty-array $records
+ * @phpstan-return Record
*/
- protected function getHighestRecord(array $records): LogRecord
+ protected function getHighestRecord(array $records): array
{
$highestRecord = null;
foreach ($records as $record) {
- if ($highestRecord === null || $record->level->isHigherThan($highestRecord->level)) {
+ if ($highestRecord === null || $highestRecord['level'] < $record['level']) {
$highestRecord = $record;
}
}
@@ -83,6 +85,8 @@ abstract class MailHandler extends AbstractProcessingHandler
/**
* Gets the default formatter.
+ *
+ * @return FormatterInterface
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php
index 0f923bc5..3003500e 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php
@@ -11,7 +11,7 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Swift;
use Swift_Message;
@@ -22,20 +22,22 @@ use Swift_Message;
*/
class MandrillHandler extends MailHandler
{
- protected Swift_Message $message;
- protected string $apiKey;
+ /** @var Swift_Message */
+ protected $message;
+ /** @var string */
+ protected $apiKey;
/**
- * @phpstan-param (Swift_Message|callable(): Swift_Message) $message
+ * @psalm-param Swift_Message|callable(): Swift_Message $message
*
* @param string $apiKey A valid Mandrill API key
* @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
*/
- public function __construct(string $apiKey, callable|Swift_Message $message, int|string|Level $level = Level::Error, bool $bubble = true)
+ public function __construct(string $apiKey, $message, $level = Logger::ERROR, bool $bubble = true)
{
parent::__construct($level, $bubble);
- if (!$message instanceof Swift_Message) {
+ if (!$message instanceof Swift_Message && is_callable($message)) {
$message = $message();
}
if (!$message instanceof Swift_Message) {
@@ -46,7 +48,7 @@ class MandrillHandler extends MailHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function send(string $content, array $records): void
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php
index 33ab68c6..30630911 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php
@@ -14,10 +14,9 @@ namespace Monolog\Handler;
use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use MongoDB\Client;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\MongoDBFormatter;
-use Monolog\LogRecord;
/**
* Logs to a MongoDB database.
@@ -34,11 +33,12 @@ use Monolog\LogRecord;
*/
class MongoDBHandler extends AbstractProcessingHandler
{
- private \MongoDB\Collection $collection;
-
- private Client|Manager $manager;
-
- private string|null $namespace = null;
+ /** @var \MongoDB\Collection */
+ private $collection;
+ /** @var Client|Manager */
+ private $manager;
+ /** @var string */
+ private $namespace;
/**
* Constructor.
@@ -47,8 +47,12 @@ class MongoDBHandler extends AbstractProcessingHandler
* @param string $database Database name
* @param string $collection Collection name
*/
- public function __construct(Client|Manager $mongodb, string $database, string $collection, int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true)
{
+ if (!($mongodb instanceof Client || $mongodb instanceof Manager)) {
+ throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required');
+ }
+
if ($mongodb instanceof Client) {
$this->collection = $mongodb->selectCollection($database, $collection);
} else {
@@ -59,21 +63,21 @@ class MongoDBHandler extends AbstractProcessingHandler
parent::__construct($level, $bubble);
}
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
if (isset($this->collection)) {
- $this->collection->insertOne($record->formatted);
+ $this->collection->insertOne($record['formatted']);
}
if (isset($this->manager, $this->namespace)) {
$bulk = new BulkWrite;
- $bulk->insert($record->formatted);
+ $bulk->insert($record["formatted"]);
$this->manager->executeBulkWrite($this->namespace, $bulk);
}
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php
index d4c9d801..0c0a3bdb 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php
@@ -11,7 +11,7 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
/**
@@ -26,39 +26,43 @@ class NativeMailerHandler extends MailHandler
* The email addresses to which the message will be sent
* @var string[]
*/
- protected array $to;
+ protected $to;
/**
* The subject of the email
+ * @var string
*/
- protected string $subject;
+ protected $subject;
/**
* Optional headers for the message
* @var string[]
*/
- protected array $headers = [];
+ protected $headers = [];
/**
* Optional parameters for the message
* @var string[]
*/
- protected array $parameters = [];
+ protected $parameters = [];
/**
* The wordwrap length for the message
+ * @var int
*/
- protected int $maxColumnWidth;
+ protected $maxColumnWidth;
/**
* The Content-type for the message
+ * @var string|null
*/
- protected string|null $contentType = null;
+ protected $contentType;
/**
* The encoding for the message
+ * @var string
*/
- protected string $encoding = 'utf-8';
+ protected $encoding = 'utf-8';
/**
* @param string|string[] $to The receiver of the mail
@@ -66,7 +70,7 @@ class NativeMailerHandler extends MailHandler
* @param string $from The sender of the mail
* @param int $maxColumnWidth The maximum column width that the message lines will have
*/
- public function __construct(string|array $to, string $subject, string $from, int|string|Level $level = Level::Error, bool $bubble = true, int $maxColumnWidth = 70)
+ public function __construct($to, string $subject, string $from, $level = Logger::ERROR, bool $bubble = true, int $maxColumnWidth = 70)
{
parent::__construct($level, $bubble);
$this->to = (array) $to;
@@ -105,11 +109,11 @@ class NativeMailerHandler extends MailHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function send(string $content, array $records): void
{
- $contentType = $this->getContentType() ?? ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
+ $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
if ($contentType !== 'text/html') {
$content = wordwrap($content, $this->maxColumnWidth);
@@ -121,8 +125,11 @@ class NativeMailerHandler extends MailHandler
$headers .= 'MIME-Version: 1.0' . "\r\n";
}
- $subjectFormatter = new LineFormatter($this->subject);
- $subject = $subjectFormatter->format($this->getHighestRecord($records));
+ $subject = $this->subject;
+ if ($records) {
+ $subjectFormatter = new LineFormatter($this->subject);
+ $subject = $subjectFormatter->format($this->getHighestRecord($records));
+ }
$parameters = implode(' ', $this->parameters);
foreach ($this->to as $to) {
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php
index b8cb3785..114d749e 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php
@@ -11,17 +11,16 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
-use Monolog\LogRecord;
/**
* Class to record a log on a NewRelic application.
* Enabling New Relic High Security mode may prevent capture of useful information.
*
- * This handler requires a NormalizerFormatter to function and expects an array in $record->formatted
+ * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
*
* @see https://docs.newrelic.com/docs/agents/php-agent
* @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
@@ -29,58 +28,75 @@ use Monolog\LogRecord;
class NewRelicHandler extends AbstractProcessingHandler
{
/**
- * @inheritDoc
+ * Name of the New Relic application that will receive logs from this handler.
+ *
+ * @var ?string
+ */
+ protected $appName;
+
+ /**
+ * Name of the current transaction
+ *
+ * @var ?string
+ */
+ protected $transactionName;
+
+ /**
+ * Some context and extra data is passed into the handler as arrays of values. Do we send them as is
+ * (useful if we are using the API), or explode them for display on the NewRelic RPM website?
+ *
+ * @var bool
+ */
+ protected $explodeArrays;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param string|null $appName
+ * @param bool $explodeArrays
+ * @param string|null $transactionName
*/
public function __construct(
- int|string|Level $level = Level::Error,
+ $level = Logger::ERROR,
bool $bubble = true,
-
- /**
- * Name of the New Relic application that will receive logs from this handler.
- */
- protected string|null $appName = null,
-
- /**
- * Some context and extra data is passed into the handler as arrays of values. Do we send them as is
- * (useful if we are using the API), or explode them for display on the NewRelic RPM website?
- */
- protected bool $explodeArrays = false,
-
- /**
- * Name of the current transaction
- */
- protected string|null $transactionName = null
+ ?string $appName = null,
+ bool $explodeArrays = false,
+ ?string $transactionName = null
) {
parent::__construct($level, $bubble);
+
+ $this->appName = $appName;
+ $this->explodeArrays = $explodeArrays;
+ $this->transactionName = $transactionName;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
if (!$this->isNewRelicEnabled()) {
throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
}
- if (null !== ($appName = $this->getAppName($record->context))) {
+ if ($appName = $this->getAppName($record['context'])) {
$this->setNewRelicAppName($appName);
}
- if (null !== ($transactionName = $this->getTransactionName($record->context))) {
+ if ($transactionName = $this->getTransactionName($record['context'])) {
$this->setNewRelicTransactionName($transactionName);
- unset($record->formatted['context']['transaction_name']);
+ unset($record['formatted']['context']['transaction_name']);
}
- if (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) {
- newrelic_notice_error($record->message, $record->context['exception']);
- unset($record->formatted['context']['exception']);
+ if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
+ newrelic_notice_error($record['message'], $record['context']['exception']);
+ unset($record['formatted']['context']['exception']);
} else {
- newrelic_notice_error($record->message);
+ newrelic_notice_error($record['message']);
}
- if (isset($record->formatted['context']) && is_array($record->formatted['context'])) {
- foreach ($record->formatted['context'] as $key => $parameter) {
+ if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) {
+ foreach ($record['formatted']['context'] as $key => $parameter) {
if (is_array($parameter) && $this->explodeArrays) {
foreach ($parameter as $paramKey => $paramValue) {
$this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue);
@@ -91,8 +107,8 @@ class NewRelicHandler extends AbstractProcessingHandler
}
}
- if (isset($record->formatted['extra']) && is_array($record->formatted['extra'])) {
- foreach ($record->formatted['extra'] as $key => $parameter) {
+ if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) {
+ foreach ($record['formatted']['extra'] as $key => $parameter) {
if (is_array($parameter) && $this->explodeArrays) {
foreach ($parameter as $paramKey => $paramValue) {
$this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue);
@@ -106,6 +122,8 @@ class NewRelicHandler extends AbstractProcessingHandler
/**
* Checks whether the NewRelic extension is enabled in the system.
+ *
+ * @return bool
*/
protected function isNewRelicEnabled(): bool
{
@@ -159,7 +177,8 @@ class NewRelicHandler extends AbstractProcessingHandler
}
/**
- * @param mixed $value
+ * @param string $key
+ * @param mixed $value
*/
protected function setNewRelicParameter(string $key, $value): void
{
@@ -171,7 +190,7 @@ class NewRelicHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php
index d9fea180..1ddf0beb 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php
@@ -11,8 +11,6 @@
namespace Monolog\Handler;
-use Monolog\LogRecord;
-
/**
* No-op
*
@@ -25,17 +23,17 @@ use Monolog\LogRecord;
class NoopHandler extends Handler
{
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function isHandling(LogRecord $record): bool
+ public function isHandling(array $record): bool
{
return true;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
return false;
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php
index 1aa84e4f..e75ee0c6 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php
@@ -11,10 +11,8 @@
namespace Monolog\Handler;
-use Monolog\Level;
-use Psr\Log\LogLevel;
use Monolog\Logger;
-use Monolog\LogRecord;
+use Psr\Log\LogLevel;
/**
* Blackhole
@@ -23,34 +21,40 @@ use Monolog\LogRecord;
* to put on top of an existing stack to override it temporarily.
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class NullHandler extends Handler
{
- private Level $level;
+ /**
+ * @var int
+ */
+ private $level;
/**
- * @param string|int|Level $level The minimum logging level at which this handler will be triggered
+ * @param string|int $level The minimum logging level at which this handler will be triggered
*
- * @phpstan-param value-of|value-of|Level|LogLevel::* $level
+ * @phpstan-param Level|LevelName|LogLevel::* $level
*/
- public function __construct(string|int|Level $level = Level::Debug)
+ public function __construct($level = Logger::DEBUG)
{
$this->level = Logger::toMonologLevel($level);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function isHandling(LogRecord $record): bool
+ public function isHandling(array $record): bool
{
- return $record->level->value >= $this->level->value;
+ return $record['level'] >= $this->level;
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
- return $record->level->value >= $this->level->value;
+ return $record['level'] >= $this->level;
}
}
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php
index a72b7a11..22068c9a 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php
@@ -11,9 +11,8 @@
namespace Monolog\Handler;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
-use Monolog\LogRecord;
/**
* Handler to only pass log messages when a certain threshold of number of messages is reached.
@@ -28,7 +27,7 @@ use Monolog\LogRecord;
* $handler = new SomeHandler(...)
*
* // Pass all warnings to the handler when more than 10 & all error messages when more then 5
- * $overflow = new OverflowHandler($handler, [Level::Warning->value => 10, Level::Error->value => 5]);
+ * $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]);
*
* $log->pushHandler($overflow);
*```
@@ -37,25 +36,36 @@ use Monolog\LogRecord;
*/
class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface
{
- private HandlerInterface $handler;
+ /** @var HandlerInterface */
+ private $handler;
- /** @var array */
- private array $thresholdMap = [];
+ /** @var int[] */
+ private $thresholdMap = [
+ Logger::DEBUG => 0,
+ Logger::INFO => 0,
+ Logger::NOTICE => 0,
+ Logger::WARNING => 0,
+ Logger::ERROR => 0,
+ Logger::CRITICAL => 0,
+ Logger::ALERT => 0,
+ Logger::EMERGENCY => 0,
+ ];
/**
* Buffer of all messages passed to the handler before the threshold was reached
*
* @var mixed[][]
*/
- private array $buffer = [];
+ private $buffer = [];
/**
- * @param array $thresholdMap Dictionary of log level value => threshold
+ * @param HandlerInterface $handler
+ * @param int[] $thresholdMap Dictionary of logger level => threshold
*/
public function __construct(
HandlerInterface $handler,
array $thresholdMap = [],
- $level = Level::Debug,
+ $level = Logger::DEBUG,
bool $bubble = true
) {
$this->handler = $handler;
@@ -75,15 +85,15 @@ class OverflowHandler extends AbstractHandler implements FormattableHandlerInter
* Unless the bubbling is interrupted (by returning true), the Logger class will keep on
* calling further handlers in the stack with a given log record.
*
- * @inheritDoc
+ * {@inheritDoc}
*/
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
- if ($record->level->isLowerThan($this->level)) {
+ if ($record['level'] < $this->level) {
return false;
}
- $level = $record->level->value;
+ $level = $record['level'];
if (!isset($this->thresholdMap[$level])) {
$this->thresholdMap[$level] = 0;
@@ -112,7 +122,7 @@ class OverflowHandler extends AbstractHandler implements FormattableHandlerInter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
@@ -126,7 +136,7 @@ class OverflowHandler extends AbstractHandler implements FormattableHandlerInter
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function getFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php
index 8aa78e4c..23a1d117 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php
@@ -13,13 +13,11 @@ namespace Monolog\Handler;
use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
-use Monolog\Level;
+use Monolog\Logger;
use Monolog\Utils;
use PhpConsole\Connector;
use PhpConsole\Handler as VendorPhpConsoleHandler;
use PhpConsole\Helper;
-use Monolog\LogRecord;
-use PhpConsole\Storage;
/**
* Monolog handler for Google Chrome extension "PHP Console"
@@ -39,59 +37,14 @@ use PhpConsole\Storage;
* PC::debug($_SERVER); // PHP Console debugger for any type of vars
*
* @author Sergey Barbushin https://www.linkedin.com/in/barbushin
- * @phpstan-type Options array{
- * enabled: bool,
- * classesPartialsTraceIgnore: string[],
- * debugTagsKeysInContext: array,
- * useOwnErrorsHandler: bool,
- * useOwnExceptionsHandler: bool,
- * sourcesBasePath: string|null,
- * registerHelper: bool,
- * serverEncoding: string|null,
- * headersLimit: int|null,
- * password: string|null,
- * enableSslOnlyMode: bool,
- * ipMasks: string[],
- * enableEvalListener: bool,
- * dumperDetectCallbacks: bool,
- * dumperLevelLimit: int,
- * dumperItemsCountLimit: int,
- * dumperItemSizeLimit: int,
- * dumperDumpSizeLimit: int,
- * detectDumpTraceAndSource: bool,
- * dataStorage: Storage|null
- * }
- * @phpstan-type InputOptions array{
- * enabled?: bool,
- * classesPartialsTraceIgnore?: string[],
- * debugTagsKeysInContext?: array,
- * useOwnErrorsHandler?: bool,
- * useOwnExceptionsHandler?: bool,
- * sourcesBasePath?: string|null,
- * registerHelper?: bool,
- * serverEncoding?: string|null,
- * headersLimit?: int|null,
- * password?: string|null,
- * enableSslOnlyMode?: bool,
- * ipMasks?: string[],
- * enableEvalListener?: bool,
- * dumperDetectCallbacks?: bool,
- * dumperLevelLimit?: int,
- * dumperItemsCountLimit?: int,
- * dumperItemSizeLimit?: int,
- * dumperDumpSizeLimit?: int,
- * detectDumpTraceAndSource?: bool,
- * dataStorage?: Storage|null
- * }
*
+ * @phpstan-import-type Record from \Monolog\Logger
* @deprecated Since 2.8.0 and 3.2.0, PHPConsole is abandoned and thus we will drop this handler in Monolog 4
*/
class PHPConsoleHandler extends AbstractProcessingHandler
{
- /**
- * @phpstan-var Options
- */
- private array $options = [
+ /** @var array */
+ private $options = [
'enabled' => true, // bool Is PHP Console server enabled
'classesPartialsTraceIgnore' => ['Monolog\\'], // array Hide calls of classes started with...
'debugTagsKeysInContext' => [0, 'tag'], // bool Is PHP Console server enabled
@@ -114,15 +67,15 @@ class PHPConsoleHandler extends AbstractProcessingHandler
'dataStorage' => null, // \PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ)
];
- private Connector $connector;
+ /** @var Connector */
+ private $connector;
/**
* @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
* @param Connector|null $connector Instance of \PhpConsole\Connector class (optional)
* @throws \RuntimeException
- * @phpstan-param InputOptions $options
*/
- public function __construct(array $options = [], ?Connector $connector = null, int|string|Level $level = Level::Debug, bool $bubble = true)
+ public function __construct(array $options = [], ?Connector $connector = null, $level = Logger::DEBUG, bool $bubble = true)
{
if (!class_exists('PhpConsole\Connector')) {
throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
@@ -133,16 +86,14 @@ class PHPConsoleHandler extends AbstractProcessingHandler
}
/**
- * @param array $options
- * @return array
+ * @param array $options
*
- * @phpstan-param InputOptions $options
- * @phpstan-return Options
+ * @return array
*/
private function initOptions(array $options): array
{
$wrongOptions = array_diff(array_keys($options), array_keys($this->options));
- if (\count($wrongOptions) > 0) {
+ if ($wrongOptions) {
throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions));
}
@@ -151,8 +102,8 @@ class PHPConsoleHandler extends AbstractProcessingHandler
private function initConnector(?Connector $connector = null): Connector
{
- if (null === $connector) {
- if ($this->options['dataStorage'] instanceof Storage) {
+ if (!$connector) {
+ if ($this->options['dataStorage']) {
Connector::setPostponeStorage($this->options['dataStorage']);
}
$connector = Connector::getInstance();
@@ -169,22 +120,22 @@ class PHPConsoleHandler extends AbstractProcessingHandler
$handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
$handler->start();
}
- if (null !== $this->options['sourcesBasePath']) {
+ if ($this->options['sourcesBasePath']) {
$connector->setSourcesBasePath($this->options['sourcesBasePath']);
}
- if (null !== $this->options['serverEncoding']) {
+ if ($this->options['serverEncoding']) {
$connector->setServerEncoding($this->options['serverEncoding']);
}
- if (null !== $this->options['password']) {
+ if ($this->options['password']) {
$connector->setPassword($this->options['password']);
}
if ($this->options['enableSslOnlyMode']) {
$connector->enableSslOnlyMode();
}
- if (\count($this->options['ipMasks']) > 0) {
+ if ($this->options['ipMasks']) {
$connector->setAllowedIpMasks($this->options['ipMasks']);
}
- if (null !== $this->options['headersLimit'] && $this->options['headersLimit'] > 0) {
+ if ($this->options['headersLimit']) {
$connector->setHeadersLimit($this->options['headersLimit']);
}
if ($this->options['detectDumpTraceAndSource']) {
@@ -217,7 +168,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
return $this->options;
}
- public function handle(LogRecord $record): bool
+ public function handle(array $record): bool
{
if ($this->options['enabled'] && $this->connector->isActiveClient()) {
return parent::handle($record);
@@ -229,39 +180,48 @@ class PHPConsoleHandler extends AbstractProcessingHandler
/**
* Writes the record down to the log of the implementing handler
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
- if ($record->level->isLowerThan(Level::Notice)) {
+ if ($record['level'] < Logger::NOTICE) {
$this->handleDebugRecord($record);
- } elseif (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) {
+ } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
$this->handleExceptionRecord($record);
} else {
$this->handleErrorRecord($record);
}
}
- private function handleDebugRecord(LogRecord $record): void
+ /**
+ * @phpstan-param Record $record
+ */
+ private function handleDebugRecord(array $record): void
{
- [$tags, $filteredContext] = $this->getRecordTags($record);
- $message = $record->message;
- if (\count($filteredContext) > 0) {
- $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($filteredContext)), null, true);
+ $tags = $this->getRecordTags($record);
+ $message = $record['message'];
+ if ($record['context']) {
+ $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true);
}
$this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
}
- private function handleExceptionRecord(LogRecord $record): void
+ /**
+ * @phpstan-param Record $record
+ */
+ private function handleExceptionRecord(array $record): void
{
- $this->connector->getErrorsDispatcher()->dispatchException($record->context['exception']);
+ $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
}
- private function handleErrorRecord(LogRecord $record): void
+ /**
+ * @phpstan-param Record $record
+ */
+ private function handleErrorRecord(array $record): void
{
- $context = $record->context;
+ $context = $record['context'];
$this->connector->getErrorsDispatcher()->dispatchError(
$context['code'] ?? null,
- $context['message'] ?? $record->message,
+ $context['message'] ?? $record['message'],
$context['file'] ?? null,
$context['line'] ?? null,
$this->options['classesPartialsTraceIgnore']
@@ -269,32 +229,32 @@ class PHPConsoleHandler extends AbstractProcessingHandler
}
/**
- * @return array{string, mixed[]}
+ * @phpstan-param Record $record
+ * @return string
*/
- private function getRecordTags(LogRecord $record): array
+ private function getRecordTags(array &$record)
{
$tags = null;
- $filteredContext = [];
- if ($record->context !== []) {
- $filteredContext = $record->context;
+ if (!empty($record['context'])) {
+ $context = & $record['context'];
foreach ($this->options['debugTagsKeysInContext'] as $key) {
- if (isset($filteredContext[$key])) {
- $tags = $filteredContext[$key];
+ if (!empty($context[$key])) {
+ $tags = $context[$key];
if ($key === 0) {
- array_shift($filteredContext);
+ array_shift($context);
} else {
- unset($filteredContext[$key]);
+ unset($context[$key]);
}
break;
}
}
}
- return [$tags ?? $record->level->toPsrLogLevel(), $filteredContext];
+ return $tags ?: strtolower($record['level_name']);
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
protected function getDefaultFormatter(): FormatterInterface
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php
index 9edc9ac5..8a8cf1be 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php
@@ -11,8 +11,7 @@
namespace Monolog\Handler;
-use Monolog\Level;
-use Monolog\LogRecord;
+use Monolog\Logger;
/**
* Stores to STDIN of any process, specified by a command.
@@ -34,14 +33,20 @@ class ProcessHandler extends AbstractProcessingHandler
*/
private $process;
- private string $command;
+ /**
+ * @var string
+ */
+ private $command;
- private ?string $cwd;
+ /**
+ * @var string|null
+ */
+ private $cwd;
/**
* @var resource[]
*/
- private array $pipes = [];
+ private $pipes = [];
/**
* @var array
@@ -58,7 +63,7 @@ class ProcessHandler extends AbstractProcessingHandler
* @param string|null $cwd "Current working directory" (CWD) for the process to be executed in.
* @throws \InvalidArgumentException
*/
- public function __construct(string $command, int|string|Level $level = Level::Debug, bool $bubble = true, ?string $cwd = null)
+ public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null)
{
if ($command === '') {
throw new \InvalidArgumentException('The command argument must be a non-empty string.');
@@ -78,14 +83,14 @@ class ProcessHandler extends AbstractProcessingHandler
*
* @throws \UnexpectedValueException
*/
- protected function write(LogRecord $record): void
+ protected function write(array $record): void
{
$this->ensureProcessIsStarted();
- $this->writeProcessInput($record->formatted);
+ $this->writeProcessInput($record['formatted']);
$errors = $this->readProcessErrors();
- if ($errors !== '') {
+ if (empty($errors) === false) {
throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
}
}
@@ -129,7 +134,7 @@ class ProcessHandler extends AbstractProcessingHandler
$errors = $this->readProcessErrors();
- if (is_resource($this->process) === false || $errors !== '') {
+ if (is_resource($this->process) === false || empty($errors) === false) {
throw new \UnexpectedValueException(
sprintf('The process "%s" could not be opened: ' . $errors, $this->command)
);
@@ -171,7 +176,7 @@ class ProcessHandler extends AbstractProcessingHandler
}
/**
- * @inheritDoc
+ * {@inheritDoc}
*/
public function close(): void
{
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php
index 9fb290fa..3adec7a4 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php
@@ -12,19 +12,20 @@
namespace Monolog\Handler;
use Monolog\Processor\ProcessorInterface;
-use Monolog\LogRecord;
/**
* Interface to describe loggers that have processors
*
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
interface ProcessableHandlerInterface
{
/**
* Adds a processor in the stack.
*
- * @phpstan-param ProcessorInterface|(callable(LogRecord): LogRecord) $callback
+ * @psalm-param ProcessorInterface|callable(Record): Record $callback
*
* @param ProcessorInterface|callable $callback
* @return HandlerInterface self
@@ -34,7 +35,7 @@ interface ProcessableHandlerInterface
/**
* Removes the processor on top of the stack and returns it.
*
- * @phpstan-return ProcessorInterface|(callable(LogRecord): LogRecord) $callback
+ * @psalm-return ProcessorInterface|callable(Record): Record $callback
*
* @throws \LogicException In case the processor stack is empty
* @return callable|ProcessorInterface
diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php
index 74eedddd..9ef6e301 100644
--- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php
+++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php
@@ -13,23 +13,24 @@ namespace Monolog\Handler;
use Monolog\ResettableInterface;
use Monolog\Processor\ProcessorInterface;
-use Monolog\LogRecord;
/**
* Helper trait for implementing ProcessableInterface
*
* @author Jordi Boggiano