kopia lustrzana https://github.com/friendica/friendica
Porównaj commity
181 Commity
fad55e0948
...
0ccb3e7efe
Autor | SHA1 | Data |
---|---|---|
Hypolite Petovan | 0ccb3e7efe | |
Michael | 4b695e361c | |
Hypolite Petovan | 4834255acf | |
Michael | 325932dc5a | |
Hypolite Petovan | faac52e078 | |
Michael | 7a0c5d141e | |
Hypolite Petovan | 732d738b82 | |
Michael | 3d267c7b8f | |
Hypolite Petovan | 987e6c5ea6 | |
Hypolite Petovan | 9e240c24ce | |
Michael | 3b419cae1e | |
Hypolite Petovan | 56f3743e75 | |
Hypolite Petovan | f26f35f009 | |
Michael | fdd777d75d | |
Michael | aff45278e1 | |
Michael | 11a16589da | |
Tobias Diekershoff | f60638787e | |
Tobias Diekershoff | c5936bb51e | |
Tobias Diekershoff | f13c5dcbaf | |
Tobias Diekershoff | 2fcd090b11 | |
Tobias Diekershoff | 4aa53beaea | |
Tobias Diekershoff | 25a22ad3ae | |
Tobias Diekershoff | ae217ce27c | |
Hypolite Petovan | 17dea0aa5a | |
foss- | bd142218c1 | |
Michael Vogel | ce8d0b3b57 | |
Hypolite Petovan | 8f7edcef22 | |
Hypolite Petovan | 2f526f7a80 | |
Tobias Diekershoff | 2780b3e3a4 | |
Tobias Diekershoff | 2785b074f8 | |
Hypolite Petovan | 8a693fed37 | |
Hypolite Petovan | 6f5585ffd7 | |
foss- | c9f6590353 | |
foss- | 3f1cac2251 | |
Hypolite Petovan | 3a8f1f6304 | |
foss- | a5c265b6aa | |
foss- | ea79782a93 | |
Hypolite Petovan | 882673c260 | |
Michael | 668bb3e6f4 | |
Hypolite Petovan | 7331e44a1c | |
Michael | 1ffdb19c8e | |
Hypolite Petovan | 5c62d91960 | |
Hypolite Petovan | 7615a3103f | |
Michael | 2ecdd683ac | |
Michael | a9b78d1974 | |
Michael Vogel | e6c23e69cc | |
Hypolite Petovan | c81a47c764 | |
Hypolite Petovan | 4bbc1d84ce | |
Hypolite Petovan | f7cb9ec504 | |
Michael | 28363a5416 | |
Michael | f1be6d5181 | |
Michael | b75fdbbd32 | |
Philipp | 9ce2142d99 | |
Philipp | 4f24247aa7 | |
Philipp | 0eec20d203 | |
Philipp | adeb9af502 | |
Philipp | c577773e07 | |
Tobias Diekershoff | b8396daca2 | |
Michael | eaddf5318a | |
Tobias Diekershoff | aee9a61fb1 | |
Tobias Diekershoff | 81b5ed160b | |
Tobias Diekershoff | 49b79d0457 | |
Michael | 8ce1797480 | |
foss- | 650aa089d9 | |
Michael Vogel | 2c689f2b73 | |
Hypolite Petovan | aac5d41fd6 | |
Hypolite Petovan | 57187f26ae | |
Hypolite Petovan | 7446048d5d | |
Hypolite Petovan | d3ee4d589b | |
Michael | fda832cd83 | |
Michael | 30f31828ae | |
Tobias Diekershoff | cd7a663733 | |
Michael | 3b024450ff | |
Tobias Diekershoff | e22ef85386 | |
Tobias Diekershoff | e206175a50 | |
Michael | 76d469675e | |
Michael | 3496d3948a | |
Michael | 00b325d521 | |
Tobias Diekershoff | 2077e00eae | |
Michael | a1427a52b3 | |
Michael | 40a47b076d | |
Hypolite Petovan | f041701765 | |
Michael | d9bedbb473 | |
Hypolite Petovan | 013bba50bc | |
Michael | 5f0657a30c | |
Michael | 435b30be11 | |
Hypolite Petovan | 73863561d2 | |
Michael | 67696d08da | |
Hypolite Petovan | 1b00b91767 | |
Michael | 68c2bdb98e | |
Michael Vogel | 54852ecb56 | |
Hypolite Petovan | 8c4b2107b5 | |
Hypolite Petovan | 111df607bc | |
Tobias Diekershoff | b8b76e870d | |
Michael | 41c89abe68 | |
Michael | 24e7556f85 | |
Michael | 8cc7bad1ea | |
Hypolite Petovan | 2357385162 | |
Michael | 31b92b16ed | |
Hypolite Petovan | 3ad4ab2940 | |
Michael Vogel | 5ab81abaa6 | |
Hypolite Petovan | 1b651519a3 | |
Michael | ba07172a65 | |
Michael | 72e045e744 | |
Tobias Diekershoff | 2cedbae206 | |
Tobias Diekershoff | a6b033c4f6 | |
Michael Vogel | dc96a72173 | |
Tobias Diekershoff | 38141edbea | |
Tobias Diekershoff | 9b0e243350 | |
Michael | 52cc8ab73b | |
Hypolite Petovan | ea4e66c74c | |
Hypolite Petovan | f4826bae52 | |
Michael | 7471513269 | |
Michael | ae37c44cc0 | |
Hypolite Petovan | 424e219c53 | |
Michael | bae7644d6f | |
Michael Vogel | f2ccce05b8 | |
Michael Vogel | 89ffe6875f | |
Hypolite Petovan | 7284210bf7 | |
Hypolite Petovan | 4fcc92e532 | |
Hypolite Petovan | 2c259c5c6f | |
Hypolite Petovan | 39d25b9699 | |
Michael | 5df1ead001 | |
Hypolite Petovan | 2d4f28dcde | |
Michael | dd55ba2d77 | |
Hypolite Petovan | c9f7d9baff | |
Hypolite Petovan | 504a2e91e2 | |
Michael | 40e882004e | |
Michael | e394a6b0fa | |
Michael | 8cf82a8449 | |
Hypolite Petovan | 0d922b75af | |
Hypolite Petovan | ba0a8069c4 | |
Hypolite Petovan | d37699bc08 | |
Hypolite Petovan | ac087749e3 | |
Michael | ddc9f5f595 | |
Tobias Diekershoff | 35bba685fa | |
Michael | e52fa44d3f | |
Hypolite Petovan | f74d6f9ebb | |
Michael | ae358cae4c | |
Michael | b572b8989f | |
Michael | 5800a973cb | |
Michael Vogel | 44ce5471b3 | |
Michael | e05b57cd5d | |
Michael | ecdf8f2b47 | |
Michael Vogel | 1c5681c199 | |
Michael | 20fd25258a | |
Michael | 00bb538fd0 | |
Michael | 12bdbaaba8 | |
Michael | 821a135033 | |
Michael Vogel | 0ff37c0075 | |
Hypolite Petovan | 0a73050de1 | |
Hypolite Petovan | a25dbf839a | |
Hypolite Petovan | e16b6ee6e1 | |
Hypolite Petovan | 5c5d7eb04f | |
Michael Vogel | fc3898fe64 | |
Michael Vogel | 71384e6f39 | |
Michael Vogel | d95c9d28a8 | |
Hypolite Petovan | bb7d25dfc9 | |
Michael Vogel | d5c0f086bd | |
Michael | 892e0a5623 | |
Michael Vogel | cb294cf411 | |
Michael Vogel | 9ad452a19b | |
Hypolite Petovan | 623a5be8a6 | |
Hypolite Petovan | d1cd9a016e | |
Michael Vogel | 7d5d3b3c29 | |
Michael Vogel | bcec6c5ab2 | |
Michael Vogel | 6384265cbd | |
Michael Vogel | f12276eff8 | |
Michael Vogel | c6160a1c38 | |
Michael Vogel | 07c20da08f | |
Michael Vogel | 4eefd0a205 | |
Hypolite Petovan | 78bc1359e0 | |
Hypolite Petovan | 1956c2ecfd | |
Michael | ade2369b5d | |
Michael | 0d2ea97eb1 | |
Michael Vogel | 08fa51d0bb | |
Michael | 7d10518e94 | |
Michael | 1069cfb570 | |
Michael Vogel | 14e5b06029 | |
Tobias Diekershoff | 1ea8a4042d | |
Tobias Diekershoff | f9c484c642 |
|
@ -39,7 +39,7 @@ steps:
|
|||
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
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
matrix:
|
||||
include:
|
||||
- PHP_MAJOR_VERSION: 7.4
|
||||
PHP_VERSION: 7.4.33
|
||||
- PHP_MAJOR_VERSION: 8.2
|
||||
PHP_VERSION: 8.2.16
|
||||
|
||||
branches:
|
||||
exclude: [ stable ]
|
||||
when:
|
||||
- branch:
|
||||
exclude: [ stable ]
|
||||
|
||||
# This forces CI executions at the "opensocial" labeled location (because of much more power...)
|
||||
labels:
|
||||
|
|
|
@ -8,5 +8,6 @@ steps:
|
|||
commands:
|
||||
- /check-messages.sh
|
||||
|
||||
branches:
|
||||
exclude: [ stable ]
|
||||
when:
|
||||
- branch:
|
||||
exclude: [ stable ]
|
||||
|
|
|
@ -5,9 +5,11 @@ matrix:
|
|||
- PHP_MAJOR_VERSION: 8.0
|
||||
PHP_VERSION: 8.0.30
|
||||
- PHP_MAJOR_VERSION: 8.1
|
||||
PHP_VERSION: 8.1.23
|
||||
PHP_VERSION: 8.1.27
|
||||
- PHP_MAJOR_VERSION: 8.2
|
||||
PHP_VERSION: 8.2.11
|
||||
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:
|
||||
|
@ -16,7 +18,6 @@ labels:
|
|||
steps:
|
||||
php-lint:
|
||||
image: php:${PHP_MAJOR_VERSION}
|
||||
group: lint
|
||||
commands:
|
||||
- find . -name \*.php -not -path './vendor/*' -not -path './view/asset/*' -print0 | xargs -0 -n1 php -l
|
||||
restore_cache:
|
||||
|
@ -64,7 +65,7 @@ steps:
|
|||
- 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}" = "7.4" -a "${CI_REPO}" = "friendica/friendica" ]; then
|
||||
- if [ "${PHP_MAJOR_VERSION}" = "8.2" -a "${CI_REPO}" = "friendica/friendica" ]; then
|
||||
phpenmod xdebug;
|
||||
export XDEBUG_MODE=coverage;
|
||||
phpunit --configuration tests/phpunit.xml -d memory_limit=-1 --coverage-clover clover.xml;
|
||||
|
@ -75,8 +76,8 @@ steps:
|
|||
image: friendicaci/codecov
|
||||
when:
|
||||
matrix:
|
||||
PHP_MAJOR_VERSION: 7.4
|
||||
PHP_VERSION: 7.4.33
|
||||
PHP_MAJOR_VERSION: 8.2
|
||||
PHP_VERSION: 8.2.16
|
||||
repo:
|
||||
- friendica/friendica
|
||||
commands:
|
||||
|
|
|
@ -37,7 +37,7 @@ steps:
|
|||
branch: stable
|
||||
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
|
||||
|
|
82
CHANGELOG
82
CHANGELOG
|
@ -1,9 +1,71 @@
|
|||
Version 2024.03 (unreleased)
|
||||
Version 2024.06 (unreleased)
|
||||
Friendica Core
|
||||
|
||||
Friendica Addons
|
||||
|
||||
Closed Issues
|
||||
|
||||
Version 2024.03 (2024-03-21)
|
||||
Friendica Core
|
||||
Updates to the translations AR, BG, CS, DE, EO, ES, FR, GD, HU, IS, IT, JA, PL, RO, RU, SV
|
||||
Updates to the themes (frio, vier) [annando, foss-, haheute, MrPetovan, Raroun, toddy15]
|
||||
Improved the channel feature [annando]
|
||||
Improved the search performance [annando]
|
||||
Improved spam detection [annando]
|
||||
Improved the account overview on the moderation page [annando]
|
||||
Improved account creation via CLI console [mexon]
|
||||
Improved the Mastodon compatible API [annando, MrPetovan]
|
||||
Improved logging of the system load value [annando]
|
||||
Improved image handling [annando]
|
||||
Improved detection of user activity [annando]
|
||||
Improved display of embedded videos [annando]
|
||||
Fixed an issue that could lead to empty URLs in the server block list [annando]
|
||||
Fixed XSS attacks [leoOliver, MrPetovan, snajafov]
|
||||
Fixed an issue when importing emails [annando]
|
||||
Fixed an issue that blocked users could still use the API [annando]
|
||||
Fixed an issue when fetching remote content [annando, arcanicanis]
|
||||
Fixed an issue with unescaped HTML characters for RSS feeds [MrPetovan, r1pu5u]
|
||||
Fixed an issue when showing the post preview [annando]
|
||||
General code cleanup [annando, MrPetovan]
|
||||
Updated the PasswordExposed usage [mexon]
|
||||
Removed fpostit (Friendica post bookmarklet) [MrPetovan]
|
||||
Removed the possibility for users to follow relays directly [annando]
|
||||
Removed unused OEmbed functionality [annando]
|
||||
Removed legacy schemes from frio theme [MrPetovan]
|
||||
Added blur effect to sensitive images and user setting against it [annando]
|
||||
Added account type Channel Relay [annando]
|
||||
Added OCR generated image descriptions via tesseract addon [annando]
|
||||
Added WebP and BMP support [annando]
|
||||
Added blocked email addresses for registration [annando]
|
||||
|
||||
Friendica Addons
|
||||
advancedcontentfilter
|
||||
Updated dependency for PHP8.2 compatibility [MrPetovan]
|
||||
blockbot
|
||||
Fixed an issue preventing the creation of previews on remote systems [annando]
|
||||
Updated block lists [annando]
|
||||
bluesky
|
||||
Overhaul of the Bluesky connector [annando]
|
||||
Fixed problem with empty quoted shares [annando]
|
||||
openstreetmap
|
||||
Fix a config problem [haheute]
|
||||
pnut:
|
||||
Connector addon was added [spacenerdmo]
|
||||
tesseract
|
||||
Added the addon to generate image descriptions from images via OCR [annando]
|
||||
tumblr
|
||||
Improved handling of quoted shares [annando]
|
||||
url_replace
|
||||
Added addon to replace URLs from Twitter, Youtube and some others using 12ft.io [toddy15]
|
||||
Fixed an issue with empty config vars [MrPetovan]
|
||||
|
||||
Closed Issues
|
||||
903, 7732, 8768, 11142, 13220, 13293, 13765, 13768, 13809,
|
||||
13814, 13814, 13818, 13819, 13822, 13823, 13828, 13837, 13839,
|
||||
13844, 13845, 13859, 13863, 13873, 13877, 13886, 13887, 13897,
|
||||
13899, 13905, 13909, 13922, 13925, 13930, 13939, 13940, 13946,
|
||||
13947, 13949, 13950, 13953, 13955, 13959, 13968, 13969, 13972,
|
||||
13984, 13985, 13986
|
||||
|
||||
Version 2023.12 (2023-12-24)
|
||||
Friendica Core
|
||||
|
@ -505,7 +567,7 @@ Version 2022.02 (2022-02-06)
|
|||
Added a media tab on profile pages [annando]
|
||||
Removed video tab on profile pages [annando]
|
||||
Bumped the minimal version of PHP to 7.3
|
||||
|
||||
|
||||
Friendica Addons
|
||||
Updates to the translations AR, DE, FR, HU, IT, PL, SV [translation teams]
|
||||
Deprecated addons: blogger, buffer, jappixmini, notimeline, xmpp
|
||||
|
@ -530,7 +592,7 @@ Version 2022.02 (2022-02-06)
|
|||
Fixed API calls [MrPetovan]
|
||||
Fixed a problem leading to duplicated links [annando]
|
||||
Updated twitteroauth dependency [nupplaphil]
|
||||
|
||||
|
||||
Closed Issues
|
||||
9720, 10301, 10365, 10454, 10634, 10691, 10725, 10726, 10729, 10734,
|
||||
10737, 10739, 10745, 10754, 10767, 10791, 10829, 10832, 10839, 10841,
|
||||
|
@ -634,7 +696,7 @@ Version 2021.07 (2021-07-04)
|
|||
The "authenticate" hook was moved deeper into the process [very-ape]
|
||||
Added support for RTL languages [MrPetovan]
|
||||
Added download link for the calendar entries [annando]
|
||||
|
||||
|
||||
Friendica Addons
|
||||
Updates to the translations DE, HU, IT, JA [translation teams]
|
||||
nitter
|
||||
|
@ -659,7 +721,7 @@ Version 2021.07 (2021-07-04)
|
|||
adaptation of new addon functionalities and code improvements [mexon]
|
||||
phpmailer
|
||||
updated dependencies [nupplaphil]
|
||||
|
||||
|
||||
Closed Issues
|
||||
7967, 8262, 9715, 9064, 9993, 10055, 10147, 10184, 10198, 10205, 10210,
|
||||
10219, 10232, 10254, 10287, 10293, 10306, 10312, 10314, 10342, 10364,
|
||||
|
@ -1053,7 +1115,7 @@ Version 2020.03 "Red Hot Poker" (2020-03-30)
|
|||
Added fetching of contact relations [annando]
|
||||
unicode emoticons:
|
||||
Extended the list of supported emoticons [loma-one]
|
||||
|
||||
|
||||
Closed Issues:
|
||||
4599, 5562, 6205, 6418, 6757, 7558, 7560, 7771, 7808, 7817, 7892,
|
||||
7964, 7968, 7978, 7984, 7991, 7992, 7994, 8002, 8008, 8014, 8058,
|
||||
|
@ -1290,7 +1352,7 @@ Version 2019.06 (2019-06-23)
|
|||
Version 2019.04 (2019-04-28)
|
||||
Friendica Core:
|
||||
Fixed a privacy problem with postings accessed by feed [MrPetovan]
|
||||
|
||||
|
||||
Version 2019.03 (2019-03-22)
|
||||
Friendica Core:
|
||||
Update to the translation (CS, DE, EN-GB, EN-US, ES, FR, IT, PL, SV, ZH-CN) [translation teams]
|
||||
|
@ -1465,7 +1527,7 @@ Version 2019.01 (2019-01-21)
|
|||
6268, 6282, 6283, 6208, 6289, 6294, 6308, 6309, 6313, 6316, 6323,
|
||||
6329, 6334, 6344, 6347, 6343, 6349, 6350, 6355, 6358, 6360, 6361,
|
||||
6363, 6368, 6370, 6391, 6394, 6424, 6425, 6439, 6459
|
||||
|
||||
|
||||
Version 2018.09 (2018-09-23)
|
||||
Friendica Core:
|
||||
Update to the translation (CS, DE, EN-US, FI, IT, NL, PL, ZH-CN) [translation teams]
|
||||
|
@ -1500,13 +1562,13 @@ Version 2018.09 (2018-09-23)
|
|||
Fixed a bug in the daemon mode of the background worker [annando]
|
||||
Fixed a bug in the frio theme that contact filtering [rabuzarus]
|
||||
Fixed a bug that mangled the display of some additional smileys [abanink]
|
||||
Fixed a bug in generating registration mails [MrPetovan]
|
||||
Fixed a bug in generating registration mails [MrPetovan]
|
||||
Fixed a bug that caused blank re-share bodies [MrPetovon]
|
||||
Fixed a bug in the API handling of private mails [fabrixxm]
|
||||
Fixed a bug when calling the mail() function [miqrogroove]
|
||||
Fixed a bug that caused deleted accounts being displayed in the local directory [miqrogroove]
|
||||
Fixed a bug when checking the domain of an email address [VVelox]
|
||||
Fixed a bug that prevented re-shares from Twitter to be shown as this [annando]
|
||||
Fixed a bug that prevented re-shares from Twitter to be shown as this [annando]
|
||||
Fixed a bug that caused broken profile links [miqrogroove]
|
||||
Fixed a bug that caused content from unknown accounts appearing in the timeline [annando]
|
||||
Fixed a bug with the ignoring and blocking of contacts [annando]
|
||||
|
|
|
@ -32,6 +32,7 @@ Anthronaut
|
|||
Anton
|
||||
Antron Samurai
|
||||
Anubis2814
|
||||
arcanicanis
|
||||
Arian - Cazare Muncitori
|
||||
Asher Pen
|
||||
atjn
|
||||
|
@ -136,6 +137,7 @@ gudzpoz
|
|||
GunChleoc
|
||||
guzzisti
|
||||
Haakon Meland Eriksen
|
||||
haheute
|
||||
Hank Grabowski
|
||||
Hannes Heute
|
||||
Hans Meine
|
||||
|
@ -147,6 +149,7 @@ hlad
|
|||
hoergen
|
||||
Hubert Kościański
|
||||
Hypolite Petovan
|
||||
ike
|
||||
Ilmari
|
||||
ImgBotApp
|
||||
irhen
|
||||
|
@ -222,6 +225,7 @@ Michal Šupler
|
|||
Michalina
|
||||
Mike Macgirvin
|
||||
miqrogroove
|
||||
Morgan McMillian
|
||||
mpanhans
|
||||
mytbk
|
||||
nathilia-peirce
|
||||
|
@ -255,8 +259,10 @@ Pierre Bernardeau
|
|||
Pierre Rudloff
|
||||
Piotr Blonkowski
|
||||
Piotr Strębski
|
||||
pixelroot
|
||||
pokerazor
|
||||
R C
|
||||
r1pu5u
|
||||
Rabuzarus
|
||||
Radek
|
||||
Rafael Garau
|
||||
|
@ -294,9 +300,11 @@ Senex Petrovic
|
|||
Seth
|
||||
SickShark X
|
||||
Silke Meyer
|
||||
Simon
|
||||
Simon L'nu
|
||||
Simon Rupf
|
||||
Simó Albert i Beltran
|
||||
snajafov
|
||||
softmetz
|
||||
soko1
|
||||
Spencer Dub
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2024.03-dev
|
||||
2024.06-dev
|
||||
|
|
|
@ -299,28 +299,28 @@
|
|||
},
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/ca-bundle.git",
|
||||
"reference": "b66d11b7479109ab547f9405b97205640b17d385"
|
||||
"reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/b66d11b7479109ab547f9405b97205640b17d385",
|
||||
"reference": "b66d11b7479109ab547f9405b97205640b17d385",
|
||||
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
|
||||
"reference": "0c5ccfcfea312b5c5a190a21ac5cef93f74baf99",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"php": "^5.3.2 || ^7.0 || ^8.0"
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.55",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/phpunit-bridge": "^4.2 || ^5",
|
||||
"symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"
|
||||
"symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -366,7 +366,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-18T12:05:55+00:00"
|
||||
"time": "2024-03-15T14:00:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dasprid/enum",
|
||||
|
@ -1498,16 +1498,16 @@
|
|||
},
|
||||
{
|
||||
"name": "matriphe/iso-639",
|
||||
"version": "1.2",
|
||||
"version": "1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/matriphe/php-iso-639.git",
|
||||
"reference": "0245d844daeefdd22a54b47103ffdb0e03c323e1"
|
||||
"reference": "9a4a5823147890e70e0e0f60f3baea95e8d3b5f1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/matriphe/php-iso-639/zipball/0245d844daeefdd22a54b47103ffdb0e03c323e1",
|
||||
"reference": "0245d844daeefdd22a54b47103ffdb0e03c323e1",
|
||||
"url": "https://api.github.com/repos/matriphe/php-iso-639/zipball/9a4a5823147890e70e0e0f60f3baea95e8d3b5f1",
|
||||
"reference": "9a4a5823147890e70e0e0f60f3baea95e8d3b5f1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -1538,7 +1538,7 @@
|
|||
"language",
|
||||
"laravel"
|
||||
],
|
||||
"time": "2017-07-19T15:11:19+00:00"
|
||||
"time": "2024-03-17T21:30:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mattwright/urlresolver",
|
||||
|
@ -3327,16 +3327,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.35",
|
||||
"version": "3.0.37",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "4b1827beabce71953ca479485c0ae9c51287f2fe"
|
||||
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4b1827beabce71953ca479485c0ae9c51287f2fe",
|
||||
"reference": "4b1827beabce71953ca479485c0ae9c51287f2fe",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
|
||||
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3429,7 +3429,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-29T01:59:53+00:00"
|
||||
"time": "2024-03-03T02:14:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pragmarx/google2fa",
|
||||
|
@ -4044,16 +4044,16 @@
|
|||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v4.3.4",
|
||||
"version": "v4.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/smarty-php/smarty.git",
|
||||
"reference": "3931d8f54b8f7a4ffab538582d34d4397ba8daa5"
|
||||
"reference": "42b869e3a098b1c8ee07922ccded0e5a5dceadcd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/3931d8f54b8f7a4ffab538582d34d4397ba8daa5",
|
||||
"reference": "3931d8f54b8f7a4ffab538582d34d4397ba8daa5",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/42b869e3a098b1c8ee07922ccded0e5a5dceadcd",
|
||||
"reference": "42b869e3a098b1c8ee07922ccded0e5a5dceadcd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4101,7 +4101,7 @@
|
|||
"keywords": [
|
||||
"templating"
|
||||
],
|
||||
"time": "2023-09-14T10:59:08+00:00"
|
||||
"time": "2024-03-18T14:19:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spomky-labs/base64url",
|
||||
|
@ -4423,6 +4423,7 @@
|
|||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"abandoned": "web-token/jwt-library",
|
||||
"time": "2021-03-17T14:55:52+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -4497,6 +4498,7 @@
|
|||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"abandoned": "web-token/jwt-library",
|
||||
"time": "2021-03-17T14:55:52+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -4570,6 +4572,7 @@
|
|||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"abandoned": "web-token/jwt-library",
|
||||
"time": "2021-03-01T19:55:28+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -4636,6 +4639,7 @@
|
|||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"abandoned": "web-token/jwt-library",
|
||||
"time": "2021-01-21T19:18:03+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -4705,6 +4709,7 @@
|
|||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"abandoned": "web-token/jwt-library",
|
||||
"time": "2021-03-24T13:35:17+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -4762,16 +4767,16 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "composer/pcre",
|
||||
"version": "3.1.1",
|
||||
"version": "3.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/pcre.git",
|
||||
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
|
||||
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
|
||||
"reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
|
||||
"url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
|
||||
"reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4825,7 +4830,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-10-11T07:11:09+00:00"
|
||||
"time": "2024-03-19T10:26:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
|
@ -5073,16 +5078,16 @@
|
|||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.46.0",
|
||||
"version": "v3.52.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2"
|
||||
"reference": "6e77207f0d851862ceeb6da63e6e22c01b1587bc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/be6831c9af1740470d2a773119b9273f8ac1c3d2",
|
||||
"reference": "be6831c9af1740470d2a773119b9273f8ac1c3d2",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/6e77207f0d851862ceeb6da63e6e22c01b1587bc",
|
||||
"reference": "6e77207f0d851862ceeb6da63e6e22c01b1587bc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5092,7 +5097,7 @@
|
|||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"sebastian/diff": "^4.0 || ^5.0",
|
||||
"sebastian/diff": "^4.0 || ^5.0 || ^6.0",
|
||||
"symfony/console": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
|
||||
|
@ -5113,7 +5118,8 @@
|
|||
"php-cs-fixer/accessible-object": "^1.1",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4",
|
||||
"phpunit/phpunit": "^9.6 || ^10.5.5",
|
||||
"phpunit/phpunit": "^9.6 || ^10.5.5 || ^11.0.2",
|
||||
"symfony/var-dumper": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
@ -5156,7 +5162,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-01-03T21:38:46+00:00"
|
||||
"time": "2024-03-19T21:02:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
|
@ -5253,16 +5259,16 @@
|
|||
},
|
||||
{
|
||||
"name": "mockery/mockery",
|
||||
"version": "1.6.7",
|
||||
"version": "1.6.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mockery/mockery.git",
|
||||
"reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06"
|
||||
"reference": "47065d1be1fa05def58dc14c03cf831d3884ef0b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mockery/mockery/zipball/0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06",
|
||||
"reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06",
|
||||
"url": "https://api.github.com/repos/mockery/mockery/zipball/47065d1be1fa05def58dc14c03cf831d3884ef0b",
|
||||
"reference": "47065d1be1fa05def58dc14c03cf831d3884ef0b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5274,8 +5280,8 @@
|
|||
"phpunit/phpunit": "<8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5 || ^9.6.10",
|
||||
"symplify/easy-coding-standard": "^12.0.8"
|
||||
"phpunit/phpunit": "^8.5 || ^9.6.17",
|
||||
"symplify/easy-coding-standard": "^12.1.14"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
@ -5325,7 +5331,7 @@
|
|||
"test double",
|
||||
"testing"
|
||||
],
|
||||
"time": "2023-12-10T02:24:34+00:00"
|
||||
"time": "2024-03-19T16:15:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
|
@ -5384,16 +5390,16 @@
|
|||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.0.0",
|
||||
"version": "v5.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc"
|
||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
|
||||
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5434,24 +5440,25 @@
|
|||
"parser",
|
||||
"php"
|
||||
],
|
||||
"time": "2024-01-07T17:17:35+00:00"
|
||||
"time": "2024-03-05T20:51:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
"version": "2.0.3",
|
||||
"version": "2.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phar-io/manifest.git",
|
||||
"reference": "97803eca37d319dfa7826cc2437fc020857acb53"
|
||||
"reference": "54750ef60c58e43759730615a392c31c80e23176"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
|
||||
"reference": "97803eca37d319dfa7826cc2437fc020857acb53",
|
||||
"url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
|
||||
"reference": "54750ef60c58e43759730615a392c31c80e23176",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"phar-io/version": "^3.0.1",
|
||||
|
@ -5490,7 +5497,13 @@
|
|||
}
|
||||
],
|
||||
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
|
||||
"time": "2021-07-20T11:28:43+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/theseer",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-03-03T12:33:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/version",
|
||||
|
@ -5541,16 +5554,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "9.2.30",
|
||||
"version": "9.2.31",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089"
|
||||
"reference": "48c34b5d8d983006bd2adc2d0de92963b9155965"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089",
|
||||
"reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965",
|
||||
"reference": "48c34b5d8d983006bd2adc2d0de92963b9155965",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5610,7 +5623,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-22T06:47:57+00:00"
|
||||
"time": "2024-03-02T06:37:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
|
@ -5839,16 +5852,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.6.15",
|
||||
"version": "9.6.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "05017b80304e0eb3f31d90194a563fd53a6021f1"
|
||||
"reference": "1a156980d78a6666721b7e8e8502fe210b587fcd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1",
|
||||
"reference": "05017b80304e0eb3f31d90194a563fd53a6021f1",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd",
|
||||
"reference": "1a156980d78a6666721b7e8e8502fe210b587fcd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5933,7 +5946,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-01T16:55:19+00:00"
|
||||
"time": "2024-02-23T13:14:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/event-dispatcher",
|
||||
|
@ -5983,16 +5996,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/cli-parser.git",
|
||||
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
|
||||
"reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
|
||||
"reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
|
||||
"reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6031,7 +6044,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-28T06:08:49+00:00"
|
||||
"time": "2024-03-02T06:27:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/code-unit",
|
||||
|
@ -6261,16 +6274,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "4.0.5",
|
||||
"version": "4.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
|
||||
"reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
|
||||
"reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc",
|
||||
"reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6319,7 +6332,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-07T05:35:17+00:00"
|
||||
"time": "2024-03-02T06:30:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
|
@ -6382,16 +6395,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "4.0.5",
|
||||
"version": "4.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
|
||||
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
|
||||
"reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72",
|
||||
"reference": "78c00df8f170e02473b682df15bfcdacc3d32d72",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6451,20 +6464,20 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-09-14T06:03:37+00:00"
|
||||
"time": "2024-03-02T06:33:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
"version": "5.0.6",
|
||||
"version": "5.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/global-state.git",
|
||||
"reference": "bde739e7565280bda77be70044ac1047bc007e34"
|
||||
"reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
|
||||
"reference": "bde739e7565280bda77be70044ac1047bc007e34",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
|
||||
"reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6511,7 +6524,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-02T09:26:13+00:00"
|
||||
"time": "2024-03-02T06:35:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/lines-of-code",
|
||||
|
@ -6731,16 +6744,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/resource-operations",
|
||||
"version": "3.0.3",
|
||||
"version": "3.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/resource-operations.git",
|
||||
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
|
||||
"reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
|
||||
"reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
|
||||
"reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6752,7 +6765,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
"dev-main": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -6778,7 +6791,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-28T06:45:17+00:00"
|
||||
"time": "2024-03-14T16:00:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/type",
|
||||
|
@ -6883,16 +6896,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.4.34",
|
||||
"version": "v5.4.36",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "4b4d8cd118484aa604ec519062113dd87abde18c"
|
||||
"reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/4b4d8cd118484aa604ec519062113dd87abde18c",
|
||||
"reference": "4b4d8cd118484aa604ec519062113dd87abde18c",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e",
|
||||
"reference": "39f75d9d73d0c11952fdcecf4877b4d0f62a8f6e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6975,20 +6988,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-08T13:33:03+00:00"
|
||||
"time": "2024-02-20T16:33:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v5.4.34",
|
||||
"version": "v5.4.35",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "e3bca343efeb613f843c254e7718ef17c9bdf7a3"
|
||||
"reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e3bca343efeb613f843c254e7718ef17c9bdf7a3",
|
||||
"reference": "e3bca343efeb613f843c254e7718ef17c9bdf7a3",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7a69a85c7ea5bdd1e875806a99c51a87d3a74b38",
|
||||
"reference": "7a69a85c7ea5bdd1e875806a99c51a87d3a74b38",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7057,7 +7070,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-27T21:12:56+00:00"
|
||||
"time": "2024-01-23T13:51:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
|
@ -7137,16 +7150,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v5.4.25",
|
||||
"version": "v5.4.35",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364"
|
||||
"reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364",
|
||||
"reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/5a553607d4ffbfa9c0ab62facadea296c9db7086",
|
||||
"reference": "5a553607d4ffbfa9c0ab62facadea296c9db7086",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7194,20 +7207,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-31T13:04:02+00:00"
|
||||
"time": "2024-01-23T13:51:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v5.4.27",
|
||||
"version": "v5.4.35",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d"
|
||||
"reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/ff4bce3c33451e7ec778070e45bd23f74214cd5d",
|
||||
"reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/abe6d6f77d9465fed3cd2d029b29d03b56b56435",
|
||||
"reference": "abe6d6f77d9465fed3cd2d029b29d03b56b56435",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7254,7 +7267,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-31T08:02:31+00:00"
|
||||
"time": "2024-01-23T13:51:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
|
@ -7324,16 +7337,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.28.0",
|
||||
"version": "v1.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
|
||||
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
|
||||
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
|
||||
"reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7347,9 +7360,6 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
|
@ -7399,20 +7409,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.28.0",
|
||||
"version": "v1.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "875e90aeea2777b6f135677f618529449334a612"
|
||||
"reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
|
||||
"reference": "875e90aeea2777b6f135677f618529449334a612",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f",
|
||||
"reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7423,9 +7433,6 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
|
@ -7477,20 +7484,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.28.0",
|
||||
"version": "v1.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
|
||||
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
|
||||
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
|
||||
"reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7501,9 +7508,6 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
|
@ -7558,20 +7562,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.28.0",
|
||||
"version": "v1.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229"
|
||||
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
|
||||
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7585,9 +7589,6 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
|
@ -7638,20 +7639,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-28T09:04:16+00:00"
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php73",
|
||||
"version": "v1.28.0",
|
||||
"version": "v1.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php73.git",
|
||||
"reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5"
|
||||
"reference": "21bd091060673a1177ae842c0ef8fe30893114d2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5",
|
||||
"reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2",
|
||||
"reference": "21bd091060673a1177ae842c0ef8fe30893114d2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7659,9 +7660,6 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
|
@ -7714,20 +7712,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.28.0",
|
||||
"version": "v1.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
|
||||
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
|
||||
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
|
||||
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7735,9 +7733,6 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
|
@ -7794,20 +7789,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.28.0",
|
||||
"version": "v1.29.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b"
|
||||
"reference": "c565ad1e63f30e7477fc40738343c62b40bc672d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b",
|
||||
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d",
|
||||
"reference": "c565ad1e63f30e7477fc40738343c62b40bc672d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7815,9 +7810,6 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
|
@ -7870,20 +7862,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
"time": "2024-01-29T20:11:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v5.4.34",
|
||||
"version": "v5.4.36",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a"
|
||||
"reference": "4fdf34004f149cc20b2f51d7d119aa500caad975"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/8fa22178dfc368911dbd513b431cd9b06f9afe7a",
|
||||
"reference": "8fa22178dfc368911dbd513b431cd9b06f9afe7a",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/4fdf34004f149cc20b2f51d7d119aa500caad975",
|
||||
"reference": "4fdf34004f149cc20b2f51d7d119aa500caad975",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7929,7 +7921,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-02T08:41:43+00:00"
|
||||
"time": "2024-02-12T15:49:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
|
@ -7991,16 +7983,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/stopwatch",
|
||||
"version": "v5.4.21",
|
||||
"version": "v5.4.35",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/stopwatch.git",
|
||||
"reference": "f83692cd869a6f2391691d40a01e8acb89e76fee"
|
||||
"reference": "887762aa99ff16f65dc8b48aafead415f942d407"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee",
|
||||
"reference": "f83692cd869a6f2391691d40a01e8acb89e76fee",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/887762aa99ff16f65dc8b48aafead415f942d407",
|
||||
"reference": "887762aa99ff16f65dc8b48aafead415f942d407",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -8046,20 +8038,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-14T08:03:56+00:00"
|
||||
"time": "2024-01-23T13:51:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v5.4.34",
|
||||
"version": "v5.4.36",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "e3f98bfc7885c957488f443df82d97814a3ce061"
|
||||
"reference": "4e232c83622bd8cd32b794216aa29d0d266d353b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/e3f98bfc7885c957488f443df82d97814a3ce061",
|
||||
"reference": "e3f98bfc7885c957488f443df82d97814a3ce061",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/4e232c83622bd8cd32b794216aa29d0d266d353b",
|
||||
"reference": "4e232c83622bd8cd32b794216aa29d0d266d353b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -8129,20 +8121,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-09T13:20:28+00:00"
|
||||
"time": "2024-02-01T08:49:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/theseer/tokenizer.git",
|
||||
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
|
||||
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
|
||||
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -8175,7 +8167,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-11-20T00:12:19+00:00"
|
||||
"time": "2024-03-03T12:36:25+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
|
52
database.sql
52
database.sql
|
@ -1,6 +1,6 @@
|
|||
-- ------------------------------------------
|
||||
-- Friendica 2024.03-dev (Yellow Archangel)
|
||||
-- DB_UPDATE_VERSION 1552
|
||||
-- Friendica 2024.06-dev (Yellow Archangel)
|
||||
-- DB_UPDATE_VERSION 1559
|
||||
-- ------------------------------------------
|
||||
|
||||
|
||||
|
@ -539,6 +539,7 @@ CREATE TABLE IF NOT EXISTS `contact-relation` (
|
|||
`relation-score` smallint unsigned COMMENT 'score for interactions of relation-cid on cid',
|
||||
`thread-score` smallint unsigned COMMENT 'score for interactions of cid on threads of relation-cid',
|
||||
`relation-thread-score` smallint unsigned COMMENT 'score for interactions of relation-cid on threads of cid',
|
||||
`post-score` smallint unsigned COMMENT 'score for the amount of posts from cid that can be seen by relation-cid',
|
||||
PRIMARY KEY(`cid`,`relation-cid`),
|
||||
INDEX `relation-cid` (`relation-cid`),
|
||||
FOREIGN KEY (`cid`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
|
||||
|
@ -1346,11 +1347,12 @@ CREATE TABLE IF NOT EXISTS `post-engagement` (
|
|||
`uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri',
|
||||
`owner-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item owner',
|
||||
`contact-type` tinyint NOT NULL DEFAULT 0 COMMENT 'Person, organisation, news, community, relay',
|
||||
`media-type` tinyint NOT NULL DEFAULT 0 COMMENT 'Type of media in a bit array (1 = image, 2 = video, 4 = audio',
|
||||
`media-type` tinyint NOT NULL DEFAULT 0 COMMENT 'Type of media in a bit array (1 = image, 2 = video, 4 = audio)',
|
||||
`language` char(2) COMMENT 'Language information about this post in the ISO 639-1 format',
|
||||
`searchtext` mediumtext COMMENT 'Simplified text for the full text search',
|
||||
`size` int unsigned COMMENT 'Body size',
|
||||
`created` datetime COMMENT '',
|
||||
`network` char(4) COMMENT '',
|
||||
`restricted` boolean NOT NULL DEFAULT '0' COMMENT 'If true, this post is either unlisted or not from a federated network',
|
||||
`comments` mediumint unsigned COMMENT 'Number of comments',
|
||||
`activities` mediumint unsigned COMMENT 'Number of activities (like, dislike, ...)',
|
||||
|
@ -1469,7 +1471,7 @@ CREATE TABLE IF NOT EXISTS `post-question-option` (
|
|||
CREATE TABLE IF NOT EXISTS `post-searchindex` (
|
||||
`uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri',
|
||||
`owner-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item owner',
|
||||
`media-type` tinyint NOT NULL DEFAULT 0 COMMENT 'Type of media in a bit array (1 = image, 2 = video, 4 = audio',
|
||||
`media-type` tinyint NOT NULL DEFAULT 0 COMMENT 'Type of media in a bit array (1 = image, 2 = video, 4 = audio)',
|
||||
`language` char(2) COMMENT 'Language information about this post in the ISO 639-1 format',
|
||||
`searchtext` mediumtext COMMENT 'Simplified text for the full text search',
|
||||
`size` int unsigned COMMENT 'Body size',
|
||||
|
@ -1548,6 +1550,7 @@ CREATE TABLE IF NOT EXISTS `post-user` (
|
|||
`post-reason` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Reason why the post arrived at the user',
|
||||
`vid` smallint unsigned COMMENT 'Id of the verb table entry that contains the activity verbs',
|
||||
`private` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '0=public, 1=private, 2=unlisted',
|
||||
`restrictions` tinyint unsigned COMMENT 'Bit array of post restrictions (1 = Reply, 2 = Like, 4 = Announce)',
|
||||
`global` boolean NOT NULL DEFAULT '0' COMMENT '',
|
||||
`visible` boolean NOT NULL DEFAULT '0' COMMENT '',
|
||||
`deleted` boolean NOT NULL DEFAULT '0' COMMENT 'item has been marked for deletion',
|
||||
|
@ -1945,6 +1948,7 @@ CREATE TABLE IF NOT EXISTS `user-contact` (
|
|||
`ignored` boolean COMMENT 'Posts from this contact are ignored',
|
||||
`collapsed` boolean COMMENT 'Posts from this contact are collapsed',
|
||||
`hidden` boolean COMMENT 'This contact is hidden from the others',
|
||||
`channel-only` boolean COMMENT 'This contact is displayed only in channels, but not in the network stream.',
|
||||
`is-blocked` boolean COMMENT 'User is blocked by this contact',
|
||||
`channel-frequency` tinyint unsigned COMMENT 'Controls the frequency of the appearance of this contact in channels',
|
||||
`pending` boolean COMMENT '',
|
||||
|
@ -2015,7 +2019,8 @@ CREATE VIEW `application-view` AS SELECT
|
|||
`application-token`.`follow` AS `follow`,
|
||||
`application-token`.`push` AS `push`
|
||||
FROM `application-token`
|
||||
INNER JOIN `application` ON `application-token`.`application-id` = `application`.`id`;
|
||||
INNER JOIN `application` ON `application-token`.`application-id` = `application`.`id`
|
||||
INNER JOIN `user` ON `user`.`uid` = `application-token`.`uid` AND `user`.`verified` AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND NOT `user`.`account_expired`;
|
||||
|
||||
--
|
||||
-- VIEW circle-member-view
|
||||
|
@ -2122,6 +2127,7 @@ CREATE VIEW `post-searchindex-user-view` AS SELECT
|
|||
`post-thread-user`.`commented` AS `commented`,
|
||||
`post-thread-user`.`received` AS `received`,
|
||||
`post-thread-user`.`created` AS `created`,
|
||||
`post-thread-user`.`network` AS `network`,
|
||||
`post-searchindex`.`language` AS `restricted`,
|
||||
0 AS `comments`,
|
||||
0 AS `activities`
|
||||
|
@ -2196,6 +2202,7 @@ CREATE VIEW `post-user-view` AS SELECT
|
|||
`post-content`.`location` AS `location`,
|
||||
`post-content`.`coord` AS `coord`,
|
||||
`post-content`.`sensitive` AS `sensitive`,
|
||||
`post-user`.`restrictions` AS `restrictions`,
|
||||
`post-content`.`app` AS `app`,
|
||||
`post-content`.`object-type` AS `object-type`,
|
||||
`post-content`.`object` AS `object`,
|
||||
|
@ -2381,6 +2388,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT
|
|||
`post-content`.`location` AS `location`,
|
||||
`post-content`.`coord` AS `coord`,
|
||||
`post-content`.`sensitive` AS `sensitive`,
|
||||
`post-user`.`restrictions` AS `restrictions`,
|
||||
`post-content`.`app` AS `app`,
|
||||
`post-content`.`object-type` AS `object-type`,
|
||||
`post-content`.`object` AS `object`,
|
||||
|
@ -2872,36 +2880,6 @@ CREATE VIEW `tag-view` AS SELECT
|
|||
LEFT JOIN `tag` ON `post-tag`.`tid` = `tag`.`id`
|
||||
LEFT JOIN `contact` ON `post-tag`.`cid` = `contact`.`id`;
|
||||
|
||||
--
|
||||
-- VIEW network-item-view
|
||||
--
|
||||
DROP VIEW IF EXISTS `network-item-view`;
|
||||
CREATE VIEW `network-item-view` AS SELECT
|
||||
`post-user`.`uri-id` AS `uri-id`,
|
||||
`post-thread-user`.`post-user-id` AS `parent`,
|
||||
`post-user`.`received` AS `received`,
|
||||
`post-thread-user`.`commented` AS `commented`,
|
||||
`post-user`.`created` AS `created`,
|
||||
`post-user`.`uid` AS `uid`,
|
||||
`post-thread-user`.`starred` AS `starred`,
|
||||
`post-thread-user`.`mention` AS `mention`,
|
||||
`post-user`.`network` AS `network`,
|
||||
`post-user`.`unseen` AS `unseen`,
|
||||
`post-user`.`gravity` AS `gravity`,
|
||||
`post-user`.`contact-id` AS `contact-id`,
|
||||
`ownercontact`.`contact-type` AS `contact-type`
|
||||
FROM `post-user`
|
||||
INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid`
|
||||
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id`
|
||||
STRAIGHT_JOIN `contact` AS `authorcontact` ON `authorcontact`.`id` = `post-thread-user`.`author-id`
|
||||
STRAIGHT_JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread-user`.`owner-id`
|
||||
WHERE `post-user`.`visible` AND NOT `post-user`.`deleted`
|
||||
AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
|
||||
AND (`post-user`.`hidden` IS NULL OR NOT `post-user`.`hidden`)
|
||||
AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked`
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`);
|
||||
|
||||
--
|
||||
-- VIEW network-thread-view
|
||||
--
|
||||
|
@ -2927,8 +2905,8 @@ CREATE VIEW `network-thread-view` AS SELECT
|
|||
AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
|
||||
AND (`post-thread-user`.`hidden` IS NULL OR NOT `post-thread-user`.`hidden`)
|
||||
AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked`
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`);
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`post-thread-user`.`author-id`, `post-thread-user`.`owner-id`, `post-thread-user`.`causer-id`) AND (`blocked` OR `ignored` OR `channel-only`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`);
|
||||
|
||||
--
|
||||
-- VIEW owner-view
|
||||
|
|
|
@ -11,21 +11,7 @@ Authentication is the same as described in [Using the APIs](help/api#Authenticat
|
|||
|
||||
## Clients
|
||||
|
||||
### Supported apps
|
||||
|
||||
For supported apps please have a look at the [FAQ](help/FAQ#clients)
|
||||
|
||||
### Unsupported apps
|
||||
|
||||
#### Android
|
||||
|
||||
- [Fedilab](https://framagit.org/tom79/fedilab) Automatically uses the legacy API, see issue: https://framagit.org/tom79/fedilab/-/issues/520
|
||||
- [Mammut](https://github.com/jamiesanson/Mammut) There are problems with the token request, see issue https://github.com/jamiesanson/Mammut/issues/19
|
||||
|
||||
#### iOS
|
||||
|
||||
- [Mast](https://github.com/Beesitech/Mast) Doesn't accept the entered instance name. Claims that it is invalid (Message is: "Not a valid instance (may be closed or dead)")
|
||||
- [Toot!](https://apps.apple.com/app/toot/id1229021451)
|
||||
Please find a list of supported apps at [FAQ](help/FAQ#clients).
|
||||
|
||||
## Entities
|
||||
|
||||
|
@ -170,7 +156,8 @@ Example:
|
|||
|
||||
- [`GET /api/v1/followed_tags`](https://docs.joinmastodon.org/methods/followed_tags/)
|
||||
- [`GET /api/v1/instance`](https://docs.joinmastodon.org/methods/instance/#v1)
|
||||
- `GET /api/v1/instance/rules` Undocumented, returns Terms of Service
|
||||
- [`GET /api/v1/instance/extended_description`](https://docs.joinmastodon.org/methods/instance/#extended_description)
|
||||
- [`GET /api/v1/instance/rules`](https://docs.joinmastodon.org/methods/instance/#rules)
|
||||
- [`GET /api/v1/instance/peers`](https://docs.joinmastodon.org/methods/instance#list-of-connected-domains)
|
||||
- [`GET /api/v1/lists`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
||||
- [`POST /api/v1/lists`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
||||
|
@ -314,7 +301,6 @@ They refer to features or data that don't exist in Friendica yet.
|
|||
- [`PUT /api/v1/filters/:id`](https://docs.joinmastodon.org/methods/accounts/filters/)
|
||||
- [`DELETE /api/v1/filters/:id`](https://docs.joinmastodon.org/methods/accounts/filters/)
|
||||
- [`GET /api/v1/instance/activity`](https://docs.joinmastodon.org/methods/instance#weekly-activity)
|
||||
- [`POST /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/)
|
||||
- [`PUT /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/)
|
||||
- [`GET /api/v1/statuses/{id:\d+}/history`](https://github.com/mastodon/mastodon/pull/16697)
|
||||
- [`GET /api/v1/streaming`](https://docs.joinmastodon.org/methods/timelines/streaming/)
|
||||
|
|
|
@ -34,6 +34,7 @@ General
|
|||
* y - for you
|
||||
* f - followers
|
||||
* r - sharers of sharers
|
||||
* q - quiet sharers
|
||||
* h - what's hot
|
||||
* i - Images
|
||||
* v - Videos
|
||||
|
|
|
@ -33,6 +33,7 @@ Predefined Channels
|
|||
* Language: Posts in your language.
|
||||
* Followers: Posts from your followers that you don't follow.
|
||||
* Sharers of sharers: Posts from accounts that are followed by accounts that you follow.
|
||||
* Quiet sharers: Posts from accounts that you follow but who don't post very often.
|
||||
* Images: Posts with images.
|
||||
* Audio: Posts with audio.
|
||||
* Videos: Posts with videos.
|
||||
|
|
10
doc/FAQ.md
10
doc/FAQ.md
|
@ -178,12 +178,12 @@ The available features are client specific and may differ.
|
|||
#### Android
|
||||
|
||||
* [AndStatus](http://andstatus.org) ([F-Droid](https://f-droid.org/repository/browse/?fdid=org.andstatus.app), [Google Play](https://play.google.com/store/apps/details?id=org.andstatus.app))
|
||||
* [Fedi](https://github.com/Big-Fig/Fediverse.app) ([Google Play](https://play.google.com/store/apps/details?id=com.fediverse.app))
|
||||
* [Fedilab](https://fedilab.app) ([F-Droid](https://f-droid.org/app/fr.gouv.etalab.mastodon), [Google Play](https://play.google.com/store/apps/details?id=app.fedilab.android))
|
||||
* [Friendiqa](https://git.friendi.ca/lubuwest/Friendiqa) ([F-Droid](https://git.friendi.ca/lubuwest/Friendiqa#install), [Google Play](https://play.google.com/store/apps/details?id=org.qtproject.friendiqa))
|
||||
* [Husky](https://git.sr.ht/~captainepoch/husky) ([F-Droid](https://f-droid.org/repository/browse/?fdid=su.xash.husky), [Google Play](https://play.google.com/store/apps/details?id=su.xash.husky))
|
||||
* [Husky](https://codeberg.org/husky/husky) ([F-Droid](https://f-droid.org/repository/browse/?fdid=su.xash.husky), [Google Play](https://play.google.com/store/apps/details?id=su.xash.husky))
|
||||
* [Mastodon](https://github.com/mastodon/mastodon-android) ([F-Droid](https://f-droid.org/en/packages/org.joinmastodon.android/), [Google Play](https://play.google.com/store/apps/details?id=org.joinmastodon.android))
|
||||
* [Subway Tooter](https://github.com/tateisu/SubwayTooter) ([F-Droid](https://android.izzysoft.de/repo/apk/jp.juggler.subwaytooter))
|
||||
* [Pachli](https://pachli.app/) ([F-Droid](https://f-droid.org/en/packages/app.pachli/), [Google Play](https://play.google.com/store/apps/details?id=app.pachli))
|
||||
* [Subway Tooter](https://github.com/tateisu/SubwayTooter) ([F-Droid via Izzy](https://android.izzysoft.de/repo/apk/jp.juggler.subwaytooter.noFcm))
|
||||
* [Tooot](https://tooot.app/) ([Google Play](https://play.google.com/store/apps/details?id=com.xmflsct.app.tooot))
|
||||
* [Tusky](https://tusky.app) ([F-Droid](https://f-droid.org/repository/browse/?fdid=com.keylesspalace.tusky), [Google Play](https://play.google.com/store/apps/details?id=com.keylesspalace.tusky))
|
||||
* [TwidereX](https://github.com/TwidereProject/TwidereX-Android) ([F-Droid](https://f-droid.org/en/packages/com.twidere.twiderex/), [Google Play](https://play.google.com/store/apps/details?id=com.twidere.twiderex))
|
||||
|
@ -193,7 +193,7 @@ The available features are client specific and may differ.
|
|||
|
||||
* [Mastodon](https://joinmastodon.org/apps) ([App Store](https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974))
|
||||
* [Stella*](https://www.stella-app.net/) ([App Store](https://apps.apple.com/us/app/stella-for-mastodon-twitter/id921372048))
|
||||
* [Tooot](https://github.com/tooot-app) ([App Store](https://apps.apple.com/app/id1549772269)
|
||||
* [Tooot](https://github.com/tooot-app) ([App Store](https://apps.apple.com/app/id1549772269))
|
||||
* [TwidereX](https://github.com/TwidereProject/TwidereX-iOS) ([App Store](https://apps.apple.com/app/twidere-x/id1530314034))
|
||||
|
||||
#### Linux
|
||||
|
@ -211,7 +211,7 @@ The available features are client specific and may differ.
|
|||
#### Windows
|
||||
|
||||
* [TheDesk](https://thedesk.top/en/) ([GitHub](https://github.com/cutls/TheDesk))
|
||||
* [Whalebird](https://whalebird.social/en/desktop/contents) ([Website Download](https://whalebird.social/en/desktop/contents/downloads#windows), [GitHub](https://github.com/h3poteto/whalebird-desktop))
|
||||
* [Whalebird](https://whalebird.social/en/desktop/contents) ([Microsoft Store](https://apps.microsoft.com/detail/9nbw4csdv5hc), [GitHub](https://github.com/h3poteto/whalebird-desktop))
|
||||
|
||||
#### Web Frontend
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ For alternative server configurations (such as Nginx server and MariaDB database
|
|||
|
||||
### Optional
|
||||
|
||||
* PHP ImageMagick extension (php-imagick) for animated GIF support.
|
||||
* PHP ImageMagick extension (php-imagick) for animated GIF and animated WebP support.
|
||||
|
||||
## Installation procedure
|
||||
|
||||
|
|
|
@ -6,17 +6,18 @@ Contact relations
|
|||
Fields
|
||||
------
|
||||
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| --------------------- | -------------------------------------------------------- | ----------------- | ---- | --- | ------------------- | ----- |
|
||||
| cid | contact the related contact had interacted with | int unsigned | NO | PRI | 0 | |
|
||||
| relation-cid | related contact who had interacted with the contact | int unsigned | NO | PRI | 0 | |
|
||||
| last-interaction | Date of the last interaction by relation-cid on cid | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||
| follow-updated | Date of the last update of the contact relationship | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||
| follows | if true, relation-cid follows cid | boolean | NO | | 0 | |
|
||||
| score | score for interactions of cid on relation-cid | smallint unsigned | YES | | NULL | |
|
||||
| relation-score | score for interactions of relation-cid on cid | smallint unsigned | YES | | NULL | |
|
||||
| thread-score | score for interactions of cid on threads of relation-cid | smallint unsigned | YES | | NULL | |
|
||||
| relation-thread-score | score for interactions of relation-cid on threads of cid | smallint unsigned | YES | | NULL | |
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| --------------------- | ----------------------------------------------------------------------- | ----------------- | ---- | --- | ------------------- | ----- |
|
||||
| cid | contact the related contact had interacted with | int unsigned | NO | PRI | 0 | |
|
||||
| relation-cid | related contact who had interacted with the contact | int unsigned | NO | PRI | 0 | |
|
||||
| last-interaction | Date of the last interaction by relation-cid on cid | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||
| follow-updated | Date of the last update of the contact relationship | datetime | NO | | 0001-01-01 00:00:00 | |
|
||||
| follows | if true, relation-cid follows cid | boolean | NO | | 0 | |
|
||||
| score | score for interactions of cid on relation-cid | smallint unsigned | YES | | NULL | |
|
||||
| relation-score | score for interactions of relation-cid on cid | smallint unsigned | YES | | NULL | |
|
||||
| thread-score | score for interactions of cid on threads of relation-cid | smallint unsigned | YES | | NULL | |
|
||||
| relation-thread-score | score for interactions of relation-cid on threads of cid | smallint unsigned | YES | | NULL | |
|
||||
| post-score | score for the amount of posts from cid that can be seen by relation-cid | smallint unsigned | YES | | NULL | |
|
||||
|
||||
Indexes
|
||||
------------
|
||||
|
|
|
@ -11,11 +11,12 @@ Fields
|
|||
| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | |
|
||||
| owner-id | Item owner | int unsigned | NO | | 0 | |
|
||||
| contact-type | Person, organisation, news, community, relay | tinyint | NO | | 0 | |
|
||||
| media-type | Type of media in a bit array (1 = image, 2 = video, 4 = audio | tinyint | NO | | 0 | |
|
||||
| media-type | Type of media in a bit array (1 = image, 2 = video, 4 = audio) | tinyint | NO | | 0 | |
|
||||
| language | Language information about this post in the ISO 639-1 format | char(2) | YES | | NULL | |
|
||||
| searchtext | Simplified text for the full text search | mediumtext | YES | | NULL | |
|
||||
| size | Body size | int unsigned | YES | | NULL | |
|
||||
| created | | datetime | YES | | NULL | |
|
||||
| network | | char(4) | YES | | NULL | |
|
||||
| restricted | If true, this post is either unlisted or not from a federated network | boolean | NO | | 0 | |
|
||||
| comments | Number of comments | mediumint unsigned | YES | | NULL | |
|
||||
| activities | Number of activities (like, dislike, ...) | mediumint unsigned | YES | | NULL | |
|
||||
|
|
|
@ -10,7 +10,7 @@ Fields
|
|||
| ---------- | --------------------------------------------------------------------- | ------------ | ---- | --- | ------- | ----- |
|
||||
| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | PRI | NULL | |
|
||||
| owner-id | Item owner | int unsigned | NO | | 0 | |
|
||||
| media-type | Type of media in a bit array (1 = image, 2 = video, 4 = audio | tinyint | NO | | 0 | |
|
||||
| media-type | Type of media in a bit array (1 = image, 2 = video, 4 = audio) | tinyint | NO | | 0 | |
|
||||
| language | Language information about this post in the ISO 639-1 format | char(2) | YES | | NULL | |
|
||||
| searchtext | Simplified text for the full text search | mediumtext | YES | | NULL | |
|
||||
| size | Body size | int unsigned | YES | | NULL | |
|
||||
|
|
|
@ -25,6 +25,7 @@ Fields
|
|||
| post-reason | Reason why the post arrived at the user | tinyint unsigned | NO | | 0 | |
|
||||
| vid | Id of the verb table entry that contains the activity verbs | smallint unsigned | YES | | NULL | |
|
||||
| private | 0=public, 1=private, 2=unlisted | tinyint unsigned | NO | | 0 | |
|
||||
| restrictions | Bit array of post restrictions (1 = Reply, 2 = Like, 4 = Announce) | tinyint unsigned | YES | | NULL | |
|
||||
| global | | boolean | NO | | 0 | |
|
||||
| visible | | boolean | NO | | 0 | |
|
||||
| deleted | item has been marked for deletion | boolean | NO | | 0 | |
|
||||
|
|
|
@ -6,29 +6,30 @@ User specific public contact data
|
|||
Fields
|
||||
------
|
||||
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ------------------------- | ----------------------------------------------------------------------- | ------------------ | ---- | --- | ------- | ----- |
|
||||
| cid | Contact id of the linked public contact | int unsigned | NO | PRI | 0 | |
|
||||
| uid | User id | mediumint unsigned | NO | PRI | 0 | |
|
||||
| uri-id | Id of the item-uri table entry that contains the contact url | int unsigned | YES | | NULL | |
|
||||
| blocked | Contact is completely blocked for this user | boolean | YES | | NULL | |
|
||||
| ignored | Posts from this contact are ignored | boolean | YES | | NULL | |
|
||||
| collapsed | Posts from this contact are collapsed | boolean | YES | | NULL | |
|
||||
| hidden | This contact is hidden from the others | boolean | YES | | NULL | |
|
||||
| is-blocked | User is blocked by this contact | boolean | YES | | NULL | |
|
||||
| channel-frequency | Controls the frequency of the appearance of this contact in channels | tinyint unsigned | YES | | NULL | |
|
||||
| pending | | boolean | YES | | NULL | |
|
||||
| rel | The kind of the relation between the user and the contact | tinyint unsigned | YES | | NULL | |
|
||||
| info | | mediumtext | YES | | NULL | |
|
||||
| notify_new_posts | | boolean | YES | | NULL | |
|
||||
| remote_self | 0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare | tinyint unsigned | YES | | NULL | |
|
||||
| fetch_further_information | 0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both | tinyint unsigned | YES | | NULL | |
|
||||
| ffi_keyword_denylist | | text | YES | | NULL | |
|
||||
| subhub | | boolean | YES | | NULL | |
|
||||
| hub-verify | | varbinary(383) | YES | | NULL | |
|
||||
| protocol | Protocol of the contact | char(4) | YES | | NULL | |
|
||||
| rating | Automatically detected feed poll frequency | tinyint | YES | | NULL | |
|
||||
| priority | Feed poll priority | tinyint unsigned | YES | | NULL | |
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ------------------------- | -------------------------------------------------------------------------- | ------------------ | ---- | --- | ------- | ----- |
|
||||
| cid | Contact id of the linked public contact | int unsigned | NO | PRI | 0 | |
|
||||
| uid | User id | mediumint unsigned | NO | PRI | 0 | |
|
||||
| uri-id | Id of the item-uri table entry that contains the contact url | int unsigned | YES | | NULL | |
|
||||
| blocked | Contact is completely blocked for this user | boolean | YES | | NULL | |
|
||||
| ignored | Posts from this contact are ignored | boolean | YES | | NULL | |
|
||||
| collapsed | Posts from this contact are collapsed | boolean | YES | | NULL | |
|
||||
| hidden | This contact is hidden from the others | boolean | YES | | NULL | |
|
||||
| channel-only | This contact is displayed only in channels, but not in the network stream. | boolean | YES | | NULL | |
|
||||
| is-blocked | User is blocked by this contact | boolean | YES | | NULL | |
|
||||
| channel-frequency | Controls the frequency of the appearance of this contact in channels | tinyint unsigned | YES | | NULL | |
|
||||
| pending | | boolean | YES | | NULL | |
|
||||
| rel | The kind of the relation between the user and the contact | tinyint unsigned | YES | | NULL | |
|
||||
| info | | mediumtext | YES | | NULL | |
|
||||
| notify_new_posts | | boolean | YES | | NULL | |
|
||||
| remote_self | 0 => No mirroring, 1-2 => Mirror as own post, 3 => Mirror as reshare | tinyint unsigned | YES | | NULL | |
|
||||
| fetch_further_information | 0 => None, 1 => Fetch information, 3 => Fetch keywords, 2 => Fetch both | tinyint unsigned | YES | | NULL | |
|
||||
| ffi_keyword_denylist | | text | YES | | NULL | |
|
||||
| subhub | | boolean | YES | | NULL | |
|
||||
| hub-verify | | varbinary(383) | YES | | NULL | |
|
||||
| protocol | Protocol of the contact | char(4) | YES | | NULL | |
|
||||
| rating | Automatically detected feed poll frequency | tinyint | YES | | NULL | |
|
||||
| priority | Feed poll priority | tinyint unsigned | YES | | NULL | |
|
||||
|
||||
Indexes
|
||||
------------
|
||||
|
|
151
doc/themes.md
151
doc/themes.md
|
@ -2,153 +2,10 @@
|
|||
|
||||
* [Home](help)
|
||||
|
||||
To change the look of friendica you have to touch the themes.
|
||||
The current default theme is [Vier](https://github.com/friendica/friendica/tree/stable/view/theme/vier) but there are numerous others.
|
||||
Have a look at [github.com/bkil/friendica-themes](https://github.com/bkil/friendica-themes) for an overview of the existing themes.
|
||||
In case none of them suits your needs, there are several ways to change a theme.
|
||||
The default Theme in Friendica is called [frio](https://github.com/friendica/friendica/tree/stable/view/theme/frio).
|
||||
|
||||
So, how to work on the UI of friendica.
|
||||
Open `Settings > Display > Custom Theme Settings` adjust the Theme to your liking. Select your preferred Appearance - light, dark or black - and your favorite Accent color. Click `Submit` to save your changes.
|
||||
|
||||
You can either directly edit an existing theme.
|
||||
But you might loose your changes when the theme is updated by the friendica team.
|
||||
The `Custom` Appearance allows to tweak the themes CSS and set colors for UI elements. So called `schemestrings` can be shared between users.
|
||||
|
||||
If you are almost happy with an existing theme, the easiest way to cover your needs is to create a new theme, inheriting most of the properties of the parent theme and change just minor stuff.
|
||||
The below for a more detailed description of theme heritage.
|
||||
|
||||
Some themes also allow users to select *variants* of the theme.
|
||||
Those theme variants most often contain an additional [CSS](https://en.wikipedia.org/wiki/CSS) file to override some styling of the default theme values.
|
||||
From the themes in the main repository *vier* and *vier* are using this methods for variations.
|
||||
Quattro is using a slightly different approach.
|
||||
|
||||
Third you can start your theme from scratch.
|
||||
Which is the most complex way to change friendicas look.
|
||||
But it leaves you the most freedom.
|
||||
So below for a *detailed* description and the meaning of some special files.
|
||||
|
||||
### Styling
|
||||
|
||||
If you want to change the styling of a theme, have a look at the themes CSS file.
|
||||
In most cases, you can found these in
|
||||
|
||||
/view/theme/**your-theme-name**/style.css
|
||||
|
||||
sometimes, there is also a file called style.php in the theme directory.
|
||||
This is only needed if the theme allows the user to change certain things of the theme dynamically.
|
||||
Say the font size or set a background image.
|
||||
|
||||
### Templates
|
||||
|
||||
If you want to change the structure of the theme, you need to change the templates used by the theme.
|
||||
Friendica themes are using [SMARTY3](http://www.smarty.net/) for templating.
|
||||
The default template can be found in
|
||||
|
||||
/view/templates
|
||||
|
||||
if you want to override any template within your theme create your version of the template in
|
||||
|
||||
/view/theme/**your-theme-name**/templates
|
||||
|
||||
any template that exists there will be used instead of the default one.
|
||||
|
||||
### JavaScript
|
||||
|
||||
The same rule applies to the JavaScript files found in
|
||||
|
||||
/js
|
||||
|
||||
they will be overwritten by files in
|
||||
|
||||
/view/theme/**your-theme-name**/js.
|
||||
|
||||
## Creating a Theme from Scratch
|
||||
|
||||
Keep patient.
|
||||
Basically what you have to do is identify which template you have to change so it looks more like what you want.
|
||||
Adopt the CSS of the theme accordingly.
|
||||
And iterate the process until you have the theme the way you want it.
|
||||
|
||||
*Use the source Luke.* and don't hesitate to ask in @[developers](https://forum.friendi.ca/profile/developers) or @[helpers](https://forum.friendi.ca/profile/helpers).
|
||||
|
||||
## Special Files
|
||||
|
||||
### unsupported
|
||||
|
||||
If a file with this name (which might be empty) exists in the theme directory, the theme is marked as *unsupported*.
|
||||
An unsupported theme may not be selected by a user in the settings.
|
||||
Users who are already using it wont notice anything.
|
||||
|
||||
### README(.md)
|
||||
|
||||
The contents of this file, with or without the .md which indicates [Markdown](https://daringfireball.net/projects/markdown/) syntax, will be displayed at most repository hosting services and in the theme page within the admin panel of friendica.
|
||||
|
||||
This file should contain information you want to let others know about your theme.
|
||||
|
||||
### screenshot.[png|jpg]
|
||||
|
||||
If you want to have a preview image of your theme displayed in the settings you should take a screenshot and save it with this name.
|
||||
Supported formats are PNG and JPEG.
|
||||
|
||||
### theme.php
|
||||
|
||||
This is the main definition file of the theme.
|
||||
In the header of that file, some meta information is stored.
|
||||
For example, have a look at the theme.php of the *vier* theme:
|
||||
|
||||
<?php
|
||||
/**
|
||||
* [Licence]
|
||||
*
|
||||
* Name: Vier
|
||||
* Version: 1.2
|
||||
* Author: Fabio <http://kirgroup.com/profile/fabrixxm>
|
||||
* Author: Ike <http://pirati.ca/profile/heluecht>
|
||||
* Author: Beanow <https://fc.oscp.info/profile/beanow>
|
||||
* Maintainer: Ike <http://pirati.ca/profile/heluecht>
|
||||
* Description: "Vier" is a very compact and modern theme. It uses the font awesome font library: http://fortawesome.github.com/Font-Awesome/
|
||||
*/
|
||||
|
||||
You see the definition of the theme's name, it's version and the initial author of the theme.
|
||||
These three pieces of information should be listed.
|
||||
If the original author is no longer working on the theme, but a maintainer has taken over, the maintainer should be listed as well.
|
||||
The information from the theme header will be displayed in the admin panel.
|
||||
|
||||
The first thing in file is to import the `App` class from `\Friendica\` namespace.
|
||||
|
||||
use Friendica\App;
|
||||
|
||||
This will make our job a little easier, as we don't have to specify the full name every time we need to use the `App` class.
|
||||
|
||||
The next crucial part of the theme.php file is a definition of an init function.
|
||||
The name of the function is <theme-name>_init.
|
||||
So in the case of vier it is
|
||||
|
||||
function vier_init(App $a) {
|
||||
$a->theme_info = array();
|
||||
$a->set_template_engine('smarty3');
|
||||
}
|
||||
|
||||
Here we have set the basic theme information, in this case they are empty.
|
||||
But the array needs to be set.
|
||||
And we have set the template engine that should be used by friendica for this theme.
|
||||
At the moment you should use the *smarty3* engine.
|
||||
There once was a friendica specific templating engine as well but that is not used anymore.
|
||||
If you like to use another templating engine, please implement it.
|
||||
|
||||
If you want to add something to the HTML header of the theme, one way to do so is by adding it to the theme.php file.
|
||||
To do so, add something alike
|
||||
|
||||
DI::page()['htmlhead'] .= <<< EOT
|
||||
/* stuff you want to add to the header */
|
||||
EOT;
|
||||
|
||||
So you can access the properties of this friendica session from the theme.php file as well.
|
||||
|
||||
### default.php
|
||||
|
||||
This file covers the structure of the underlying HTML layout.
|
||||
The default file is in
|
||||
|
||||
/view/default.php
|
||||
|
||||
if you want to change it, say adding a 4th column for banners of your favourite FLOSS projects, place a new default.php file in your theme directory.
|
||||
As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed.
|
||||
In the `General Theme Settings` you can also find the [vier](https://github.com/friendica/friendica/tree/stable/view/theme/vier) Theme, which precedes frio and is no longer officially maintained.
|
||||
|
|
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 5.0 KiB Po Szerokość: | Wysokość: | Rozmiar: 7.8 KiB |
|
@ -278,7 +278,7 @@ function item_process(array $post, array $request, bool $preview, string $return
|
|||
$post['quote-uri-id'] = Item::getQuoteUriId($post['body'], $post['uid']);
|
||||
$post['body'] = BBCode::removeSharedData(Item::setHashtags($post['body']));
|
||||
$post['writable'] = true;
|
||||
$post['sensitive'] = true;
|
||||
$post['sensitive'] = false;
|
||||
|
||||
$o = DI::conversation()->render([$post], Conversation::MODE_SEARCH, false, true);
|
||||
|
||||
|
|
|
@ -132,8 +132,6 @@ function photos_post(App $a)
|
|||
throw new HTTPException\NotFoundException(DI::l10n()->t('User not found.'));
|
||||
}
|
||||
|
||||
$phototypes = Images::supportedTypes();
|
||||
|
||||
$can_post = false;
|
||||
$visitor = 0;
|
||||
|
||||
|
@ -337,7 +335,7 @@ function photos_post(App $a)
|
|||
|
||||
if (DBA::isResult($photos)) {
|
||||
$photo = $photos[0];
|
||||
$ext = $phototypes[$photo['type']];
|
||||
$ext = Images::getExtensionByMimeType($photo['type']);
|
||||
Photo::update(
|
||||
['desc' => $desc, 'album' => $albname, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_circle_allow, 'deny_cid' => $str_contact_deny, 'deny_gid' => $str_circle_deny],
|
||||
['resource-id' => $resource_id, 'uid' => $page_owner_uid]
|
||||
|
@ -590,8 +588,6 @@ function photos_content(App $a)
|
|||
|
||||
$profile = Profile::getByUID($user['uid']);
|
||||
|
||||
$phototypes = Images::supportedTypes();
|
||||
|
||||
$_SESSION['photo_return'] = DI::args()->getCommand();
|
||||
|
||||
// Parse arguments
|
||||
|
@ -844,7 +840,7 @@ function photos_content(App $a)
|
|||
foreach ($r as $rr) {
|
||||
$twist = !$twist;
|
||||
|
||||
$ext = $phototypes[$rr['type']];
|
||||
$ext = Images::getExtensionByMimeType($rr['type']);
|
||||
|
||||
$imgalt_e = $rr['filename'];
|
||||
$desc_e = $rr['desc'];
|
||||
|
@ -855,7 +851,7 @@ function photos_content(App $a)
|
|||
'link' => 'photos/' . $user['nickname'] . '/image/' . $rr['resource-id']
|
||||
. ($order_field === 'created' ? '?order=created' : ''),
|
||||
'title' => DI::l10n()->t('View Photo'),
|
||||
'src' => 'photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' . $ext,
|
||||
'src' => 'photo/' . $rr['resource-id'] . '-' . $rr['scale'] . $ext,
|
||||
'alt' => $imgalt_e,
|
||||
'desc' => $desc_e,
|
||||
'ext' => $ext,
|
||||
|
@ -1013,9 +1009,9 @@ function photos_content(App $a)
|
|||
}
|
||||
|
||||
$photo = [
|
||||
'href' => 'photo/' . $hires['resource-id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
|
||||
'href' => 'photo/' . $hires['resource-id'] . '-' . $hires['scale'] . Images::getExtensionByMimeType($hires['type']),
|
||||
'title' => DI::l10n()->t('View Full Size'),
|
||||
'src' => 'photo/' . $lores['resource-id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?_u=' . DateTimeFormat::utcNow('ymdhis'),
|
||||
'src' => 'photo/' . $lores['resource-id'] . '-' . $lores['scale'] . Images::getExtensionByMimeType($lores['type']) . '?_u=' . DateTimeFormat::utcNow('ymdhis'),
|
||||
'height' => $hires['height'],
|
||||
'width' => $hires['width'],
|
||||
'album' => $hires['album'],
|
||||
|
@ -1043,7 +1039,7 @@ function photos_content(App $a)
|
|||
$pager = new Pager(DI::l10n(), DI::args()->getQueryString());
|
||||
|
||||
$params = ['order' => ['id'], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
|
||||
$items = Post::toArray(Post::selectForUser($link_item['uid'], Item::ITEM_FIELDLIST, $condition, $params));
|
||||
$items = Post::toArray(Post::selectForUser($link_item['uid'], array_merge(Item::ITEM_FIELDLIST, ['author-alias']), $condition, $params));
|
||||
|
||||
if (DI::userSession()->getLocalUserId() == $link_item['uid']) {
|
||||
Item::update(['unseen' => false], ['parent' => $link_item['parent']]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Contact: mailto:info@friendi.ca
|
||||
|
||||
Expires: 2024-10-30T23:59:59Z
|
||||
Expires: 2025-01-30T23:59:59Z
|
||||
|
||||
Preferred-Languages: en
|
||||
|
||||
|
|
15
src/App.php
15
src/App.php
|
@ -43,6 +43,7 @@ use Friendica\Model\Contact;
|
|||
use Friendica\Model\Profile;
|
||||
use Friendica\Module\Special\HTTPException as ModuleHTTPException;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Protocol\ATProtocol\DID;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\HTTPInputData;
|
||||
use Friendica\Util\HTTPSignature;
|
||||
|
@ -64,7 +65,7 @@ class App
|
|||
{
|
||||
const PLATFORM = 'Friendica';
|
||||
const CODENAME = 'Yellow Archangel';
|
||||
const VERSION = '2024.03-dev';
|
||||
const VERSION = '2024.06-dev';
|
||||
|
||||
// Allow themes to control internal parameters
|
||||
// by changing App values in theme.php
|
||||
|
@ -565,8 +566,8 @@ class App
|
|||
*/
|
||||
public function runFrontend(App\Router $router, IManagePersonalConfigValues $pconfig, Authentication $auth, App\Page $page, Nav $nav, ModuleHTTPException $httpException, HTTPInputData $httpInput, float $start_time, array $server)
|
||||
{
|
||||
$requeststring = ($_SERVER['REQUEST_METHOD'] ?? '') . ' ' . ($_SERVER['REQUEST_URI'] ?? '') . ' ' . ($_SERVER['SERVER_PROTOCOL'] ?? '');
|
||||
$this->logger->debug('Request received', ['address' => $_SERVER['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $_SERVER['HTTP_REFERER'] ?? '', 'user-agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']);
|
||||
$requeststring = ($server['REQUEST_METHOD'] ?? '') . ' ' . ($server['REQUEST_URI'] ?? '') . ' ' . ($server['SERVER_PROTOCOL'] ?? '');
|
||||
$this->logger->debug('Request received', ['address' => $server['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $server['HTTP_REFERER'] ?? '', 'user-agent' => $server['HTTP_USER_AGENT'] ?? '']);
|
||||
$request_start = microtime(true);
|
||||
|
||||
$this->profiler->set($start_time, 'start');
|
||||
|
@ -593,8 +594,10 @@ class App
|
|||
Core\Hook::callAll('init_1');
|
||||
}
|
||||
|
||||
DID::routeRequest($this->args->getCommand(), $server);
|
||||
|
||||
if ($this->mode->isNormal() && !$this->mode->isBackend()) {
|
||||
$requester = HTTPSignature::getSigner('', $_SERVER);
|
||||
$requester = HTTPSignature::getSigner('', $server);
|
||||
if (!empty($requester)) {
|
||||
Profile::addVisitorCookieForHandle($requester);
|
||||
}
|
||||
|
@ -716,10 +719,10 @@ class App
|
|||
$response = $page->run($this, $this->baseURL, $this->args, $this->mode, $response, $this->l10n, $this->profiler, $this->config, $pconfig, $nav, $this->session->getLocalUserId());
|
||||
}
|
||||
|
||||
$this->logger->debug('Request processed sucessfully', ['response' => $response->getStatusCode(), 'address' => $_SERVER['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $_SERVER['HTTP_REFERER'] ?? '', 'user-agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'duration' => number_format(microtime(true) - $request_start, 3)]);
|
||||
$this->logger->debug('Request processed sucessfully', ['response' => $response->getStatusCode(), 'address' => $server['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $server['HTTP_REFERER'] ?? '', 'user-agent' => $server['HTTP_USER_AGENT'] ?? '', 'duration' => number_format(microtime(true) - $request_start, 3)]);
|
||||
System::echoResponse($response);
|
||||
} catch (HTTPException $e) {
|
||||
$this->logger->debug('Request processed with exception', ['response' => $e->getCode(), 'address' => $_SERVER['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $_SERVER['HTTP_REFERER'] ?? '', 'user-agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'duration' => number_format(microtime(true) - $request_start, 3)]);
|
||||
$this->logger->debug('Request processed with exception', ['response' => $e->getCode(), 'address' => $server['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $server['HTTP_REFERER'] ?? '', 'user-agent' => $server['HTTP_USER_AGENT'] ?? '', 'duration' => number_format(microtime(true) - $request_start, 3)]);
|
||||
$httpException->rawContent($e);
|
||||
}
|
||||
$page->logRuntime($this->config, 'runFrontend');
|
||||
|
|
|
@ -150,7 +150,7 @@ HELP;
|
|||
|
||||
if ($valid) {
|
||||
$this->out('3', false);
|
||||
$image = new Image($imgdata, Images::getMimeTypeByData($imgdata));
|
||||
$image = new Image($imgdata);
|
||||
if (!$image->isValid()) {
|
||||
$this->out(' ' . $this->l10n->t('invalid image for id %s', $resourceid) . ' ', false);
|
||||
$valid = false;
|
||||
|
|
|
@ -80,13 +80,18 @@ class Avatar
|
|||
return $fields;
|
||||
}
|
||||
|
||||
if (!$fetchResult->isSuccess()) {
|
||||
Logger::debug('Fetching was unsuccessful', ['avatar' => $avatar]);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$img_str = $fetchResult->getBodyString();
|
||||
if (empty($img_str)) {
|
||||
Logger::debug('Avatar is invalid', ['avatar' => $avatar]);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$image = new Image($img_str, Images::getMimeTypeByData($img_str));
|
||||
$image = new Image($img_str, $fetchResult->getContentType(), $avatar);
|
||||
if (!$image->isValid()) {
|
||||
Logger::debug('Avatar picture is invalid', ['avatar' => $avatar]);
|
||||
return $fields;
|
||||
|
@ -145,7 +150,7 @@ class Avatar
|
|||
return '';
|
||||
}
|
||||
|
||||
$path = $filename . $size . '.' . $image->getExt();
|
||||
$path = $filename . $size . $image->getExt();
|
||||
|
||||
$basepath = self::basePath();
|
||||
if (empty($basepath)) {
|
||||
|
|
|
@ -28,6 +28,7 @@ class Channel extends Timeline
|
|||
const DISCOVER = 'discover';
|
||||
const FOLLOWERS = 'followers';
|
||||
const SHARERSOFSHARERS = 'sharersofsharers';
|
||||
const QUIETSHARERS = 'quietsharers';
|
||||
const IMAGE = 'image';
|
||||
const VIDEO = 'video';
|
||||
const AUDIO = 'audio';
|
||||
|
|
|
@ -45,6 +45,7 @@ final class Channel extends Timeline
|
|||
new ChannelEntity(ChannelEntity::LANGUAGE, $native, $this->l10n->t('Posts in %s', $native), 'g'),
|
||||
new ChannelEntity(ChannelEntity::FOLLOWERS, $this->l10n->t('Followers'), $this->l10n->t('Posts from your followers that you don\'t follow'), 'f'),
|
||||
new ChannelEntity(ChannelEntity::SHARERSOFSHARERS, $this->l10n->t('Sharers of sharers'), $this->l10n->t('Posts from accounts that are followed by accounts that you follow'), 'r'),
|
||||
new ChannelEntity(ChannelEntity::QUIETSHARERS, $this->l10n->t('Quiet sharers'), $this->l10n->t('Posts from accounts that you follow but who don\'t post very often'), 'q'),
|
||||
new ChannelEntity(ChannelEntity::IMAGE, $this->l10n->t('Images'), $this->l10n->t('Posts with images'), 'i'),
|
||||
new ChannelEntity(ChannelEntity::AUDIO, $this->l10n->t('Audio'), $this->l10n->t('Posts with audio'), 'd'),
|
||||
new ChannelEntity(ChannelEntity::VIDEO, $this->l10n->t('Videos'), $this->l10n->t('Posts with videos'), 'v'),
|
||||
|
@ -55,6 +56,6 @@ final class Channel extends Timeline
|
|||
|
||||
public function isTimeline(string $selectedTab): bool
|
||||
{
|
||||
return in_array($selectedTab, [ChannelEntity::WHATSHOT, ChannelEntity::FORYOU, ChannelEntity::DISCOVER, ChannelEntity::FOLLOWERS, ChannelEntity::SHARERSOFSHARERS, ChannelEntity::IMAGE, ChannelEntity::VIDEO, ChannelEntity::AUDIO, ChannelEntity::LANGUAGE]);
|
||||
return in_array($selectedTab, [ChannelEntity::WHATSHOT, ChannelEntity::FORYOU, ChannelEntity::DISCOVER, ChannelEntity::FOLLOWERS, ChannelEntity::SHARERSOFSHARERS, ChannelEntity::QUIETSHARERS, ChannelEntity::IMAGE, ChannelEntity::VIDEO, ChannelEntity::AUDIO, ChannelEntity::LANGUAGE]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -695,7 +695,7 @@ class Item
|
|||
$item['body'] = Post\Media::addAttachmentsToBody($item['uri-id'], $item['body']);
|
||||
}
|
||||
|
||||
$shared_content = BBCode::getShareOpeningTag($item['author-name'], $item['author-link'], $item['author-avatar'], $item['plink'], $item['created'], $item['guid'], $item['uri']);
|
||||
$shared_content = BBCode::getShareOpeningTag($item['author-name'], $item['author-link'], $item['author-avatar'], $item['plink'] ?? $item['uri'], $item['created'], $item['guid'], $item['uri']);
|
||||
|
||||
if (!empty($item['title'])) {
|
||||
$shared_content .= '[h3]' . $item['title'] . "[/h3]\n";
|
||||
|
@ -1105,4 +1105,35 @@ class Item
|
|||
Tag::store($toUriId, $receiver['type'], $receiver['name'], $receiver['url']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the item is too old
|
||||
*
|
||||
* @param string $created
|
||||
* @param integer $uid
|
||||
* @return boolean item is too old
|
||||
*/
|
||||
public function isTooOld(string $created, int $uid = 0): bool
|
||||
{
|
||||
// check for create date and expire time
|
||||
$expire_interval = DI::config()->get('system', 'dbclean-expire-days', 0);
|
||||
|
||||
if ($uid) {
|
||||
$user = DBA::selectFirst('user', ['expire'], ['uid' => $uid]);
|
||||
if (DBA::isResult($user) && ($user['expire'] > 0) && (($user['expire'] < $expire_interval) || ($expire_interval == 0))) {
|
||||
$expire_interval = $user['expire'];
|
||||
}
|
||||
}
|
||||
|
||||
if (($expire_interval > 0) && !empty($created)) {
|
||||
$expire_date = time() - ($expire_interval * 86400);
|
||||
$created_date = strtotime($created);
|
||||
if ($created_date < $expire_date) {
|
||||
Logger::notice('Item created before expiration interval.', ['created' => date('c', $created_date), 'expired' => date('c', $expire_date)]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ class Nav
|
|||
$nav['home'] = [$homelink, $this->l10n->t('Home'), '', $this->l10n->t('Home Page')];
|
||||
}
|
||||
|
||||
if (intval($this->config->get('config', 'register_policy')) === \Friendica\Module\Register::OPEN && !$this->session->isAuthenticated()) {
|
||||
if (\Friendica\Module\Register::getPolicy() === \Friendica\Module\Register::OPEN && !$this->session->isAuthenticated()) {
|
||||
$nav['register'] = ['register', $this->l10n->t('Register'), '', $this->l10n->t('Create an account')];
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,9 @@
|
|||
namespace Friendica\Content;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMNode;
|
||||
use DOMText;
|
||||
use DOMXPath;
|
||||
use Exception;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Core\Cache\Enum\Duration;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\Renderer;
|
||||
|
@ -49,32 +48,15 @@ use Friendica\Util\Strings;
|
|||
*/
|
||||
class OEmbed
|
||||
{
|
||||
/**
|
||||
* Callback for fetching URL, checking allowance and returning formatted HTML
|
||||
*
|
||||
* @param array $matches
|
||||
* @return string Formatted HTML
|
||||
*/
|
||||
public static function replaceCallback(array $matches): string
|
||||
{
|
||||
$embedurl = $matches[1];
|
||||
$j = self::fetchURL($embedurl, !self::isAllowedURL($embedurl));
|
||||
$s = self::formatObject($j);
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data from an URL to embed its content.
|
||||
*
|
||||
* @param string $embedurl The URL from which the data should be fetched.
|
||||
* @param bool $no_rich_type If set to true rich type content won't be fetched.
|
||||
* @param bool $use_parseurl Use the "ParseUrl" functionality to add additional data
|
||||
* @param string $embedurl The URL from which the data should be fetched.
|
||||
*
|
||||
* @return \Friendica\Object\OEmbed
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
public static function fetchURL(string $embedurl, bool $no_rich_type = false, bool $use_parseurl = true): \Friendica\Object\OEmbed
|
||||
private static function fetchURL(string $embedurl): \Friendica\Object\OEmbed
|
||||
{
|
||||
$embedurl = trim($embedurl, '\'"');
|
||||
|
||||
|
@ -119,7 +101,7 @@ class OEmbed
|
|||
$href = str_replace(['http://www.youtube.com/', 'http://player.vimeo.com/'],
|
||||
['https://www.youtube.com/', 'https://player.vimeo.com/'], $href);
|
||||
$result = DI::httpClient()->fetchFull($href . '&maxwidth=' . $a->getThemeInfoValue('videowidth'));
|
||||
if ($result->getReturnCode() === 200) {
|
||||
if ($result->isSuccess()) {
|
||||
$json_string = $result->getBodyString();
|
||||
break;
|
||||
}
|
||||
|
@ -157,57 +139,55 @@ class OEmbed
|
|||
}
|
||||
|
||||
// Improve the OEmbed data with data from OpenGraph, Twitter cards and other sources
|
||||
if ($use_parseurl) {
|
||||
$data = ParseUrl::getSiteinfoCached($embedurl, false);
|
||||
$data = ParseUrl::getSiteinfoCached($embedurl);
|
||||
|
||||
if (($oembed->type == 'error') && empty($data['title']) && empty($data['text'])) {
|
||||
return $oembed;
|
||||
}
|
||||
if (($oembed->type == 'error') && empty($data['title']) && empty($data['text'])) {
|
||||
return $oembed;
|
||||
}
|
||||
|
||||
if ($no_rich_type || ($oembed->type == 'error')) {
|
||||
$oembed->html = '';
|
||||
$oembed->type = $data['type'];
|
||||
if (!self::isAllowedURL($embedurl) || ($oembed->type == 'error')) {
|
||||
$oembed->html = '';
|
||||
$oembed->type = $data['type'];
|
||||
|
||||
if ($oembed->type == 'photo') {
|
||||
if (!empty($data['images'])) {
|
||||
$oembed->url = $data['images'][0]['src'];
|
||||
$oembed->width = $data['images'][0]['width'];
|
||||
$oembed->height = $data['images'][0]['height'];
|
||||
} else {
|
||||
$oembed->type = 'link';
|
||||
}
|
||||
if ($oembed->type == 'photo') {
|
||||
if (!empty($data['images'])) {
|
||||
$oembed->url = $data['images'][0]['src'];
|
||||
$oembed->width = $data['images'][0]['width'];
|
||||
$oembed->height = $data['images'][0]['height'];
|
||||
} else {
|
||||
$oembed->type = 'link';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['title'])) {
|
||||
$oembed->title = $data['title'];
|
||||
}
|
||||
if (!empty($data['title'])) {
|
||||
$oembed->title = $data['title'];
|
||||
}
|
||||
|
||||
if (!empty($data['text'])) {
|
||||
$oembed->description = $data['text'];
|
||||
}
|
||||
if (!empty($data['text'])) {
|
||||
$oembed->description = $data['text'];
|
||||
}
|
||||
|
||||
if (!empty($data['publisher_name'])) {
|
||||
$oembed->provider_name = $data['publisher_name'];
|
||||
}
|
||||
if (!empty($data['publisher_name'])) {
|
||||
$oembed->provider_name = $data['publisher_name'];
|
||||
}
|
||||
|
||||
if (!empty($data['publisher_url'])) {
|
||||
$oembed->provider_url = $data['publisher_url'];
|
||||
}
|
||||
if (!empty($data['publisher_url'])) {
|
||||
$oembed->provider_url = $data['publisher_url'];
|
||||
}
|
||||
|
||||
if (!empty($data['author_name'])) {
|
||||
$oembed->author_name = $data['author_name'];
|
||||
}
|
||||
if (!empty($data['author_name'])) {
|
||||
$oembed->author_name = $data['author_name'];
|
||||
}
|
||||
|
||||
if (!empty($data['author_url'])) {
|
||||
$oembed->author_url = $data['author_url'];
|
||||
}
|
||||
if (!empty($data['author_url'])) {
|
||||
$oembed->author_url = $data['author_url'];
|
||||
}
|
||||
|
||||
if (!empty($data['images']) && ($oembed->type != 'photo')) {
|
||||
$oembed->thumbnail_url = $data['images'][0]['src'];
|
||||
$oembed->thumbnail_width = $data['images'][0]['width'];
|
||||
$oembed->thumbnail_height = $data['images'][0]['height'];
|
||||
}
|
||||
if (!empty($data['images']) && ($oembed->type != 'photo')) {
|
||||
$oembed->thumbnail_url = $data['images'][0]['src'];
|
||||
$oembed->thumbnail_width = $data['images'][0]['width'];
|
||||
$oembed->thumbnail_height = $data['images'][0]['height'];
|
||||
}
|
||||
|
||||
Hook::callAll('oembed_fetch_url', $embedurl, $oembed);
|
||||
|
@ -219,9 +199,10 @@ class OEmbed
|
|||
* Returns a formatted string from OEmbed object
|
||||
*
|
||||
* @param \Friendica\Object\OEmbed $oembed
|
||||
* @param int $uriid
|
||||
* @return string
|
||||
*/
|
||||
private static function formatObject(\Friendica\Object\OEmbed $oembed): string
|
||||
private static function formatObject(\Friendica\Object\OEmbed $oembed, int $uriid): string
|
||||
{
|
||||
$ret = '<div class="oembed ' . $oembed->type . '">';
|
||||
|
||||
|
@ -241,22 +222,22 @@ class OEmbed
|
|||
'$escapedhtml' => base64_encode($oembed->html),
|
||||
'$tw' => $tw,
|
||||
'$th' => $th,
|
||||
'$turl' => $oembed->thumbnail_url,
|
||||
'$turl' => BBCode::proxyUrl($oembed->thumbnail_url, BBCode::INTERNAL, $uriid, Proxy::SIZE_SMALL),
|
||||
]);
|
||||
} else {
|
||||
$ret = $oembed->html;
|
||||
$ret .= Proxy::proxifyHtml($oembed->html, $uriid);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'photo':
|
||||
$ret .= '<img width="' . $oembed->width . '" src="' . Proxy::proxifyUrl($oembed->url) . '">';
|
||||
$ret .= '<img width="' . $oembed->width . '" src="' . BBCode::proxyUrl($oembed->url, BBCode::INTERNAL, $uriid, Proxy::SIZE_MEDIUM) . '">';
|
||||
break;
|
||||
|
||||
case 'link':
|
||||
break;
|
||||
|
||||
case 'rich':
|
||||
$ret .= Proxy::proxifyHtml($oembed->html);
|
||||
$ret .= Proxy::proxifyHtml($oembed->html, $uriid);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -294,12 +275,21 @@ class OEmbed
|
|||
$ret .= '<a href="' . $oembed->embed_url . '" rel="oembed">' . $oembed->embed_url . '</a>';
|
||||
}
|
||||
$ret .= "</h4>";
|
||||
if ($oembed->type == 'link') {
|
||||
if (!empty($oembed->thumbnail_url)) {
|
||||
$ret .= '<img width="' . $oembed->width . '" src="' . BBCode::proxyUrl($oembed->thumbnail_url, BBCode::INTERNAL, $uriid, Proxy::SIZE_MEDIUM) . '">';
|
||||
}
|
||||
if (!empty($oembed->description)) {
|
||||
$ret .= '<p>' . $oembed->description . '</p>';
|
||||
}
|
||||
}
|
||||
} elseif (!strpos($oembed->html, $oembed->embed_url)) {
|
||||
// add <a> for html2bbcode conversion
|
||||
$ret .= '<a href="' . $oembed->embed_url . '" rel="oembed">' . $oembed->title . '</a>';
|
||||
}
|
||||
|
||||
$ret .= '</div>';
|
||||
$test = Proxy::proxifyHtml($ret, $uriid);
|
||||
|
||||
return str_replace("\n", "", $ret);
|
||||
}
|
||||
|
@ -308,51 +298,19 @@ class OEmbed
|
|||
* Converts BBCode to HTML code
|
||||
*
|
||||
* @param string $text
|
||||
* @param int $uriid
|
||||
* @return string
|
||||
*/
|
||||
public static function BBCode2HTML(string $text): string
|
||||
public static function BBCode2HTML(string $text, int $uriid): string
|
||||
{
|
||||
if (DI::config()->get('system', 'no_oembed')) {
|
||||
return preg_replace("/\[embed\](.+?)\[\/embed\]/is", "<!-- oembed $1 --><i>" . DI::l10n()->t('Embedding disabled') . " : $1</i><!-- /oembed $1 -->", $text);
|
||||
}
|
||||
return preg_replace_callback("/\[embed\](.+?)\[\/embed\]/is", [self::class, 'replaceCallback'], $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find <span class='oembed'>..<a href='url' rel='oembed'>..</a></span>
|
||||
* and replace it with [embed]url[/embed]
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function HTML2BBCode(string $text): string
|
||||
{
|
||||
// start parser only if 'oembed' is in text
|
||||
if (strpos($text, 'oembed')) {
|
||||
// convert non ascii chars to html entities
|
||||
$html_text = mb_convert_encoding($text, 'HTML-ENTITIES', mb_detect_encoding($text));
|
||||
|
||||
// If it doesn't parse at all, just return the text.
|
||||
$dom = new DOMDocument();
|
||||
if (!@$dom->loadHTML($html_text)) {
|
||||
return $text;
|
||||
}
|
||||
$xpath = new DOMXPath($dom);
|
||||
|
||||
$xattr = self::buildXPath('class', 'oembed');
|
||||
$entries = $xpath->query("//div[$xattr]");
|
||||
|
||||
$xattr = "@rel='oembed'"; //oe_build_xpath("rel","oembed");
|
||||
foreach ($entries as $e) {
|
||||
$href = $xpath->evaluate("a[$xattr]/@href", $e)->item(0)->nodeValue;
|
||||
if (!is_null($href)) {
|
||||
$e->parentNode->replaceChild(new DOMText('[embed]' . $href . '[/embed]'), $e);
|
||||
}
|
||||
}
|
||||
return self::getInnerHTML($dom->getElementsByTagName('body')->item(0));
|
||||
} else {
|
||||
if (!preg_match_all("/\[embed\](.+?)\[\/embed\]/is", $text, $matches, PREG_SET_ORDER)) {
|
||||
return $text;
|
||||
}
|
||||
foreach ($matches as $match) {
|
||||
$data = self::fetchURL($match[1]);
|
||||
$text = str_replace($match[0], self::formatObject($data, $uriid), $text);
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -373,26 +331,25 @@ class OEmbed
|
|||
return false;
|
||||
}
|
||||
|
||||
$str_allowed = DI::config()->get('system', 'allowed_oembed', '');
|
||||
if (empty($str_allowed)) {
|
||||
$allowed = DI::config()->get('system', 'allowed_oembed', '');
|
||||
if (empty($allowed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$allowed = explode(',', $str_allowed);
|
||||
|
||||
return Network::isDomainAllowed($domain, $allowed);
|
||||
return Network::isDomainMatch($domain, explode(',', $allowed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted HTML code from given URL and sets optional title
|
||||
*
|
||||
* @param string $url URL to fetch
|
||||
* @param string $title Optional title (default: what comes from OEmbed object)
|
||||
* @param string $title title (default: what comes from OEmbed object)
|
||||
* @param int $uriid
|
||||
* @return string Formatted HTML
|
||||
*/
|
||||
public static function getHTML(string $url, string $title = ''): string
|
||||
public static function getHTML(string $url, string $title, int $uriid): string
|
||||
{
|
||||
$o = self::fetchURL($url, !self::isAllowedURL($url));
|
||||
$o = self::fetchURL($url);
|
||||
|
||||
if (!is_object($o) || property_exists($o, 'type') && $o->type == 'error') {
|
||||
throw new Exception('OEmbed failed for URL: ' . $url);
|
||||
|
@ -402,74 +359,8 @@ class OEmbed
|
|||
$o->title = $title;
|
||||
}
|
||||
|
||||
$html = self::formatObject($o);
|
||||
$html = self::formatObject($o, $uriid);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the iframe HTML for an oembed attachment.
|
||||
*
|
||||
* Width and height are given by the remote, and are regularly too small for
|
||||
* the generated iframe.
|
||||
*
|
||||
* The width is entirely discarded for the actual width of the post, while fixed
|
||||
* height is used as a starting point before the inevitable resizing.
|
||||
*
|
||||
* Since the iframe is automatically resized on load, there are no need for ugly
|
||||
* and impractical scrollbars.
|
||||
*
|
||||
* @todo This function is currently unused until someone™ adds support for a separate OEmbed domain
|
||||
*
|
||||
* @param string $src Original remote URL to embed
|
||||
* @param string $width
|
||||
* @param string $height
|
||||
* @return string Formatted HTML
|
||||
*
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @see oembed_format_object()
|
||||
*/
|
||||
private static function iframe(string $src, string $width, string $height): string
|
||||
{
|
||||
if (!$height || strstr($height, '%')) {
|
||||
$height = '200';
|
||||
}
|
||||
$width = '100%';
|
||||
|
||||
$src = DI::baseUrl() . '/oembed/' . Strings::base64UrlEncode($src);
|
||||
return '<iframe onload="resizeIframe(this);" class="embed_rich" height="' . $height . '" width="' . $width . '" src="' . $src . '" allowfullscreen scrolling="no" frameborder="no">' . DI::l10n()->t('Embedded content') . '</iframe>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates attribute search XPath string
|
||||
*
|
||||
* Generates an XPath query to select elements whose provided attribute contains
|
||||
* the provided value in a space-separated list.
|
||||
*
|
||||
* @param string $attr Name of the attribute to search
|
||||
* @param string $value Value to search in a space-separated list
|
||||
* @return string
|
||||
*/
|
||||
private static function buildXPath(string $attr, $value): string
|
||||
{
|
||||
// https://www.westhoffswelt.de/blog/2009/6/9/select-html-elements-with-more-than-one-css-class-using-xpath
|
||||
return "contains(normalize-space(@$attr), ' $value ') or substring(normalize-space(@$attr), 1, string-length('$value') + 1) = '$value ' or substring(normalize-space(@$attr), string-length(@$attr) - string-length('$value')) = ' $value' or @$attr = '$value'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inner XML string of a provided DOMNode
|
||||
*
|
||||
* @param DOMNode $node
|
||||
* @return string
|
||||
*/
|
||||
private static function getInnerHTML(DOMNode $node): string
|
||||
{
|
||||
$innerHTML = '';
|
||||
$children = $node->childNodes;
|
||||
foreach ($children as $child) {
|
||||
$innerHTML .= $child->ownerDocument->saveXML($child);
|
||||
}
|
||||
return $innerHTML;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ use Friendica\Content\Post\Collection;
|
|||
use Friendica\Content\Post\Entity;
|
||||
use Friendica\Content\Post\Factory;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Util\Strings;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
|
@ -62,7 +63,7 @@ class PostMedia extends BaseRepository
|
|||
|
||||
public function selectByUriId(int $uriId): Collection\PostMedias
|
||||
{
|
||||
return $this->_select(['uri-id' => $uriId]);
|
||||
return $this->_select(["`uri-id` = ? AND `type` != ?", $uriId, Post\Media::UNKNOWN]);
|
||||
}
|
||||
|
||||
public function save(Entity\PostMedia $PostMedia): Entity\PostMedia
|
||||
|
|
|
@ -40,6 +40,7 @@ use Friendica\Model\Post;
|
|||
use Friendica\Model\Tag;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Util\Images;
|
||||
use Friendica\Util\Map;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\ParseUrl;
|
||||
|
@ -309,7 +310,7 @@ class BBCode
|
|||
return trim($text);
|
||||
}
|
||||
|
||||
private static function proxyUrl(string $image, int $simplehtml = self::INTERNAL, int $uriid = 0, string $size = ''): string
|
||||
public static function proxyUrl(string $image, int $simplehtml = self::INTERNAL, int $uriid = 0, string $size = ''): string
|
||||
{
|
||||
// Only send proxied pictures to API and for internal display
|
||||
if (!in_array($simplehtml, [self::INTERNAL, self::MASTODON_API, self::TWITTER_API])) {
|
||||
|
@ -452,7 +453,7 @@ class BBCode
|
|||
$return = '';
|
||||
try {
|
||||
if ($tryoembed && OEmbed::isAllowedURL($data['url'])) {
|
||||
$return = OEmbed::getHTML($data['url'], $data['title']);
|
||||
$return = OEmbed::getHTML($data['url'], $data['title'], $uriid);
|
||||
} else {
|
||||
throw new Exception('OEmbed is disabled for this attachment.');
|
||||
}
|
||||
|
@ -1027,12 +1028,12 @@ class BBCode
|
|||
if (is_null($text)) {
|
||||
$curlResult = DI::httpClient()->head($match[1], [HttpClientOptions::TIMEOUT => DI::config()->get('system', 'xrd_timeout')]);
|
||||
if ($curlResult->isSuccess()) {
|
||||
$mimetype = $curlResult->getHeader('Content-Type')[0] ?? '';
|
||||
$mimetype = $curlResult->getContentType() ?? '';
|
||||
} else {
|
||||
$mimetype = '';
|
||||
}
|
||||
|
||||
if (substr($mimetype, 0, 6) == 'image/') {
|
||||
if (Images::isSupportedMimeType($mimetype)) {
|
||||
$text = '[url=' . $match[1] . ']' . $match[1] . '[/url]';
|
||||
} else {
|
||||
$text = '[url=' . $match[2] . ']' . $match[2] . '[/url]';
|
||||
|
@ -1125,13 +1126,13 @@ class BBCode
|
|||
|
||||
$curlResult = DI::httpClient()->head($match[1], [HttpClientOptions::TIMEOUT => DI::config()->get('system', 'xrd_timeout')]);
|
||||
if ($curlResult->isSuccess()) {
|
||||
$mimetype = $curlResult->getHeader('Content-Type')[0] ?? '';
|
||||
$mimetype = $curlResult->getContentType() ?? '';
|
||||
} else {
|
||||
$mimetype = '';
|
||||
}
|
||||
|
||||
// if its a link to a picture then embed this picture
|
||||
if (substr($mimetype, 0, 6) == 'image/') {
|
||||
if (Images::isSupportedMimeType($mimetype)) {
|
||||
$text = '[img]' . $match[1] . '[/img]';
|
||||
} else {
|
||||
if (!empty($match[3])) {
|
||||
|
@ -1244,6 +1245,42 @@ class BBCode
|
|||
return $match[1] . '[url=' . $data['url'] . ']' . $data['nick'] . '[/url]';
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace mention links
|
||||
*
|
||||
* @param string $body HTML/BBCode
|
||||
* @return string Body with replaced mentions
|
||||
*/
|
||||
public static function setMentionsToAddr(string $body): string
|
||||
{
|
||||
DI::profiler()->startRecording('rendering');
|
||||
$regexp = "/([@!])\[url\=([^\[\]]*)\].*?\[\/url\]/ism";
|
||||
$body = preg_replace_callback($regexp, [self::class, 'mentionToAddrCallback'], $body);
|
||||
DI::profiler()->stopRecording();
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function to replace a Friendica style mention in a mention with the addr
|
||||
*
|
||||
* @param array $match Matching values for the callback
|
||||
* @return string Replaced mention or empty string
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function mentionToAddrCallback(array $match): string
|
||||
{
|
||||
if (empty($match[2])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$data = Contact::getByURL($match[2], false, ['url', 'nick', 'addr']);
|
||||
if (empty($data['nick'])) {
|
||||
return $match[0];
|
||||
}
|
||||
|
||||
return $match[1] . ($data['addr'] ?: $data['nick']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize links to Youtube and Vimeo to a unified format.
|
||||
*
|
||||
|
@ -1357,12 +1394,12 @@ class BBCode
|
|||
* $match[1] = $url
|
||||
* $match[2] = $title or absent
|
||||
*/
|
||||
$try_oembed_callback = function (array $match) {
|
||||
$try_oembed_callback = function (array $match) use ($uriid) {
|
||||
$url = $match[1];
|
||||
$title = $match[2] ?? '';
|
||||
|
||||
try {
|
||||
$return = OEmbed::getHTML($url, $title);
|
||||
$return = OEmbed::getHTML($url, $title, $uriid);
|
||||
} catch (Exception $ex) {
|
||||
$return = $match[0];
|
||||
}
|
||||
|
@ -1787,7 +1824,7 @@ class BBCode
|
|||
$text = self::normalizeVideoLinks($text);
|
||||
|
||||
// Youtube extensions
|
||||
if ($try_oembed) {
|
||||
if ($try_oembed && OEmbed::isAllowedURL('https://www.youtube.com/embed/')) {
|
||||
$text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->getThemeInfoValue('videowidth') . '" height="' . $a->getThemeInfoValue('videoheight') . '" src="https://www.youtube.com/embed/$1" frameborder="0" ></iframe>', $text);
|
||||
} else {
|
||||
$text = preg_replace(
|
||||
|
@ -1798,7 +1835,7 @@ class BBCode
|
|||
}
|
||||
|
||||
// Vimeo extensions
|
||||
if ($try_oembed) {
|
||||
if ($try_oembed && OEmbed::isAllowedURL('https://player.vimeo.com/video')) {
|
||||
$text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->getThemeInfoValue('videowidth') . '" height="' . $a->getThemeInfoValue('videoheight') . '" src="https://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $text);
|
||||
} else {
|
||||
$text = preg_replace(
|
||||
|
@ -1809,7 +1846,7 @@ class BBCode
|
|||
}
|
||||
|
||||
// oembed tag
|
||||
$text = OEmbed::BBCode2HTML($text);
|
||||
$text = OEmbed::BBCode2HTML($text, $uriid);
|
||||
|
||||
// Avoid triple linefeeds through oembed
|
||||
$text = str_replace("<br style='clear:left'></span><br><br>", "<br style='clear:left'></span><br>", $text);
|
||||
|
@ -2056,13 +2093,7 @@ class BBCode
|
|||
);
|
||||
|
||||
// Default iframe allowed domains/path
|
||||
$allowedIframeDomains = [
|
||||
DI::baseUrl()->getHost()
|
||||
. (DI::baseUrl()->getPath() ? '/' . DI::baseUrl()->getPath() : '')
|
||||
. '/oembed/', # The path part has to change with the source in Content\Oembed::iframe
|
||||
'www.youtube.com/embed/',
|
||||
'player.vimeo.com/video/',
|
||||
];
|
||||
$allowedIframeDomains = DI::config()->get('system', 'no_oembed_rich_content') ? [] : ['www.youtube.com/embed/', 'player.vimeo.com/video/'];
|
||||
|
||||
$allowedIframeDomains = array_merge(
|
||||
$allowedIframeDomains,
|
||||
|
|
|
@ -103,6 +103,7 @@ class Widget
|
|||
{
|
||||
// Always hide content from these networks
|
||||
$networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET, Protocol::TWITTER, Protocol::ZOT];
|
||||
Addon::loadAddons();
|
||||
|
||||
if (!Addon::isEnabled("discourse")) {
|
||||
$networks[] = Protocol::DISCOURSE;
|
||||
|
|
|
@ -104,7 +104,7 @@ class VCard
|
|||
$mention_label = DI::l10n()->t('Post to group');
|
||||
$mention_link = 'compose/0?body=!' . $contact['addr'];
|
||||
}
|
||||
$showgroup_link = 'network/group/' . $id;
|
||||
$showgroup_link = 'contact/' . $id . '/conversations';
|
||||
} elseif (!$hide_mention) {
|
||||
$mention_label = DI::l10n()->t('Mention');
|
||||
$mention_link = 'compose/0?body=@' . $contact['addr'];
|
||||
|
|
|
@ -632,23 +632,10 @@ class Installer
|
|||
*/
|
||||
public function checkImagick()
|
||||
{
|
||||
$imagick = false;
|
||||
$gif = false;
|
||||
|
||||
if (class_exists('Imagick')) {
|
||||
$imagick = true;
|
||||
$supported = Images::supportedTypes();
|
||||
if (array_key_exists('image/gif', $supported)) {
|
||||
$gif = true;
|
||||
}
|
||||
}
|
||||
if (!$imagick) {
|
||||
$this->addCheck(DI::l10n()->t('ImageMagick PHP extension is not installed'), $imagick, false, "");
|
||||
if (!class_exists('Imagick')) {
|
||||
$this->addCheck(DI::l10n()->t('ImageMagick PHP extension is not installed'), false, false, "");
|
||||
} else {
|
||||
$this->addCheck(DI::l10n()->t('ImageMagick PHP extension is installed'), $imagick, false, "");
|
||||
if ($imagick) {
|
||||
$this->addCheck(DI::l10n()->t('ImageMagick supports GIF'), $gif, false, "");
|
||||
}
|
||||
$this->addCheck(DI::l10n()->t('ImageMagick PHP extension is installed'), true, false, "");
|
||||
}
|
||||
|
||||
// Imagick is not required
|
||||
|
|
|
@ -473,7 +473,7 @@ class System
|
|||
return false;
|
||||
}
|
||||
|
||||
return max($load_arr[0], $load_arr[1]);
|
||||
return round(max($load_arr[0], $load_arr[1]), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Friendica\Core\Cache\Enum\Duration;
|
||||
use Friendica\Core\Worker\Entity\Process;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
|
@ -54,7 +55,8 @@ class Worker
|
|||
const FAST_COMMANDS = ['APDelivery', 'Delivery'];
|
||||
|
||||
const LOCK_PROCESS = 'worker_process';
|
||||
const LOCK_WORKER = 'worker';
|
||||
const LOCK_WORKER = 'worker';
|
||||
const LAST_CHECK = 'worker::check';
|
||||
|
||||
private static $up_start;
|
||||
private static $db_duration = 0;
|
||||
|
@ -832,6 +834,17 @@ class Worker
|
|||
} else {
|
||||
self::spawnWorker();
|
||||
}
|
||||
} elseif (($active > $queues) && ($active < $maxqueues) && ($load < $maxsysload)) {
|
||||
$max_idletime = DI::config()->get('system', 'worker_max_idletime');
|
||||
$last_check = DI::cache()->get(self::LAST_CHECK);
|
||||
$last_date = $last_check ? date('c', $last_check) : '';
|
||||
if (($max_idletime > 0) && (time() > $last_check + $max_idletime) && !DBA::exists('workerqueue', ["`done` AND `executed` > ?", DateTimeFormat::utc('now - ' . $max_idletime . ' second')])) {
|
||||
DI::cache()->set(self::LAST_CHECK, time(), Duration::HOUR);
|
||||
Logger::info('The last worker execution had been too long ago.', ['last' => $last_check, 'last-check' => $last_date, 'seconds' => $max_idletime, 'load' => $load, 'max_load' => $maxsysload, 'active_worker' => $active, 'max_worker' => $maxqueues]);
|
||||
return false;
|
||||
} elseif ($max_idletime > 0) {
|
||||
Logger::debug('Maximum idletime not reached.', ['last' => $last_check, 'last-check' => $last_date, 'seconds' => $max_idletime, 'load' => $load, 'max_load' => $maxsysload, 'active_worker' => $active, 'max_worker' => $maxqueues]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Friendica\Factory\Api\Mastodon;
|
|||
|
||||
use Friendica\BaseFactory;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Model\Subscription;
|
||||
use Friendica\Network\HTTPException\UnprocessableEntityException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
|
@ -56,6 +57,8 @@ class Application extends BaseFactory
|
|||
$application['client_secret'],
|
||||
$application['id'],
|
||||
$application['redirect_uri'],
|
||||
$application['website']);
|
||||
$application['website'],
|
||||
Subscription::getPublicVapidKey(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ class Attachment extends BaseFactory
|
|||
$type = 'audio';
|
||||
} elseif (($filetype == 'video') || ($attachment['type'] == Post\Media::VIDEO)) {
|
||||
$type = 'video';
|
||||
} elseif ($attachment['mimetype'] == 'image/gif') {
|
||||
} elseif ($attachment['mimetype'] == image_type_to_mime_type(IMAGETYPE_GIF)) {
|
||||
$type = 'gifv';
|
||||
} elseif (($filetype == 'image') || ($attachment['type'] == Post\Media::IMAGE)) {
|
||||
$type = 'image';
|
||||
|
@ -95,12 +95,12 @@ class Attachment extends BaseFactory
|
|||
$remote = $attachment['url'];
|
||||
if ($type == 'image') {
|
||||
$url = Post\Media::getPreviewUrlForId($attachment['id']);
|
||||
$preview = Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_SMALL);
|
||||
$preview = Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_MEDIUM);
|
||||
} else {
|
||||
$url = $attachment['url'];
|
||||
|
||||
if (!empty($attachment['preview'])) {
|
||||
$preview = Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_SMALL);
|
||||
$preview = Post\Media::getPreviewUrlForId($attachment['id'], Proxy::SIZE_MEDIUM);
|
||||
} else {
|
||||
$preview = '';
|
||||
}
|
||||
|
@ -130,14 +130,13 @@ class Attachment extends BaseFactory
|
|||
'blurhash' => $photo['blurhash'],
|
||||
];
|
||||
|
||||
$photoTypes = Images::supportedTypes();
|
||||
$ext = $photoTypes[$photo['type']];
|
||||
$ext = Images::getExtensionByMimeType($photo['type']);
|
||||
|
||||
$url = $this->baseUrl . '/photo/' . $photo['resource-id'] . '-0.' . $ext;
|
||||
$url = $this->baseUrl . '/photo/' . $photo['resource-id'] . '-0' . $ext;
|
||||
|
||||
$preview = Photo::selectFirst(['scale'], ["`resource-id` = ? AND `uid` = ? AND `scale` > ?", $photo['resource-id'], $photo['uid'], 0], ['order' => ['scale']]);
|
||||
if (!empty($preview)) {
|
||||
$preview_url = $this->baseUrl . '/photo/' . $photo['resource-id'] . '-' . $preview['scale'] . '.' . $ext;
|
||||
$preview_url = $this->baseUrl . '/photo/' . $photo['resource-id'] . '-' . $preview['scale'] . $ext;
|
||||
} else {
|
||||
$preview_url = '';
|
||||
}
|
||||
|
|
|
@ -67,10 +67,12 @@ class Poll extends BaseFactory
|
|||
|
||||
if (empty($uid)) {
|
||||
$ownvotes = null;
|
||||
$voted = null;
|
||||
} else {
|
||||
$ownvotes = [];
|
||||
$voted = false;
|
||||
}
|
||||
|
||||
return new \Friendica\Object\Api\Mastodon\Poll($question, $options, $expired, $votes, $ownvotes);
|
||||
return new \Friendica\Object\Api\Mastodon\Poll($question, $options, $expired, $votes, $ownvotes, $voted);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ use Friendica\Database\DBA;
|
|||
use Friendica\DI;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Model\Tag as TagModel;
|
||||
use Friendica\Model\Verb;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Object\Api\Mastodon\Status\FriendicaDeliveryData;
|
||||
|
@ -60,8 +59,6 @@ class Status extends BaseFactory
|
|||
private $mstdnAttachmentFactory;
|
||||
/** @var Emoji */
|
||||
private $mstdnEmojiFactory;
|
||||
/** @var Error */
|
||||
private $mstdnErrorFactory;
|
||||
/** @var Poll */
|
||||
private $mstdnPollFactory;
|
||||
/** @var ContentItem */
|
||||
|
@ -78,7 +75,6 @@ class Status extends BaseFactory
|
|||
Card $mstdnCardFactory,
|
||||
Attachment $mstdnAttachmentFactory,
|
||||
Emoji $mstdnEmojiFactory,
|
||||
Error $mstdnErrorFactory,
|
||||
Poll $mstdnPollFactory,
|
||||
ContentItem $contentItem,
|
||||
ACLFormatter $aclFormatter
|
||||
|
@ -91,7 +87,6 @@ class Status extends BaseFactory
|
|||
$this->mstdnCardFactory = $mstdnCardFactory;
|
||||
$this->mstdnAttachmentFactory = $mstdnAttachmentFactory;
|
||||
$this->mstdnEmojiFactory = $mstdnEmojiFactory;
|
||||
$this->mstdnErrorFactory = $mstdnErrorFactory;
|
||||
$this->mstdnPollFactory = $mstdnPollFactory;
|
||||
$this->contentItem = $contentItem;
|
||||
$this->aclFormatter = $aclFormatter;
|
||||
|
|
|
@ -38,10 +38,14 @@ class StatusSource extends BaseFactory
|
|||
*/
|
||||
public function createFromUriId(int $uriId, int $uid): \Friendica\Object\Api\Mastodon\StatusSource
|
||||
{
|
||||
$post = Post::selectOriginal(['uri-id', 'raw-body', 'body', 'title'], ['uri-id' => $uriId, 'uid' => [0, $uid]]);
|
||||
$post = Post::selectOriginal(['uri-id', 'raw-body', 'body', 'title', 'content-warning'], ['uri-id' => $uriId, 'uid' => [0, $uid]]);
|
||||
|
||||
$spoiler_text = $post['title'] ?: BBCode::toPlaintext(BBCode::getAbstract($post['body'], Protocol::ACTIVITYPUB));
|
||||
$body = BBCode::toMarkdown(Post\Media::removeFromEndOfBody($post['body']));
|
||||
$spoiler_text = $post['title'] ?: $post['content-warning'] ?: BBCode::toPlaintext(BBCode::getAbstract($post['body'], Protocol::ACTIVITYPUB));
|
||||
|
||||
$body = Post\Media::removeFromEndOfBody($post['body']);
|
||||
$body = Post\Media::addHTMLLinkToBody($uriId, $body);
|
||||
$body = BBCode::setMentionsToAddr($body);
|
||||
$body = BBCode::toPlaintext($body);
|
||||
|
||||
return new \Friendica\Object\Api\Mastodon\StatusSource($post['uri-id'], $body, $spoiler_text);
|
||||
}
|
||||
|
|
|
@ -24,10 +24,9 @@ namespace Friendica\Factory\Api\Twitter;
|
|||
use Friendica\BaseFactory;
|
||||
use Friendica\Model\APContact;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Factory\Api\Twitter\Status;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class User extends BaseFactory
|
||||
|
@ -85,9 +84,17 @@ class User extends BaseFactory
|
|||
* @param bool $include_user_entities
|
||||
*
|
||||
* @return \Friendica\Object\Api\Twitter\User
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws HTTPException\NotFoundException If the $uid doesn't exist
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function createFromUserId(int $uid, bool $skip_status = true, bool $include_user_entities = true): \Friendica\Object\Api\Twitter\User
|
||||
{
|
||||
return $this->createFromContactId(Contact::getPublicIdByUserId($uid), $uid, $skip_status, $include_user_entities);
|
||||
$cid = Contact::getPublicIdByUserId($uid);
|
||||
if (!$cid) {
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
return $this->createFromContactId($cid, $uid, $skip_status, $include_user_entities);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,6 +208,8 @@ class APContact
|
|||
|
||||
if (!$failed && ($curlResult->getReturnCode() == 410)) {
|
||||
$data = ['@context' => ActivityPub::CONTEXT, 'id' => $url, 'type' => 'Tombstone'];
|
||||
} elseif (!$failed && !HTTPSignature::isValidContentType($curlResult->getContentType(), $url)) {
|
||||
$failed = true;
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
Logger::notice('Error fetching url', ['url' => $url, 'exception' => $exception]);
|
||||
|
@ -374,6 +376,9 @@ class APContact
|
|||
}
|
||||
|
||||
$apcontact['discoverable'] = JsonLD::fetchElement($compacted, 'toot:discoverable', '@value');
|
||||
if (is_null($apcontact['discoverable']) && ($apcontact['type'] == 'Application')) {
|
||||
$apcontact['discoverable'] = false;
|
||||
}
|
||||
|
||||
if (!empty($apcontact['photo'])) {
|
||||
$apcontact['photo'] = Network::addBasePath($apcontact['photo'], $apcontact['url']);
|
||||
|
|
|
@ -755,7 +755,7 @@ class Contact
|
|||
$user = DBA::selectFirst(
|
||||
'user',
|
||||
['uid', 'username', 'nickname', 'pubkey', 'prvkey'],
|
||||
['uid' => $uid, 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false]
|
||||
['uid' => $uid, 'account_removed' => false, 'account_expired' => false]
|
||||
);
|
||||
if (!DBA::isResult($user)) {
|
||||
return false;
|
||||
|
@ -842,7 +842,6 @@ class Contact
|
|||
return false;
|
||||
}
|
||||
|
||||
$file_suffix = 'jpg';
|
||||
$url = DI::baseUrl() . '/profile/' . $user['nickname'];
|
||||
|
||||
$fields = [
|
||||
|
@ -875,17 +874,11 @@ class Contact
|
|||
$fields['avatar-date'] = DateTimeFormat::utcNow();
|
||||
}
|
||||
|
||||
// Creating the path to the avatar, beginning with the file suffix
|
||||
$types = Images::supportedTypes();
|
||||
if (isset($types[$avatar['type']])) {
|
||||
$file_suffix = $types[$avatar['type']];
|
||||
}
|
||||
|
||||
// We are adding a timestamp value so that other systems won't use cached content
|
||||
$timestamp = strtotime($fields['avatar-date']);
|
||||
|
||||
$prefix = DI::baseUrl() . '/photo/' . $avatar['resource-id'] . '-';
|
||||
$suffix = '.' . $file_suffix . '?ts=' . $timestamp;
|
||||
$suffix = Images::getExtensionByMimeType($avatar['type']) . '?ts=' . $timestamp;
|
||||
|
||||
$fields['photo'] = $prefix . '4' . $suffix;
|
||||
$fields['thumb'] = $prefix . '5' . $suffix;
|
||||
|
@ -1137,7 +1130,7 @@ class Contact
|
|||
{
|
||||
// Always unarchive the relay contact entry
|
||||
if (!empty($contact['batch']) && !empty($contact['term-date']) && ($contact['term-date'] > DBA::NULL_DATETIME)) {
|
||||
$fields = ['failed' => false, 'term-date' => DBA::NULL_DATETIME, 'archive' => false];
|
||||
$fields = ['failed' => false, 'term-date' => DBA::NULL_DATETIME, 'archive' => false, 'unsearchable' => true];
|
||||
$condition = ['uid' => 0, 'network' => Protocol::FEDERATED, 'batch' => $contact['batch'], 'contact-type' => self::TYPE_RELAY];
|
||||
if (!DBA::exists('contact', array_merge($condition, $fields))) {
|
||||
self::update($fields, $condition);
|
||||
|
@ -1212,13 +1205,12 @@ class Contact
|
|||
$mention_label = DI::l10n()->t('Post to group');
|
||||
$mention_url = 'compose/0?body=!' . $contact['addr'];
|
||||
$network_label = DI::l10n()->t('View group');
|
||||
$network_url = 'network/group/' . $contact['id'];
|
||||
} else {
|
||||
$mention_label = DI::l10n()->t('Mention');
|
||||
$mention_url = 'compose/0?body=@' . $contact['addr'];
|
||||
$network_label = DI::l10n()->t('Network Posts');
|
||||
$network_url = 'contact/' . $contact['id'] . '/conversations';
|
||||
}
|
||||
$network_url = 'contact/' . $contact['id'] . '/conversations';
|
||||
|
||||
$follow_link = '';
|
||||
$unfollow_link = '';
|
||||
|
@ -2313,8 +2305,8 @@ class Contact
|
|||
$fetchResult = HTTPSignature::fetchRaw($avatar, 0, [HttpClientOptions::ACCEPT_CONTENT => [HttpClientAccept::IMAGE]]);
|
||||
|
||||
$img_str = $fetchResult->getBodyString();
|
||||
if (!empty($img_str)) {
|
||||
$image = new Image($img_str, Images::getMimeTypeByData($img_str));
|
||||
if ($fetchResult->isSuccess() && !empty($img_str)) {
|
||||
$image = new Image($img_str, $fetchResult->getContentType(), $avatar);
|
||||
if ($image->isValid()) {
|
||||
$update_fields['blurhash'] = $image->getBlurHash();
|
||||
} else {
|
||||
|
@ -2827,13 +2819,19 @@ class Contact
|
|||
}
|
||||
|
||||
// We must not try to update relay contacts via probe. They are no real contacts.
|
||||
// See Relay::updateContact() for more details.
|
||||
// We check after the probing to be able to correct falsely detected contact types.
|
||||
if (($contact['contact-type'] == self::TYPE_RELAY) &&
|
||||
if (($contact['contact-type'] == self::TYPE_RELAY) && Strings::compareLink($contact['url'], $contact['baseurl']) &&
|
||||
(!Strings::compareLink($ret['url'], $contact['url']) || in_array($ret['network'], [Protocol::FEED, Protocol::PHANTOM]))
|
||||
) {
|
||||
self::updateContact($id, $uid, $uriid, $contact['url'], ['failed' => false, 'local-data' => $has_local_data, 'last-update' => $updated, 'next-update' => $success_next_update, 'success_update' => $updated]);
|
||||
Logger::info('Not updating relais', ['id' => $id, 'url' => $contact['url']]);
|
||||
return true;
|
||||
if (GServer::reachable($contact)) {
|
||||
self::updateContact($id, $uid, $uriid, $contact['url'], ['failed' => false, 'local-data' => $has_local_data, 'last-update' => $updated, 'next-update' => $success_next_update, 'success_update' => $updated, 'unsearchable' => true]);
|
||||
Logger::info('Not updating relay', ['id' => $id, 'url' => $contact['url']]);
|
||||
return true;
|
||||
}
|
||||
Logger::info('Relay server is not reachable', ['id' => $id, 'url' => $contact['url']]);
|
||||
self::updateContact($id, $uid, $uriid, $contact['url'], ['failed' => true, 'local-data' => $has_local_data, 'last-update' => $updated, 'next-update' => $failed_next_update, 'failure_update' => $updated, 'unsearchable' => true]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If Probe::uri fails the network code will be different ("feed" or "unkn")
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespace Friendica\Model\Contact;
|
||||
|
||||
use Exception;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Database\Database;
|
||||
|
@ -78,14 +79,14 @@ class Relation
|
|||
*/
|
||||
public static function discoverByUser(int $uid)
|
||||
{
|
||||
$contact = Contact::selectFirst(['id', 'url', 'network'], ['uid' => $uid, 'self' => true]);
|
||||
$contact = Contact::selectFirst(['id', 'url', 'network'], ['id' => Contact::getPublicIdByUserId($uid)]);
|
||||
if (empty($contact)) {
|
||||
Logger::warning('Self contact for user not found', ['uid' => $uid]);
|
||||
return;
|
||||
}
|
||||
|
||||
$followers = self::getContacts($uid, [Contact::FOLLOWER, Contact::FRIEND]);
|
||||
$followings = self::getContacts($uid, [Contact::SHARING, Contact::FRIEND]);
|
||||
$followers = self::getContacts($uid, [Contact::FOLLOWER, Contact::FRIEND], false);
|
||||
$followings = self::getContacts($uid, [Contact::SHARING, Contact::FRIEND], false);
|
||||
|
||||
self::updateFollowersFollowings($contact, $followers, $followings);
|
||||
}
|
||||
|
@ -207,10 +208,11 @@ class Relation
|
|||
* Fetch contact url list from the given local user
|
||||
*
|
||||
* @param integer $uid
|
||||
* @param array $rel
|
||||
* @param array $rel
|
||||
* @param bool $only_ap
|
||||
* @return array contact list
|
||||
*/
|
||||
private static function getContacts(int $uid, array $rel): array
|
||||
private static function getContacts(int $uid, array $rel, bool $only_ap = true): array
|
||||
{
|
||||
$list = [];
|
||||
$profile = Profile::getByUID($uid);
|
||||
|
@ -219,15 +221,22 @@ class Relation
|
|||
}
|
||||
|
||||
$condition = [
|
||||
'rel' => $rel,
|
||||
'uid' => $uid,
|
||||
'self' => false,
|
||||
'rel' => $rel,
|
||||
'uid' => $uid,
|
||||
'self' => false,
|
||||
'deleted' => false,
|
||||
'hidden' => false,
|
||||
'hidden' => false,
|
||||
'archive' => false,
|
||||
'pending' => false,
|
||||
'blocked' => false,
|
||||
'failed' => false,
|
||||
];
|
||||
$condition = DBA::mergeConditions($condition, ["`url` IN (SELECT `url` FROM `apcontact`)"]);
|
||||
if ($only_ap) {
|
||||
$condition = DBA::mergeConditions($condition, ["`url` IN (SELECT `url` FROM `apcontact`)"]);
|
||||
} else {
|
||||
$networks = Widget::unavailableNetworks();
|
||||
$condition = DBA::mergeConditions($condition, array_merge(["NOT `network` IN (" . substr(str_repeat("?, ", count($networks)), 0, -2) . ")"], $networks));
|
||||
}
|
||||
$contacts = DBA::select('contact', ['url'], $condition);
|
||||
while ($contact = DBA::fetch($contacts)) {
|
||||
$list[] = $contact['url'];
|
||||
|
@ -870,6 +879,20 @@ class Relation
|
|||
DBA::update('contact-relation', ['thread-score' => $score], ['relation-cid' => $contact_id, 'cid' => $interaction['author-id']]);
|
||||
}
|
||||
DBA::close($interactions);
|
||||
|
||||
$total = DBA::fetchFirst("SELECT count(*) AS `posts` FROM `post-thread-user` WHERE EXISTS(SELECT `cid` FROM `contact-relation` WHERE `cid` = `post-thread-user`.`author-id` AND `relation-cid` = ? AND `follows`) AND `uid` = ? AND `created` > ?",
|
||||
$contact_id, $uid, DateTimeFormat::utc('now - ' . $days . ' day'));
|
||||
|
||||
Logger::debug('Calculate post-score', ['uid' => $uid, 'total' => $total['posts']]);
|
||||
|
||||
$posts = DBA::p("SELECT `author-id`, count(*) AS `posts` FROM `post-thread-user` WHERE EXISTS(SELECT `cid` FROM `contact-relation` WHERE `cid` = `post-thread-user`.`author-id` AND `relation-cid` = ? AND `follows`) AND `uid` = ? AND `created` > ? GROUP BY `author-id`",
|
||||
$contact_id, $uid, DateTimeFormat::utc('now - ' . $days . ' day'));
|
||||
while ($post = DBA::fetch($posts)) {
|
||||
$score = min((int)(($post['posts'] / $total['posts']) * 65535), 65535);
|
||||
DBA::update('contact-relation', ['post-score' => $score], ['relation-cid' => $contact_id, 'cid' => $post['author-id']]);
|
||||
}
|
||||
DBA::close($posts);
|
||||
|
||||
Logger::debug('Calculation - end', ['uid' => $uid]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -364,6 +364,53 @@ class User
|
|||
return $frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel only value for contact id and user id
|
||||
*
|
||||
* @param int $cid Either public contact id or user's contact id
|
||||
* @param int $uid User ID
|
||||
* @param int $isChannelOnly Is channel only
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setChannelOnly(int $cid, int $uid, bool $isChannelOnly)
|
||||
{
|
||||
$cdata = Contact::getPublicAndUserContactID($cid, $uid);
|
||||
if (empty($cdata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DBA::update('user-contact', ['channel-only' => $isChannelOnly], ['cid' => $cdata['public'], 'uid' => $uid], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the contact is channel only for contact id and user id
|
||||
*
|
||||
* @param int $cid Either public contact id or user's contact id
|
||||
* @param int $uid User ID
|
||||
* @return bool Contact is channel only
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public static function getChannelOnly(int $cid, int $uid): bool
|
||||
{
|
||||
$cdata = Contact::getPublicAndUserContactID($cid, $uid);
|
||||
if (empty($cdata)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$isChannelOnly = false;
|
||||
|
||||
if (!empty($cdata['public'])) {
|
||||
$public_contact = DBA::selectFirst('user-contact', ['channel-only'], ['cid' => $cdata['public'], 'uid' => $uid]);
|
||||
if (DBA::isResult($public_contact)) {
|
||||
$isChannelOnly = $public_contact['channel-only'] ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
return $isChannelOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set/Release that the user is blocked by the contact
|
||||
*
|
||||
|
|
|
@ -925,9 +925,6 @@ class Event
|
|||
$end_short = '';
|
||||
}
|
||||
|
||||
// Format the event location.
|
||||
$location = self::locationToArray($item['event-location']);
|
||||
|
||||
// Construct the profile link (magic-auth).
|
||||
$author = [
|
||||
'uid' => 0,
|
||||
|
@ -964,7 +961,7 @@ class Event
|
|||
'$show_map_label' => DI::l10n()->t('Show map'),
|
||||
'$hide_map_label' => DI::l10n()->t('Hide map'),
|
||||
'$map_btn_label' => DI::l10n()->t('Show map'),
|
||||
'$location' => $location
|
||||
'$location' => self::locationToTemplateVars($item['event-location']),
|
||||
]);
|
||||
|
||||
return $return;
|
||||
|
@ -984,7 +981,7 @@ class Event
|
|||
* 'coordinates' => Latitude and longitude (e.g. '48.864716,2.349014').<br>
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private static function locationToArray(string $s = ''): array
|
||||
private static function locationToTemplateVars(string $s = ''): array
|
||||
{
|
||||
if ($s == '') {
|
||||
return [];
|
||||
|
|
|
@ -34,10 +34,11 @@ use Friendica\Core\Protocol;
|
|||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Post\Category;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Network\HTTPException\ServiceUnavailableException;
|
||||
use Friendica\Protocol\Activity;
|
||||
|
@ -45,6 +46,7 @@ use Friendica\Protocol\ActivityPub;
|
|||
use Friendica\Protocol\Delivery;
|
||||
use Friendica\Protocol\Diaspora;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\HTTPSignature;
|
||||
use Friendica\Util\Map;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\Proxy;
|
||||
|
@ -106,7 +108,7 @@ class Item
|
|||
'owner-id', 'owner-link', 'owner-alias', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type', 'owner-updated', 'owner-gsid',
|
||||
'causer-id', 'causer-link', 'causer-alias', 'causer-name', 'causer-avatar', 'causer-contact-type', 'causer-network', 'causer-gsid',
|
||||
'contact-id', 'contact-uid', 'contact-link', 'contact-name', 'contact-avatar',
|
||||
'writable', 'self', 'cid', 'alias',
|
||||
'writable', 'restrictions', 'self', 'cid', 'alias',
|
||||
'event-created', 'event-edited', 'event-start', 'event-finish',
|
||||
'event-summary', 'event-desc', 'event-location', 'event-type',
|
||||
'event-nofinish', 'event-ignore', 'event-id',
|
||||
|
@ -166,6 +168,11 @@ class Item
|
|||
const GRAVITY_COMMENT = 6;
|
||||
const GRAVITY_UNKNOWN = 9;
|
||||
|
||||
// Restrictions
|
||||
const CANT_REPLY = 1;
|
||||
const CANT_LIKE = 2;
|
||||
const CANT_ANNOUNCE = 4;
|
||||
|
||||
/**
|
||||
* Update existing item entries
|
||||
*
|
||||
|
@ -689,38 +696,6 @@ class Item
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the item array is too old
|
||||
*
|
||||
* @param array $item Item record
|
||||
* @return boolean item is too old
|
||||
*/
|
||||
public static function isTooOld(array $item): bool
|
||||
{
|
||||
// check for create date and expire time
|
||||
$expire_interval = DI::config()->get('system', 'dbclean-expire-days', 0);
|
||||
|
||||
$user = DBA::selectFirst('user', ['expire'], ['uid' => $item['uid']]);
|
||||
if (DBA::isResult($user) && ($user['expire'] > 0) && (($user['expire'] < $expire_interval) || ($expire_interval == 0))) {
|
||||
$expire_interval = $user['expire'];
|
||||
}
|
||||
|
||||
if (($expire_interval > 0) && !empty($item['created'])) {
|
||||
$expire_date = time() - ($expire_interval * 86400);
|
||||
$created_date = strtotime($item['created']);
|
||||
if ($created_date < $expire_date) {
|
||||
Logger::notice('Item created before expiration interval.', [
|
||||
'created' => date('c', $created_date),
|
||||
'expired' => date('c', $expire_date),
|
||||
'$item' => $item
|
||||
]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the id of the given item array if it has been stored before
|
||||
*
|
||||
|
@ -789,7 +764,7 @@ class Item
|
|||
{
|
||||
$fields = [
|
||||
'uid', 'uri', 'parent-uri', 'id', 'deleted',
|
||||
'uri-id', 'parent-uri-id',
|
||||
'uri-id', 'parent-uri-id', 'restrictions', 'verb',
|
||||
'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid',
|
||||
'wall', 'private', 'origin', 'author-id'
|
||||
];
|
||||
|
@ -813,6 +788,11 @@ class Item
|
|||
return [];
|
||||
}
|
||||
|
||||
if (self::hasRestrictions($item, $parent['author-id'], $parent['restrictions'])) {
|
||||
Logger::notice('Restrictions apply - ignoring item', ['restrictions' => $parent['restrictions'], 'verb' => $parent['verb'], 'uri-id' => $item['uri-id'], 'thr-parent-id' => $item['thr-parent-id'], 'uid' => $item['uid']]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($parent['uri-id'] == $parent['parent-uri-id']) {
|
||||
return $parent;
|
||||
}
|
||||
|
@ -1032,7 +1012,7 @@ class Item
|
|||
|
||||
if (
|
||||
!empty($item['direction']) && in_array($item['direction'], [Conversation::PUSH, Conversation::RELAY]) &&
|
||||
empty($item['origin']) && self::isTooOld($item)
|
||||
empty($item['origin']) && DI::contentItem()->isTooOld($item['created'], $item['uid'])
|
||||
) {
|
||||
Logger::info('Item is too old', ['item' => $item]);
|
||||
return 0;
|
||||
|
@ -1469,6 +1449,27 @@ class Item
|
|||
return $post_user_id;
|
||||
}
|
||||
|
||||
private static function hasRestrictions(array $item, int $author_id, int $restrictions = null): bool
|
||||
{
|
||||
if (empty($restrictions) || ($author_id == $item['author-id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (($restrictions & self::CANT_REPLY) && ($item['verb'] == Activity::POST)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (($restrictions & self::CANT_ANNOUNCE) && ($item['verb'] == Activity::ANNOUNCE)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (($restrictions & self::CANT_LIKE) && in_array($item['verb'], [Activity::LIKE, Activity::DISLIKE, Activity::ATTEND, Activity::ATTENDMAYBE, Activity::ATTENDNO])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function reshareChannelPost(int $uri_id, int $reshare_id = 0)
|
||||
{
|
||||
if (!DI::config()->get('system', 'allow_relay_channels')) {
|
||||
|
@ -3675,6 +3676,13 @@ class Item
|
|||
}
|
||||
|
||||
if ($PostMedia->mimetype->type == 'video') {
|
||||
if (($PostMedia->height ?? 0) > ($PostMedia->width ?? 0)) {
|
||||
$height = min(DI::config()->get('system', 'max_video_height') ?: '100%', $PostMedia->height);
|
||||
$width = 'auto';
|
||||
} else {
|
||||
$height = 'auto';
|
||||
$width = '100%';
|
||||
}
|
||||
/// @todo Move the template to /content as well
|
||||
$media = Renderer::replaceMacros(Renderer::getMarkupTemplate('video_top.tpl'), [
|
||||
'$video' => [
|
||||
|
@ -3683,6 +3691,8 @@ class Item
|
|||
'name' => $PostMedia->name ?: $PostMedia->url,
|
||||
'preview' => $preview_url,
|
||||
'mime' => (string)$PostMedia->mimetype,
|
||||
'height' => $height,
|
||||
'width' => $width,
|
||||
],
|
||||
]);
|
||||
if (($item['post-type'] ?? null) == Item::PT_VIDEO) {
|
||||
|
@ -4117,9 +4127,12 @@ class Item
|
|||
return is_numeric($hookData['item_id']) ? $hookData['item_id'] : 0;
|
||||
}
|
||||
|
||||
$fetched_uri = ActivityPub\Processor::fetchMissingActivity($uri, [], '', $completion, $uid);
|
||||
$curlResult = DI::httpClient()->head($uri, [HttpClientOptions::ACCEPT_CONTENT => HttpClientAccept::JSON_AS]);
|
||||
if (HTTPSignature::isValidContentType($curlResult->getContentType(), $uri)) {
|
||||
$fetched_uri = ActivityPub\Processor::fetchMissingActivity($uri, [], '', $completion, $uid);
|
||||
}
|
||||
|
||||
if ($fetched_uri) {
|
||||
if (!empty($fetched_uri)) {
|
||||
$item_id = self::searchByLink($fetched_uri, $uid);
|
||||
} else {
|
||||
$item_id = Diaspora::fetchByURL($uri);
|
||||
|
|
|
@ -363,6 +363,7 @@ class Photo
|
|||
$photo['backend-class'] = SystemResource::NAME;
|
||||
$photo['backend-ref'] = $filename;
|
||||
$photo['type'] = $mimetype;
|
||||
$photo['filename'] = basename($filename);
|
||||
$photo['cacheable'] = false;
|
||||
|
||||
return $photo;
|
||||
|
@ -394,6 +395,7 @@ class Photo
|
|||
$photo['backend-class'] = ExternalResource::NAME;
|
||||
$photo['backend-ref'] = json_encode(['url' => $url, 'uid' => $uid]);
|
||||
$photo['type'] = $mimetype;
|
||||
$photo['filename'] = basename(parse_url($url, PHP_URL_PATH));
|
||||
$photo['cacheable'] = true;
|
||||
$photo['blurhash'] = $blurhash;
|
||||
$photo['width'] = $width;
|
||||
|
@ -608,9 +610,7 @@ class Photo
|
|||
return false;
|
||||
}
|
||||
|
||||
$type = Images::getMimeTypeByData($img_str, $image_url, $type);
|
||||
|
||||
$image = new Image($img_str, $type);
|
||||
$image = new Image($img_str, $type, $image_url);
|
||||
if ($image->isValid()) {
|
||||
$image->scaleToSquare(300);
|
||||
|
||||
|
@ -619,9 +619,9 @@ class Photo
|
|||
|
||||
if ($maximagesize && ($filesize > $maximagesize)) {
|
||||
Logger::info('Avatar exceeds image limit', ['uid' => $uid, 'cid' => $cid, 'maximagesize' => $maximagesize, 'size' => $filesize, 'type' => $image->getType()]);
|
||||
if ($image->getType() == 'image/gif') {
|
||||
if ($image->getImageType() == IMAGETYPE_GIF) {
|
||||
$image->toStatic();
|
||||
$image = new Image($image->asString(), 'image/png');
|
||||
$image = new Image($image->asString(), image_type_to_mime_type(IMAGETYPE_PNG));
|
||||
|
||||
$filesize = strlen($image->asString());
|
||||
Logger::info('Converted gif to a static png', ['uid' => $uid, 'cid' => $cid, 'size' => $filesize, 'type' => $image->getType()]);
|
||||
|
@ -662,9 +662,9 @@ class Photo
|
|||
|
||||
$suffix = '?ts=' . time();
|
||||
|
||||
$image_url = DI::baseUrl() . '/photo/' . $resource_id . '-4.' . $image->getExt() . $suffix;
|
||||
$thumb = DI::baseUrl() . '/photo/' . $resource_id . '-5.' . $image->getExt() . $suffix;
|
||||
$micro = DI::baseUrl() . '/photo/' . $resource_id . '-6.' . $image->getExt() . $suffix;
|
||||
$image_url = DI::baseUrl() . '/photo/' . $resource_id . '-4' . $image->getExt() . $suffix;
|
||||
$thumb = DI::baseUrl() . '/photo/' . $resource_id . '-5' . $image->getExt() . $suffix;
|
||||
$micro = DI::baseUrl() . '/photo/' . $resource_id . '-6' . $image->getExt() . $suffix;
|
||||
} else {
|
||||
$photo_failure = true;
|
||||
}
|
||||
|
@ -1060,9 +1060,7 @@ class Photo
|
|||
return [];
|
||||
}
|
||||
|
||||
$type = Images::getMimeTypeByData($img_str, $image_url, $type);
|
||||
|
||||
$image = new Image($img_str, $type);
|
||||
$image = new Image($img_str, $type, $image_url);
|
||||
|
||||
$image = self::fitImageSize($image);
|
||||
if (empty($image)) {
|
||||
|
@ -1132,12 +1130,10 @@ class Photo
|
|||
return [];
|
||||
}
|
||||
|
||||
$filetype = Images::getMimeTypeBySource($src, $filename, $filetype);
|
||||
|
||||
Logger::info('File upload', ['src' => $src, 'filename' => $filename, 'size' => $filesize, 'type' => $filetype]);
|
||||
|
||||
$imagedata = @file_get_contents($src);
|
||||
$image = new Image($imagedata, $filetype);
|
||||
$image = new Image($imagedata, $filetype, $filename);
|
||||
if (!$image->isValid()) {
|
||||
Logger::notice('Image is unvalid', ['files' => $files]);
|
||||
return [];
|
||||
|
|
|
@ -43,7 +43,7 @@ class Counts
|
|||
Activity::EMOJIREACT, Activity::ANNOUNCE, Activity::VIEW, Activity::READ])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
$condition = ['thr-parent-id' => $uri_id, 'vid' => $vid, 'deleted' => false];
|
||||
|
||||
if ($body == $verb) {
|
||||
|
@ -52,7 +52,7 @@ class Counts
|
|||
} elseif ($verb == Activity::POST) {
|
||||
$condition['gravity'] = Item::GRAVITY_COMMENT;
|
||||
$body = '';
|
||||
} elseif (($verb != Activity::POST) && (mb_strlen($body) == 1) && Smilies::isEmojiPost($body)) {
|
||||
} elseif ($body && mb_strlen($body) == 1 && Smilies::isEmojiPost($body)) {
|
||||
$condition['body'] = $body;
|
||||
} else {
|
||||
$body = '';
|
||||
|
|
|
@ -118,6 +118,7 @@ class Engagement
|
|||
'searchtext' => $searchtext,
|
||||
'size' => self::getContentSize($parent),
|
||||
'created' => $parent['created'],
|
||||
'network' => $parent['network'],
|
||||
'restricted' => !in_array($item['network'], Protocol::FEDERATED) || ($parent['private'] != Item::PUBLIC),
|
||||
'comments' => DBA::count('post', ['parent-uri-id' => $item['parent-uri-id'], 'gravity' => Item::GRAVITY_COMMENT]),
|
||||
'activities' => DBA::count('post', [
|
||||
|
@ -277,6 +278,9 @@ class Engagement
|
|||
$body = self::addResharers($body, $item['uri-id']);
|
||||
|
||||
foreach ($receivers as $receiver) {
|
||||
if (empty($receiver)) {
|
||||
continue;
|
||||
}
|
||||
$contact = Contact::getByURL($receiver, false, ['nick', 'addr', 'contact-type']);
|
||||
if (empty($contact)) {
|
||||
continue;
|
||||
|
|
|
@ -134,15 +134,23 @@ class Link
|
|||
Logger::notice('Error fetching url', ['url' => $url, 'exception' => $exception]);
|
||||
return [];
|
||||
}
|
||||
$fields = ['mimetype' => $curlResult->getHeader('Content-Type')[0]];
|
||||
|
||||
$img_str = $curlResult->getBodyString();
|
||||
$image = new Image($img_str, Images::getMimeTypeByData($img_str));
|
||||
if ($image->isValid()) {
|
||||
$fields['mimetype'] = $image->getType();
|
||||
$fields['width'] = $image->getWidth();
|
||||
$fields['height'] = $image->getHeight();
|
||||
$fields['blurhash'] = $image->getBlurHash();
|
||||
if (!$curlResult->isSuccess()) {
|
||||
Logger::notice('Fetching unsuccessful', ['url' => $url]);
|
||||
return [];
|
||||
}
|
||||
|
||||
$fields = ['mimetype' => $curlResult->getContentType()];
|
||||
|
||||
if (Images::isSupportedMimeType($fields['mimetype'])) {
|
||||
$img_str = $curlResult->getBodyString();
|
||||
$image = new Image($img_str, $fields['mimetype'], $url);
|
||||
if ($image->isValid()) {
|
||||
$fields['mimetype'] = $image->getType();
|
||||
$fields['width'] = $image->getWidth();
|
||||
$fields['height'] = $image->getHeight();
|
||||
$fields['blurhash'] = $image->getBlurHash();
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
|
|
|
@ -196,7 +196,7 @@ class Media
|
|||
|
||||
if ($curlResult->isSuccess()) {
|
||||
if (empty($media['mimetype'])) {
|
||||
$media['mimetype'] = $curlResult->getHeader('Content-Type')[0] ?? '';
|
||||
$media['mimetype'] = $curlResult->getContentType() ?? '';
|
||||
}
|
||||
if (empty($media['size'])) {
|
||||
$media['size'] = (int)($curlResult->getHeader('Content-Length')[0] ?? 0);
|
||||
|
@ -365,7 +365,7 @@ class Media
|
|||
*/
|
||||
private static function addPage(array $media): array
|
||||
{
|
||||
$data = ParseUrl::getSiteinfoCached($media['url'], false);
|
||||
$data = ParseUrl::getSiteinfoCached($media['url']);
|
||||
$media['preview'] = $data['images'][0]['src'] ?? null;
|
||||
$media['preview-height'] = $data['images'][0]['height'] ?? null;
|
||||
$media['preview-width'] = $data['images'][0]['width'] ?? null;
|
||||
|
@ -912,6 +912,8 @@ class Media
|
|||
$body .= "\n[audio]" . $media['url'] . "[/audio]\n";
|
||||
} elseif ($media['type'] == self::VIDEO) {
|
||||
$body .= "\n[video]" . $media['url'] . "[/video]\n";
|
||||
} else {
|
||||
$body .= "\n[url]" . $media['url'] . "[/url]\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,9 @@ class SearchIndex
|
|||
}
|
||||
|
||||
$item = Post::selectFirstPost(['created', 'owner-id', 'private', 'language', 'network', 'title', 'content-warning', 'body', 'quote-uri-id'], ['uri-id' => $uri_id]);
|
||||
if (empty($item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$search = [
|
||||
'uri-id' => $uri_id,
|
||||
|
|
|
@ -461,13 +461,12 @@ class Profile
|
|||
$mention_label = DI::l10n()->t('Post to group');
|
||||
$mention_url = 'compose/0?body=!' . $profile['addr'];
|
||||
$network_label = DI::l10n()->t('View group');
|
||||
$network_url = 'network/group/' . $cid;
|
||||
} else {
|
||||
$mention_label = DI::l10n()->t('Mention');
|
||||
$mention_url = 'compose/0?body=@' . $profile['addr'];
|
||||
$network_label = DI::l10n()->t('Network Posts');
|
||||
$network_url = 'contact/' . $cid . '/conversations';
|
||||
}
|
||||
$network_url = 'contact/' . $cid . '/conversations';
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate('profile/vcard.tpl');
|
||||
$o .= Renderer::replaceMacros($tpl, [
|
||||
|
|
|
@ -826,26 +826,30 @@ class User
|
|||
/**
|
||||
* Update the day of the last activity of the given user
|
||||
*
|
||||
* @param integer $uid
|
||||
* @param array $user
|
||||
* @param bool $refresh_login
|
||||
* @return void
|
||||
*/
|
||||
public static function updateLastActivity(int $uid)
|
||||
public static function updateLastActivity(array $user, bool $refresh_login)
|
||||
{
|
||||
if (!$uid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = self::getById($uid, ['last-activity']);
|
||||
if (empty($user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_day = DateTimeFormat::utcNow('Y-m-d');
|
||||
if (($user['last-activity'] == $current_day) && (!$refresh_login || DateTimeFormat::utc($user['login_date'], 'z-H') == DateTimeFormat::utcNow('z-H'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($user['last-activity'] != $current_day) {
|
||||
self::update(['last-activity' => $current_day], $uid);
|
||||
// Set the last activity for all identities of the user
|
||||
DBA::update('user', ['last-activity' => $current_day], ['parent-uid' => $uid, 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false]);
|
||||
$fields = ['last-activity' => $current_day];
|
||||
if ($refresh_login) {
|
||||
$fields['login_date'] = DateTimeFormat::utcNow();
|
||||
}
|
||||
|
||||
Logger::debug('Set last activity for user', ['uid' => $user['uid'], 'fields' => $fields]);
|
||||
self::update($fields, $user['uid']);
|
||||
// Set the last activity for all identities of the user
|
||||
DBA::update('user', $fields, ['parent-uid' => $user['uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false]);
|
||||
|
||||
if (!empty($user['parent-uid'])) {
|
||||
self::update($fields, $user['parent-uid']);
|
||||
DBA::update('user', $fields, ['parent-uid' => $user['parent-uid'], 'verified' => true, 'blocked' => false, 'account_removed' => false, 'account_expired' => false]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1403,9 +1407,7 @@ class User
|
|||
$type = '';
|
||||
}
|
||||
|
||||
$type = Images::getMimeTypeByData($img_str, $photo, $type);
|
||||
|
||||
$image = new Image($img_str, $type);
|
||||
$image = new Image($img_str, $type, $photo);
|
||||
if ($image->isValid()) {
|
||||
$image->scaleToSquare(300);
|
||||
|
||||
|
|
|
@ -77,6 +77,11 @@ class Inbox extends BaseApi
|
|||
throw new \Friendica\Network\HTTPException\BadRequestException();
|
||||
}
|
||||
|
||||
if (!HTTPSignature::isValidContentType($this->server['CONTENT_TYPE'] ?? '')) {
|
||||
Logger::notice('Unexpected content type', ['content-type' => $this->server['CONTENT_TYPE'] ?? '', 'agent' => $this->server['HTTP_USER_AGENT'] ?? '']);
|
||||
throw new \Friendica\Network\HTTPException\UnsupportedMediaTypeException();
|
||||
}
|
||||
|
||||
if (DI::config()->get('debug', 'ap_inbox_log')) {
|
||||
if (HTTPSignature::getSigner($postdata, $_SERVER)) {
|
||||
$filename = 'signed-activitypub';
|
||||
|
|
|
@ -43,6 +43,7 @@ class Federation extends BaseAdmin
|
|||
'birdsitelive' => ['name' => 'BirdsiteLIVE', 'color' => '#1b6ec2'], // Color from the page
|
||||
'bookwyrm' => ['name' => 'BookWyrm', 'color' => '#00d1b2'], // Color from the page
|
||||
'castopod' => ['name' => 'Castopod', 'color' => '#00564a'], // Background color from the page
|
||||
'cherrypick' => ['name' => 'Cherrypick', 'color' => 'pink'], // Color from one of the instabces
|
||||
'diaspora' => ['name' => 'Diaspora', 'color' => '#a1a1a1'], // logo is black and white, makes a gray
|
||||
'calckey' => ['name' => 'firefish (Calckey)', 'color' => '#1c4a5c'], // Color from the page
|
||||
'sharkey' => ['name' => 'Sharkey', 'color' => 'lightpink'], // Font color from the homepage
|
||||
|
@ -58,6 +59,7 @@ class Federation extends BaseAdmin
|
|||
'kbin' => ['name' => 'kbin', 'color' => '#61366b'], // Color from their main instance
|
||||
'lemmy' => ['name' => 'Lemmy', 'color' => '#00c853'], // Green from the page
|
||||
'mastodon' => ['name' => 'Mastodon', 'color' => '#1a9df9'], // blue from the Mastodon logo
|
||||
'mbin' => ['name' => 'mbin', 'color' => '#3c3c3c'], // Color from one of their instances
|
||||
'microblog' => ['name' => 'Microblog', 'color' => '#fdb52b'], // Color from the page
|
||||
'misskey' => ['name' => 'Misskey', 'color' => '#ccfefd'], // Font color of the homepage
|
||||
'mobilizon' => ['name' => 'Mobilizon', 'color' => '#ffd599'], // Background color of parts of the homepage
|
||||
|
|
|
@ -30,6 +30,8 @@ class PhpInfo extends BaseAdmin
|
|||
{
|
||||
self::checkAdminAccess();
|
||||
|
||||
self::checkFormSecurityTokenForbiddenOnError('phpinfo', 't');
|
||||
|
||||
phpinfo();
|
||||
System::exit();
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ class Site extends BaseAdmin
|
|||
|
||||
$allowed_sites = (!empty($_POST['allowed_sites']) ? trim($_POST['allowed_sites']) : '');
|
||||
$allowed_email = (!empty($_POST['allowed_email']) ? trim($_POST['allowed_email']) : '');
|
||||
$disallowed_email = (!empty($_POST['disallowed_email']) ? trim($_POST['disallowed_email']) : '');
|
||||
$forbidden_nicknames = (!empty($_POST['forbidden_nicknames']) ? strtolower(trim($_POST['forbidden_nicknames'])) : '');
|
||||
$system_actor_name = (!empty($_POST['system_actor_name']) ? trim($_POST['system_actor_name']) : '');
|
||||
$no_oembed_rich_content = !empty($_POST['no_oembed_rich_content']);
|
||||
|
@ -255,6 +256,7 @@ class Site extends BaseAdmin
|
|||
$transactionConfig->set('config', 'register_text' , $register_text);
|
||||
$transactionConfig->set('system', 'allowed_sites' , $allowed_sites);
|
||||
$transactionConfig->set('system', 'allowed_email' , $allowed_email);
|
||||
$transactionConfig->set('system', 'disallowed_email' , $disallowed_email);
|
||||
$transactionConfig->set('system', 'forbidden_nicknames' , $forbidden_nicknames);
|
||||
$transactionConfig->set('system', 'system_actor_name' , $system_actor_name);
|
||||
$transactionConfig->set('system', 'no_oembed_rich_content' , $no_oembed_rich_content);
|
||||
|
@ -505,6 +507,7 @@ class Site extends BaseAdmin
|
|||
'$abandon_days' => ['abandon_days', DI::l10n()->t('Accounts abandoned after x days'), DI::config()->get('system', 'account_abandon_days'), DI::l10n()->t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')],
|
||||
'$allowed_sites' => ['allowed_sites', DI::l10n()->t('Allowed friend domains'), DI::config()->get('system', 'allowed_sites'), DI::l10n()->t('Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains')],
|
||||
'$allowed_email' => ['allowed_email', DI::l10n()->t('Allowed email domains'), DI::config()->get('system', 'allowed_email'), DI::l10n()->t('Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains')],
|
||||
'$disallowed_email' => ['disallowed_email', DI::l10n()->t('Disallowed email domains'), DI::config()->get('system', 'disallowed_email'), DI::l10n()->t('Comma separated list of domains which are rejected as email addresses for registrations to this site. Wildcards are accepted.')],
|
||||
'$no_oembed_rich_content' => ['no_oembed_rich_content', DI::l10n()->t('No OEmbed rich content'), DI::config()->get('system', 'no_oembed_rich_content'), DI::l10n()->t('Don\'t show the rich content (e.g. embedded PDF), except from the domains listed below.')],
|
||||
'$allowed_oembed' => ['allowed_oembed', DI::l10n()->t('Trusted third-party domains'), DI::config()->get('system', 'allowed_oembed'), DI::l10n()->t('Comma separated list of domains from which content is allowed to be embedded in posts like with OEmbed. All sub-domains of the listed domains are allowed as well.')],
|
||||
'$block_public' => ['block_public', DI::l10n()->t('Block public'), DI::config()->get('system', 'block_public'), DI::l10n()->t('Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.')],
|
||||
|
|
|
@ -47,7 +47,7 @@ class Config extends BaseApi
|
|||
'broughtby' => '',
|
||||
'broughtbyurl' => '',
|
||||
'timezone' => DI::config()->get('system', 'default_timezone'),
|
||||
'closed' => (DI::config()->get('config', 'register_policy') == Register::CLOSED),
|
||||
'closed' => Register::getPolicy() === Register::CLOSED,
|
||||
'inviteonly' => (bool)DI::config()->get('system', 'invitation_only'),
|
||||
'private' => (bool)DI::config()->get('system', 'block_public'),
|
||||
'textlimit' => (string) DI::config()->get('config', 'api_import_size', DI::config()->get('config', 'max_import_size')),
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Module\Api\Mastodon\Accounts;
|
||||
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
||||
/**
|
||||
* @see https://docs.joinmastodon.org/methods/accounts/#lookup
|
||||
*/
|
||||
class Lookup extends BaseApi
|
||||
{
|
||||
/**
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
*/
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
$this->checkAllowedScope(self::SCOPE_READ);
|
||||
$uid = self::getCurrentUserID();
|
||||
|
||||
$request = $this->getRequest([
|
||||
'acct' => '', // The username or Webfinger address to lookup.
|
||||
], $request);
|
||||
|
||||
if (empty($request['acct'])) {
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
}
|
||||
$contact = Contact::getByURL($request['acct'], null, ['id', 'network', 'failed', 'blocked']);
|
||||
if (empty($contact) || ($contact['network'] == Protocol::PHANTOM) || $contact['failed'] || $contact['blocked']) {
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
}
|
||||
|
||||
$this->jsonExit(DI::mstdnAccount()->createFromContactId($contact['id'], $uid));
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon\Apps;
|
||||
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon;
|
||||
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
|
|
@ -38,7 +38,7 @@ use Friendica\Util\Strings;
|
|||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @see https://docs.joinmastodon.org/api/rest/instances/
|
||||
* @see https://docs.joinmastodon.org/methods/instance/
|
||||
*/
|
||||
class Instance extends BaseApi
|
||||
{
|
||||
|
@ -95,7 +95,7 @@ class Instance extends BaseApi
|
|||
|
||||
return new InstanceV2Entity\Configuration(
|
||||
$statuses_config,
|
||||
new InstanceV2Entity\MediaAttachmentsConfig(array_keys(Images::supportedTypes()), $image_size_limit, $image_matrix_limit),
|
||||
new InstanceV2Entity\MediaAttachmentsConfig(Images::supportedMimeTypes(), $image_size_limit, $image_matrix_limit),
|
||||
new InstanceV2Entity\Polls(),
|
||||
new InstanceV2Entity\Accounts(),
|
||||
);
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2024, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Module\Api\Mastodon\Instance;
|
||||
|
||||
use DateTime;
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\Api\ApiResponse;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Object\Api\Mastodon;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @see https://docs.joinmastodon.org/methods/instance/#extended_description
|
||||
*/
|
||||
class ExtendedDescription extends BaseApi
|
||||
{
|
||||
private IManageConfigValues $config;
|
||||
|
||||
public function __construct(\Friendica\Factory\Api\Mastodon\Error $errorFactory, App $app, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, ApiResponse $response, IManageConfigValues $config, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($errorFactory, $app, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
protected function rawContent(array $request = [])
|
||||
{
|
||||
$account = User::getSystemAccount();
|
||||
|
||||
$this->jsonExit(new Mastodon\ExtendedDescription(new DateTime($account['updated']), $this->config->get('config', 'info')));
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@
|
|||
namespace Friendica\Module\Api\Mastodon\Instance;
|
||||
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\Model\GServer;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
|
|
@ -21,10 +21,7 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon\Instance;
|
||||
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\HTML;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ class InstanceV2 extends BaseApi
|
|||
|
||||
return new InstanceEntity\Configuration(
|
||||
$statuses_config,
|
||||
new InstanceEntity\MediaAttachmentsConfig(array_keys(Images::supportedTypes()), $image_size_limit, $image_matrix_limit),
|
||||
new InstanceEntity\MediaAttachmentsConfig(Images::supportedMimeTypes(), $image_size_limit, $image_matrix_limit),
|
||||
new InstanceEntity\Polls(),
|
||||
new InstanceEntity\Accounts(),
|
||||
);
|
||||
|
@ -166,9 +166,9 @@ class InstanceV2 extends BaseApi
|
|||
|
||||
private function buildRegistrationsInfo(): InstanceEntity\Registrations
|
||||
{
|
||||
$register_policy = intval($this->config->get('config', 'register_policy'));
|
||||
$enabled = ($register_policy != Register::CLOSED);
|
||||
$approval_required = ($register_policy == Register::APPROVE);
|
||||
$register_policy = Register::getPolicy();
|
||||
$enabled = $register_policy !== Register::CLOSED;
|
||||
$approval_required = $register_policy === Register::APPROVE;
|
||||
|
||||
return new InstanceEntity\Registrations($enabled, $approval_required);
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ class Markers extends BaseApi
|
|||
$values->{$marker['timeline']} = [
|
||||
'last_read_id' => $marker['last_read_id'],
|
||||
'version' => $marker['version'],
|
||||
'updated_at' => $marker['updated_at']
|
||||
'updated_at' => DateTimeFormat::utc($marker['updated_at'], DateTimeFormat::JSON)
|
||||
];
|
||||
}
|
||||
return $values;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon;
|
||||
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
|
@ -39,15 +38,6 @@ class Mutes extends BaseApi
|
|||
$this->checkAllowedScope(self::SCOPE_READ);
|
||||
$uid = self::getCurrentUserID();
|
||||
|
||||
if (empty($this->parameters['id'])) {
|
||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
||||
}
|
||||
|
||||
$id = $this->parameters['id'];
|
||||
if (!DBA::exists('contact', ['id' => $id, 'uid' => 0])) {
|
||||
$this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
|
||||
}
|
||||
|
||||
$request = $this->getRequest([
|
||||
'max_id' => 0, // Return results older than this id
|
||||
'since_id' => 0, // Return results newer than this id
|
||||
|
@ -57,7 +47,7 @@ class Mutes extends BaseApi
|
|||
|
||||
$params = ['order' => ['cid' => true], 'limit' => $request['limit']];
|
||||
|
||||
$condition = ['cid' => $id, 'ignored' => true, 'uid' => $uid];
|
||||
$condition = ['ignored' => true, 'uid' => $uid];
|
||||
|
||||
if (!empty($request['max_id'])) {
|
||||
$condition = DBA::mergeConditions($condition, ["`cid` < ?", $request['max_id']]);
|
||||
|
@ -74,6 +64,7 @@ class Mutes extends BaseApi
|
|||
}
|
||||
|
||||
$followers = DBA::select('user-contact', ['cid'], $condition, $params);
|
||||
$accounts = [];
|
||||
while ($follower = DBA::fetch($followers)) {
|
||||
self::setBoundaries($follower['cid']);
|
||||
$accounts[] = DI::mstdnAccount()->createFromContactId($follower['cid'], $uid);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
namespace Friendica\Module\Api\Mastodon;
|
||||
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
|
|
@ -137,6 +137,10 @@ class Search extends BaseApi
|
|||
private static function searchStatuses(int $uid, string $q, string $account_id, int $max_id, int $min_id, int $limit, int $offset)
|
||||
{
|
||||
if (Network::isValidHttpUrl($q)) {
|
||||
// Unique post search, any offset greater than 0 should return empty result
|
||||
if ($offset > 0) {
|
||||
return [];
|
||||
}
|
||||
$q = Network::convertToIdn($q);
|
||||
// If the user-specific search failed, we search and probe a public post
|
||||
$item_id = Item::fetchByLink($q, $uid) ?: Item::fetchByLink($q);
|
||||
|
@ -158,6 +162,10 @@ class Search extends BaseApi
|
|||
$table = 'post-searchindex';
|
||||
}
|
||||
|
||||
if (!empty($account_id)) {
|
||||
$condition = DBA::mergeConditions($condition, ["`author-id` = ?", $account_id]);
|
||||
}
|
||||
|
||||
if (!empty($max_id)) {
|
||||
$condition = DBA::mergeConditions($condition, ["`uri-id` < ?", $max_id]);
|
||||
}
|
||||
|
|
|
@ -403,11 +403,10 @@ class Statuses extends BaseApi
|
|||
|
||||
Photo::setPermissionForResource($media[0]['resource-id'], $item['uid'], $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
|
||||
|
||||
$phototypes = Images::supportedTypes();
|
||||
$ext = $phototypes[$media[0]['type']];
|
||||
$ext = Images::getExtensionByMimeType($media[0]['type']);
|
||||
|
||||
$attachment = ['type' => Post\Media::IMAGE, 'mimetype' => $media[0]['type'],
|
||||
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . '.' . $ext,
|
||||
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . $ext,
|
||||
'size' => $media[0]['datasize'],
|
||||
'name' => $media[0]['filename'] ?: $media[0]['resource-id'],
|
||||
'description' => $media[0]['desc'] ?? '',
|
||||
|
@ -415,7 +414,7 @@ class Statuses extends BaseApi
|
|||
'height' => $media[0]['height']];
|
||||
|
||||
if (count($media) > 1) {
|
||||
$attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . '.' . $ext;
|
||||
$attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . $ext;
|
||||
$attachment['preview-width'] = $media[1]['width'];
|
||||
$attachment['preview-height'] = $media[1]['height'];
|
||||
}
|
||||
|
|
|
@ -129,7 +129,11 @@ class Context extends BaseApi
|
|||
$display_quotes = self::appSupportsQuotes();
|
||||
|
||||
foreach (array_slice($ancestors, 0, $request['limit']) as $ancestor) {
|
||||
$statuses['ancestors'][] = DI::mstdnStatus()->createFromUriId($ancestor, $uid, $display_quotes);
|
||||
try {
|
||||
$statuses['ancestors'][] = DI::mstdnStatus()->createFromUriId($ancestor, $uid, $display_quotes);
|
||||
} catch (\Throwable $th) {
|
||||
$this->logger->info('Post not fetchable', ['uri-id' => $ancestor, 'uid' => $uid, 'error' => $th]);
|
||||
}
|
||||
}
|
||||
|
||||
$descendants = array_diff(self::getChildren($id, $children), $deleted);
|
||||
|
@ -137,7 +141,11 @@ class Context extends BaseApi
|
|||
asort($descendants);
|
||||
|
||||
foreach (array_slice($descendants, 0, $request['limit']) as $descendant) {
|
||||
$statuses['descendants'][] = DI::mstdnStatus()->createFromUriId($descendant, $uid, $display_quotes);
|
||||
try {
|
||||
$statuses['descendants'][] = DI::mstdnStatus()->createFromUriId($descendant, $uid, $display_quotes);
|
||||
} catch (\Throwable $th) {
|
||||
$this->logger->info('Post not fetchable', ['uri-id' => $descendant, 'uid' => $uid, 'error' => $th]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->jsonExit($statuses);
|
||||
|
|
|
@ -155,13 +155,12 @@ class Update extends BaseApi
|
|||
|
||||
Photo::setPermissionForResource($media[0]['resource-id'], $uid, $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
|
||||
|
||||
$phototypes = Images::supportedTypes();
|
||||
$ext = $phototypes[$media[0]['type']];
|
||||
$ext = Images::getExtensionByMimeType($media[0]['type']);
|
||||
|
||||
$attachment = [
|
||||
'type' => Post\Media::IMAGE,
|
||||
'mimetype' => $media[0]['type'],
|
||||
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . '.' . $ext,
|
||||
'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . $ext,
|
||||
'size' => $media[0]['datasize'],
|
||||
'name' => $media[0]['filename'] ?: $media[0]['resource-id'],
|
||||
'description' => $media[0]['desc'] ?? '',
|
||||
|
@ -170,7 +169,7 @@ class Update extends BaseApi
|
|||
];
|
||||
|
||||
if (count($media) > 1) {
|
||||
$attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . '.' . $ext;
|
||||
$attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . $ext;
|
||||
$attachment['preview-width'] = $media[1]['width'];
|
||||
$attachment['preview-height'] = $media[1]['height'];
|
||||
}
|
||||
|
|
|
@ -65,11 +65,7 @@ class Attach extends BaseModule
|
|||
// error in Chrome for filenames with commas in them
|
||||
header('Content-type: ' . $item['filetype']);
|
||||
header('Content-length: ' . $item['filesize']);
|
||||
if (isset($_GET['attachment']) && $_GET['attachment'] === '0') {
|
||||
header('Content-disposition: filename="' . $item['filename'] . '"');
|
||||
} else {
|
||||
header('Content-disposition: attachment; filename="' . $item['filename'] . '"');
|
||||
}
|
||||
header('Content-disposition: attachment; filename="' . $item['filename'] . '"');
|
||||
|
||||
echo $data;
|
||||
System::exit();
|
||||
|
|
|
@ -104,7 +104,7 @@ abstract class BaseAdmin extends BaseModule
|
|||
'logsview' => ['admin/logs/view' , DI::l10n()->t('View Logs') , 'viewlogs'],
|
||||
]],
|
||||
'diagnostics' => [DI::l10n()->t('Diagnostics'), [
|
||||
'phpinfo' => ['admin/phpinfo' , DI::l10n()->t('PHP Info') , 'phpinfo'],
|
||||
'phpinfo' => ['admin/phpinfo?t=' . self::getFormSecurityToken('phpinfo'), DI::l10n()->t('PHP Info') , 'phpinfo'],
|
||||
'probe' => ['probe' , DI::l10n()->t('probe address') , 'probe'],
|
||||
'webfinger' => ['webfinger' , DI::l10n()->t('check webfinger') , 'webfinger'],
|
||||
'babel' => ['babel' , DI::l10n()->t('Babel') , 'babel'],
|
||||
|
|
|
@ -42,7 +42,7 @@ class Bookmarklet extends BaseModule
|
|||
|
||||
if (!DI::userSession()->getLocalUserId()) {
|
||||
$output = '<h2>' . DI::l10n()->t('Login') . '</h2>';
|
||||
$output .= Login::form(DI::args()->getQueryString(), intval($config->get('config', 'register_policy')) === Register::CLOSED ? false : true);
|
||||
$output .= Login::form(DI::args()->getQueryString(), Register::getPolicy() !== Register::CLOSED);
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,8 @@ class API extends BaseModule
|
|||
{
|
||||
$eventId = !empty($request['event_id']) ? intval($request['event_id']) : 0;
|
||||
$uid = (int)$this->session->getLocalUserId();
|
||||
$cid = !empty($request['cid']) ? intval($request['cid']) : 0;
|
||||
// No overwriting event.cid on edit
|
||||
$cid = !empty($request['cid']) && !$eventId ? intval($request['cid']) : 0;
|
||||
|
||||
$strStartDateTime = Strings::escapeHtml($request['start_text'] ?? '');
|
||||
$strFinishDateTime = Strings::escapeHtml($request['finish_text'] ?? '');
|
||||
|
|
|
@ -141,13 +141,15 @@ class Circle extends BaseModule
|
|||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
$change = false;
|
||||
$change = false;
|
||||
$relation = $request['rel'] ?? '';
|
||||
|
||||
if (!DI::userSession()->getLocalUserId()) {
|
||||
throw new \Friendica\Network\HTTPException\ForbiddenException();
|
||||
}
|
||||
|
||||
DI::page()['aside'] = Model\Circle::sidebarWidget('contact', 'circle', 'extended', ((DI::args()->getArgc() > 1) ? DI::args()->getArgv()[1] : 'everyone'));
|
||||
DI::page()['aside'] .= Widget::contactRels($this->server['REQUEST_URI'], $relation);
|
||||
|
||||
// With no circle number provided we jump to the unassigned contacts as a starting point
|
||||
// @TODO: Replace with parameter from router
|
||||
|
@ -298,6 +300,9 @@ class Circle extends BaseModule
|
|||
|
||||
// Format the data of the circle members
|
||||
foreach ($members as $member) {
|
||||
if (!self::matchRelation($relation, $member['rel'])) {
|
||||
continue;
|
||||
}
|
||||
if ($member['url']) {
|
||||
$entry = Contact::getContactTemplateVars($member);
|
||||
$entry['label'] = 'members';
|
||||
|
@ -332,6 +337,9 @@ class Circle extends BaseModule
|
|||
if (DBA::isResult($contacts)) {
|
||||
// Format the data of the contacts who aren't in the contact circle
|
||||
foreach ($contacts as $member) {
|
||||
if (!self::matchRelation($relation, $member['rel'])) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($member['id'], $preselected)) {
|
||||
$entry = Contact::getContactTemplateVars($member);
|
||||
$entry['label'] = 'contacts';
|
||||
|
@ -366,4 +374,19 @@ class Circle extends BaseModule
|
|||
|
||||
return Renderer::replaceMacros($tpl, $context);
|
||||
}
|
||||
|
||||
private static function matchRelation(string $relation, int $rel)
|
||||
{
|
||||
switch ($relation) {
|
||||
case 'followers':
|
||||
return($rel == Model\Contact::FOLLOWER);
|
||||
case 'following':
|
||||
return($rel == Model\Contact::SHARING);
|
||||
case 'mutuals':
|
||||
return($rel == Model\Contact::FRIEND);
|
||||
case 'nothing':
|
||||
return($rel == Model\Contact::NOTHING);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,32 +95,32 @@ class Profile extends BaseModule
|
|||
return;
|
||||
}
|
||||
|
||||
Hook::callAll('contact_edit_post', $_POST);
|
||||
Hook::callAll('contact_edit_post', $request);
|
||||
|
||||
$fields = [];
|
||||
|
||||
if (isset($_POST['hidden'])) {
|
||||
$fields['hidden'] = !empty($_POST['hidden']);
|
||||
if (isset($request['hidden'])) {
|
||||
$fields['hidden'] = !empty($request['hidden']);
|
||||
}
|
||||
|
||||
if (isset($_POST['notify_new_posts'])) {
|
||||
$fields['notify_new_posts'] = !empty($_POST['notify_new_posts']);
|
||||
if (isset($request['notify_new_posts'])) {
|
||||
$fields['notify_new_posts'] = !empty($request['notify_new_posts']);
|
||||
}
|
||||
|
||||
if (isset($_POST['fetch_further_information'])) {
|
||||
$fields['fetch_further_information'] = intval($_POST['fetch_further_information']);
|
||||
if (isset($request['fetch_further_information'])) {
|
||||
$fields['fetch_further_information'] = intval($request['fetch_further_information']);
|
||||
}
|
||||
|
||||
if (isset($_POST['remote_self'])) {
|
||||
$fields['remote_self'] = intval($_POST['remote_self']);
|
||||
if (isset($request['remote_self'])) {
|
||||
$fields['remote_self'] = intval($request['remote_self']);
|
||||
}
|
||||
|
||||
if (isset($_POST['ffi_keyword_denylist'])) {
|
||||
$fields['ffi_keyword_denylist'] = $_POST['ffi_keyword_denylist'];
|
||||
if (isset($request['ffi_keyword_denylist'])) {
|
||||
$fields['ffi_keyword_denylist'] = $request['ffi_keyword_denylist'];
|
||||
}
|
||||
|
||||
if (isset($_POST['poll'])) {
|
||||
$priority = intval($_POST['poll']);
|
||||
if (isset($request['poll'])) {
|
||||
$priority = intval($request['poll']);
|
||||
if ($priority > 5 || $priority < 0) {
|
||||
$priority = 0;
|
||||
}
|
||||
|
@ -128,12 +128,16 @@ class Profile extends BaseModule
|
|||
$fields['priority'] = $priority;
|
||||
}
|
||||
|
||||
if (isset($_POST['info'])) {
|
||||
$fields['info'] = $_POST['info'];
|
||||
if (isset($request['info'])) {
|
||||
$fields['info'] = $request['info'];
|
||||
}
|
||||
|
||||
if (isset($_POST['channel_frequency'])) {
|
||||
Contact\User::setChannelFrequency($cdata['user'], $this->session->getLocalUserId(), $_POST['channel_frequency']);
|
||||
if (isset($request['channel_frequency'])) {
|
||||
Contact\User::setChannelFrequency($cdata['user'], $this->session->getLocalUserId(), $request['channel_frequency']);
|
||||
}
|
||||
|
||||
if (isset($request['channel_only'])) {
|
||||
Contact\User::setChannelOnly($cdata['user'], $this->session->getLocalUserId(), $request['channel_only']);
|
||||
}
|
||||
|
||||
if (!Contact::update($fields, ['id' => $cdata['user'], 'uid' => $this->session->getLocalUserId()])) {
|
||||
|
@ -340,7 +344,8 @@ class Profile extends BaseModule
|
|||
];
|
||||
}
|
||||
|
||||
$channel_frequency = Contact\User::getChannelFrequency($contact['id'], $this->session->getLocalUserId());
|
||||
$channel_frequency = Contact\User::getChannelFrequency($contact['id'], $this->session->getLocalUserId());
|
||||
$channel_only = Contact\User::getChannelOnly($contact['id'], $this->session->getLocalUserId());
|
||||
|
||||
$poll_interval = null;
|
||||
if ((($contact['network'] == Protocol::FEED) && !$this->config->get('system', 'adjust_poll_frequency')) || ($contact['network'] == Protocol::MAIL)) {
|
||||
|
@ -432,6 +437,7 @@ class Profile extends BaseModule
|
|||
'$frequency_always' => ['channel_frequency', $this->t('Display all posts of this contact'), Contact\User::FREQUENCY_ALWAYS, $this->t('All posts from this contact will appear on the "for you" channel'), $channel_frequency == Contact\User::FREQUENCY_ALWAYS],
|
||||
'$frequency_reduced' => ['channel_frequency', $this->t('Display only few posts'), Contact\User::FREQUENCY_REDUCED, $this->t('When a contact creates a lot of posts in a short period, this setting reduces the number of displayed posts in every channel.'), $channel_frequency == Contact\User::FREQUENCY_REDUCED],
|
||||
'$frequency_never' => ['channel_frequency', $this->t('Never display posts'), Contact\User::FREQUENCY_NEVER, $this->t('Posts from this contact will never be displayed in any channel'), $channel_frequency == Contact\User::FREQUENCY_NEVER],
|
||||
'$channel_only' => ['channel_only', $this->t('Channel Only'), $channel_only, $this->t('If enabled, posts from this contact will only appear in channels, but not in the network stream.')],
|
||||
]);
|
||||
|
||||
$arr = ['contact' => $contact, 'output' => $o];
|
||||
|
|
|
@ -65,8 +65,6 @@ class Network extends Timeline
|
|||
/** @var int */
|
||||
protected $circleId;
|
||||
/** @var string */
|
||||
protected $network;
|
||||
/** @var string */
|
||||
protected $dateFrom;
|
||||
/** @var string */
|
||||
protected $dateTo;
|
||||
|
|
|
@ -74,6 +74,8 @@ class Timeline extends BaseModule
|
|||
protected $raw;
|
||||
/** @var string */
|
||||
protected $order;
|
||||
/** @var string */
|
||||
protected $network;
|
||||
|
||||
/** @var App\Mode $mode */
|
||||
protected $mode;
|
||||
|
@ -176,11 +178,11 @@ class Timeline extends BaseModule
|
|||
protected function getNoSharerWidget(string $base): string
|
||||
{
|
||||
$path = $this->selectedTab;
|
||||
if (!empty($this->accountTypeString)) {
|
||||
$path .= '/' . $this->accountTypeString;
|
||||
}
|
||||
$query_parameters = [];
|
||||
|
||||
$query_parameters = [];
|
||||
if (!empty($this->accountTypeString)) {
|
||||
$query_parameters['accounttype'] = $this->accountTypeString;
|
||||
}
|
||||
if (!empty($this->minId)) {
|
||||
$query_parameters['min_id'] = $this->minId;
|
||||
}
|
||||
|
@ -345,6 +347,13 @@ class Timeline extends BaseModule
|
|||
AND NOT `cid` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ?))",
|
||||
DateTimeFormat::utc('now - ' . $this->config->get('channel', 'sharer_interaction_days') . ' day'), $cid, $this->getMedianRelationThreadScore($cid, 4), $cid
|
||||
];
|
||||
} elseif ($this->selectedTab == ChannelEntity::QUIETSHARERS) {
|
||||
$cid = Contact::getPublicIdByUserId($uid);
|
||||
|
||||
$condition = [
|
||||
"`owner-id` IN (SELECT `cid` FROM `contact-relation` WHERE `follows` AND `relation-cid` = ? AND `post-score` <= ?)",
|
||||
$cid, $this->getMedianPostScore($cid, 2)
|
||||
];
|
||||
} elseif ($this->selectedTab == ChannelEntity::IMAGE) {
|
||||
$condition = ["`media-type` & ?", 1];
|
||||
} elseif ($this->selectedTab == ChannelEntity::VIDEO) {
|
||||
|
@ -365,6 +374,10 @@ class Timeline extends BaseModule
|
|||
|
||||
$this->setMaxMinByOrder($request);
|
||||
|
||||
if (!empty($this->network)) {
|
||||
$condition = DBA::mergeConditions($condition, ['network' => $this->network]);
|
||||
}
|
||||
|
||||
if (($this->selectedTab != ChannelEntity::LANGUAGE) && !is_numeric($this->selectedTab)) {
|
||||
$condition = $this->addLanguageCondition($uid, $condition);
|
||||
}
|
||||
|
@ -634,6 +647,28 @@ class Timeline extends BaseModule
|
|||
return $score;
|
||||
}
|
||||
|
||||
private function getMedianPostScore(int $cid, int $divider): int
|
||||
{
|
||||
$cache_key = 'Channel:getPostScore:' . $cid . ':' . $divider;
|
||||
$score = $this->cache->get($cache_key);
|
||||
if (!empty($score)) {
|
||||
return $score;
|
||||
}
|
||||
|
||||
$condition = ["`relation-cid` = ? AND `post-score` > ?", $cid, 0];
|
||||
|
||||
$limit = $this->database->count('contact-relation', $condition) / $divider;
|
||||
$relation = $this->database->selectToArray('contact-relation', ['post-score'], $condition, ['order' => ['post-score' => true], 'limit' => [$limit, 1]]);
|
||||
$score = $relation[0]['post-score'] ?? 0;
|
||||
if (empty($score)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$this->cache->set($cache_key, $score, Duration::HALF_HOUR);
|
||||
$this->logger->debug('Calculated median score', ['cid' => $cid, 'divider' => $divider, 'median' => $score]);
|
||||
return $score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the displayed items.
|
||||
*
|
||||
|
|
|
@ -43,10 +43,11 @@ class Babel extends BaseModule
|
|||
}
|
||||
|
||||
$results = [];
|
||||
if (!empty($_REQUEST['text'])) {
|
||||
switch (($_REQUEST['type'] ?? '') ?: 'bbcode') {
|
||||
if (!empty($request['text'])) {
|
||||
self::checkFormSecurityTokenForbiddenOnError('babel');
|
||||
switch (($request['type'] ?? '') ?: 'bbcode') {
|
||||
case 'bbcode':
|
||||
$bbcode = $_REQUEST['text'];
|
||||
$bbcode = $request['text'];
|
||||
$results[] = [
|
||||
'title' => DI::l10n()->t('Source input'),
|
||||
'content' => visible_whitespace($bbcode)
|
||||
|
@ -136,7 +137,7 @@ class Babel extends BaseModule
|
|||
];
|
||||
break;
|
||||
case 'diaspora':
|
||||
$diaspora = trim($_REQUEST['text']);
|
||||
$diaspora = trim($request['text']);
|
||||
$results[] = [
|
||||
'title' => DI::l10n()->t('Source input (Diaspora format)'),
|
||||
'content' => visible_whitespace($diaspora),
|
||||
|
@ -144,7 +145,7 @@ class Babel extends BaseModule
|
|||
|
||||
$markdown = XML::unescape($diaspora);
|
||||
case 'markdown':
|
||||
$markdown = $markdown ?? trim($_REQUEST['text']);
|
||||
$markdown = $markdown ?? trim($request['text']);
|
||||
|
||||
$results[] = [
|
||||
'title' => DI::l10n()->t('Source input (Markdown)'),
|
||||
|
@ -169,7 +170,7 @@ class Babel extends BaseModule
|
|||
];
|
||||
break;
|
||||
case 'html' :
|
||||
$html = trim($_REQUEST['text']);
|
||||
$html = trim($request['text']);
|
||||
$results[] = [
|
||||
'title' => DI::l10n()->t('Raw HTML input'),
|
||||
'content' => visible_whitespace($html),
|
||||
|
@ -239,7 +240,7 @@ class Babel extends BaseModule
|
|||
];
|
||||
break;
|
||||
case 'twitter':
|
||||
$json = trim($_REQUEST['text']);
|
||||
$json = trim($request['text']);
|
||||
|
||||
if (file_exists('addon/twitter/twitter.php')) {
|
||||
require_once 'addon/twitter/twitter.php';
|
||||
|
@ -302,13 +303,14 @@ class Babel extends BaseModule
|
|||
$tpl = Renderer::getMarkupTemplate('babel.tpl');
|
||||
$o = Renderer::replaceMacros($tpl, [
|
||||
'$title' => DI::l10n()->t('Babel Diagnostic'),
|
||||
'$text' => ['text', DI::l10n()->t('Source text'), $_REQUEST['text'] ?? '', ''],
|
||||
'$type_bbcode' => ['type', DI::l10n()->t('BBCode'), 'bbcode', '', (($_REQUEST['type'] ?? '') ?: 'bbcode') == 'bbcode'],
|
||||
'$type_diaspora' => ['type', DI::l10n()->t('Diaspora'), 'diaspora', '', (($_REQUEST['type'] ?? '') ?: 'bbcode') == 'diaspora'],
|
||||
'$type_markdown' => ['type', DI::l10n()->t('Markdown'), 'markdown', '', (($_REQUEST['type'] ?? '') ?: 'bbcode') == 'markdown'],
|
||||
'$type_html' => ['type', DI::l10n()->t('HTML'), 'html', '', (($_REQUEST['type'] ?? '') ?: 'bbcode') == 'html'],
|
||||
'$form_security_token' => self::getFormSecurityToken('babel'),
|
||||
'$text' => ['text', DI::l10n()->t('Source text'), $request['text'] ?? '', ''],
|
||||
'$type_bbcode' => ['type', DI::l10n()->t('BBCode'), 'bbcode', '', (($request['type'] ?? '') ?: 'bbcode') == 'bbcode'],
|
||||
'$type_diaspora' => ['type', DI::l10n()->t('Diaspora'), 'diaspora', '', (($request['type'] ?? '') ?: 'bbcode') == 'diaspora'],
|
||||
'$type_markdown' => ['type', DI::l10n()->t('Markdown'), 'markdown', '', (($request['type'] ?? '') ?: 'bbcode') == 'markdown'],
|
||||
'$type_html' => ['type', DI::l10n()->t('HTML'), 'html', '', (($request['type'] ?? '') ?: 'bbcode') == 'html'],
|
||||
'$flag_twitter' => file_exists('addon/twitter/twitter.php'),
|
||||
'$type_twitter' => ['type', DI::l10n()->t('Twitter Source / Tweet URL (requires API key)'), 'twitter', '', (($_REQUEST['type'] ?? '') ?: 'bbcode') == 'twitter'],
|
||||
'$type_twitter' => ['type', DI::l10n()->t('Twitter Source / Tweet URL (requires API key)'), 'twitter', '', (($request['type'] ?? '') ?: 'bbcode') == 'twitter'],
|
||||
'$results' => $results,
|
||||
'$submit' => DI::l10n()->t('Submit'),
|
||||
]);
|
||||
|
|
|
@ -30,7 +30,6 @@ use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
|||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\PostUpdate;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Network\HTTPException;
|
||||
|
@ -154,7 +153,7 @@ class Friendica extends BaseModule
|
|||
Register::OPEN => 'REGISTER_OPEN'
|
||||
];
|
||||
|
||||
$register_policy_int = $this->config->get('config', 'register_policy');
|
||||
$register_policy_int = Register::getPolicy();
|
||||
if ($register_policy_int !== Register::CLOSED && $this->config->get('config', 'invitation_only')) {
|
||||
$register_policy = 'REGISTER_INVITATION';
|
||||
} else {
|
||||
|
|
|
@ -73,7 +73,7 @@ class Home extends BaseModule
|
|||
}
|
||||
}
|
||||
|
||||
$login = Login::form(DI::args()->getQueryString(), $config->get('config', 'register_policy') === Register::CLOSED ? 0 : 1);
|
||||
$login = Login::form(DI::args()->getQueryString(), Register::getPolicy() !== Register::CLOSED);
|
||||
|
||||
$content = '';
|
||||
Hook::callAll('home_content', $content);
|
||||
|
|
|
@ -146,14 +146,14 @@ class Invite extends BaseModule
|
|||
|
||||
$dirLocation = Search::getGlobalDirectory();
|
||||
if (strlen($dirLocation)) {
|
||||
if ($config->get('config', 'register_policy') === Register::CLOSED) {
|
||||
if (Register::getPolicy() === Register::CLOSED) {
|
||||
$linkTxt = DI::l10n()->t('Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks.', $dirLocation . '/servers');
|
||||
} else {
|
||||
$linkTxt = DI::l10n()->t('To accept this invitation, please visit and register at %s or any other public Friendica website.', DI::baseUrl() . '/register')
|
||||
. "\r\n" . "\r\n" . DI::l10n()->t('Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join.', $dirLocation . '/servers');
|
||||
}
|
||||
} else { // there is no global directory URL defined
|
||||
if ($config->get('config', 'register_policy') === Register::CLOSED) {
|
||||
if (Register::getPolicy() === Register::CLOSED) {
|
||||
return DI::l10n()->t('Our apologies. This system is not currently configured to connect with other public sites or invite members.');
|
||||
} else {
|
||||
$linkTxt = DI::l10n()->t('To accept this invitation, please visit and register at %s.', DI::baseUrl() . '/register'
|
||||
|
|
|
@ -99,8 +99,7 @@ class Browser extends BaseModule
|
|||
|
||||
protected function map_files(array $record): array
|
||||
{
|
||||
$types = Images::supportedTypes();
|
||||
$ext = $types[$record['type']];
|
||||
$ext = Images::getExtensionByMimeType($record['type']);
|
||||
$filename_e = $record['filename'];
|
||||
|
||||
// Take the largest picture that is smaller or equal 640 pixels
|
||||
|
@ -118,7 +117,7 @@ class Browser extends BaseModule
|
|||
return [
|
||||
sprintf('%s/photos/%s/image/%s', $this->baseUrl, $this->app->getLoggedInUserNickname(), $record['resource-id']),
|
||||
$filename_e,
|
||||
sprintf('%s/photo/%s-%s.%s', $this->baseUrl, $record['resource-id'], $scale, $ext),
|
||||
sprintf('%s/photo/%s-%s%s', $this->baseUrl, $record['resource-id'], $scale, $ext),
|
||||
$record['desc'],
|
||||
];
|
||||
}
|
||||
|
|
|
@ -135,8 +135,6 @@ class Upload extends \Friendica\BaseModule
|
|||
$this->return(401, $this->t('Invalid request.'), true);
|
||||
}
|
||||
|
||||
$filetype = Images::getMimeTypeBySource($src, $filename, $filetype);
|
||||
|
||||
$this->logger->info('File upload:', [
|
||||
'src' => $src,
|
||||
'filename' => $filename,
|
||||
|
@ -145,7 +143,7 @@ class Upload extends \Friendica\BaseModule
|
|||
]);
|
||||
|
||||
$imagedata = @file_get_contents($src);
|
||||
$image = new Image($imagedata, $filetype);
|
||||
$image = new Image($imagedata, $filetype, $filename);
|
||||
|
||||
if (!$image->isValid()) {
|
||||
@unlink($src);
|
||||
|
|
|
@ -57,11 +57,11 @@ class Index extends BaseModeration
|
|||
|
||||
// Edit the entries from blocklist
|
||||
$blocklist = [];
|
||||
foreach ($request['domain'] as $id => $domain) {
|
||||
foreach ((array)$request['domain'] as $id => $domain) {
|
||||
// Trimming whitespaces as well as any lingering slashes
|
||||
$domain = trim($domain);
|
||||
$reason = trim($request['reason'][$id]);
|
||||
if (empty($request['delete'][$id])) {
|
||||
if (empty($request['delete'][$id]) && !empty($domain)) {
|
||||
$blocklist[] = [
|
||||
'domain' => $domain,
|
||||
'reason' => $reason
|
||||
|
|
|
@ -24,7 +24,6 @@ namespace Friendica\Module;
|
|||
use Friendica\App;
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Capabilities\ICanCreateResponses;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\Nodeinfo;
|
||||
|
@ -65,7 +64,7 @@ class NodeInfo110 extends BaseModule
|
|||
],
|
||||
'services' => Nodeinfo::getServices(),
|
||||
'usage' => Nodeinfo::getUsage(),
|
||||
'openRegistrations' => intval($this->config->get('config', 'register_policy')) !== Register::CLOSED,
|
||||
'openRegistrations' => Register::getPolicy() !== Register::CLOSED,
|
||||
'metadata' => [
|
||||
'nodeName' => $this->config->get('config', 'sitename'),
|
||||
],
|
||||
|
|
|
@ -24,7 +24,6 @@ namespace Friendica\Module;
|
|||
use Friendica\App;
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Capabilities\ICanCreateResponses;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\Nodeinfo;
|
||||
|
@ -58,7 +57,7 @@ class NodeInfo120 extends BaseModule
|
|||
'protocols' => ['dfrn', 'activitypub'],
|
||||
'services' => Nodeinfo::getServices(),
|
||||
'usage' => Nodeinfo::getUsage(),
|
||||
'openRegistrations' => intval($this->config->get('config', 'register_policy')) !== Register::CLOSED,
|
||||
'openRegistrations' => Register::getPolicy() !== Register::CLOSED,
|
||||
'metadata' => [
|
||||
'nodeName' => $this->config->get('config', 'sitename'),
|
||||
],
|
||||
|
|
|
@ -24,7 +24,6 @@ namespace Friendica\Module;
|
|||
use Friendica\App;
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Capabilities\ICanCreateResponses;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\Nodeinfo;
|
||||
|
@ -59,7 +58,7 @@ class NodeInfo210 extends BaseModule
|
|||
'organization' => Nodeinfo::getOrganization($this->config),
|
||||
'protocols' => ['dfrn', 'activitypub'],
|
||||
'services' => Nodeinfo::getServices(),
|
||||
'openRegistrations' => intval($this->config->get('config', 'register_policy')) !== Register::CLOSED,
|
||||
'openRegistrations' => Register::getPolicy() !== Register::CLOSED,
|
||||
'usage' => Nodeinfo::getUsage(true),
|
||||
];
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ use Friendica\Core\Hook;
|
|||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\Model\Circle;
|
||||
|
@ -175,7 +174,7 @@ class Ping extends BaseModule
|
|||
$myurl = $this->session->getMyUrl();
|
||||
$mail_count = $this->database->count('mail', ["`uid` = ? AND NOT `seen` AND `from-url` != ?", $this->session->getLocalUserId(), $myurl]);
|
||||
|
||||
if (intval($this->config->get('config', 'register_policy')) === Register::APPROVE && $this->session->isSiteAdmin()) {
|
||||
if (Register::getPolicy() === Register::APPROVE && $this->session->isSiteAdmin()) {
|
||||
$registrations = \Friendica\Model\Register::getPending();
|
||||
$register_count = count($registrations);
|
||||
}
|
||||
|
|
|
@ -21,10 +21,7 @@
|
|||
|
||||
namespace Friendica\Module\OAuth;
|
||||
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Module\BaseApi;
|
||||
use Friendica\Module\Special\HTTPException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue