mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-22 01:17:41 -04:00
Compare commits
118 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89a1af1794 | ||
|
|
d5e0c24e13 | ||
|
|
8fe73d73ce | ||
|
|
7559d6bb5c | ||
|
|
6c40576f94 | ||
|
|
1c9c0dc70e | ||
|
|
bf4227bfef | ||
|
|
c296d4bbed | ||
|
|
68452fb07b | ||
|
|
7f98cd606b | ||
|
|
d0ae7a0493 | ||
|
|
81e79eec04 | ||
|
|
7d70f2f0f2 | ||
|
|
016a11ad27 | ||
|
|
1637e61681 | ||
|
|
1ec0e91405 | ||
|
|
3ab52a060b | ||
|
|
866cd52073 | ||
|
|
1774140307 | ||
|
|
698dce044d | ||
|
|
bf0d73515e | ||
|
|
8152da1275 | ||
|
|
01de48b994 | ||
|
|
eb10820195 | ||
|
|
9d33456c89 | ||
|
|
56c7f76230 | ||
|
|
3dd9559d9f | ||
|
|
51ac502d97 | ||
|
|
955ee217e3 | ||
|
|
6d8bfe58ef | ||
|
|
f98f540256 | ||
|
|
54c7319075 | ||
|
|
72c930f964 | ||
|
|
ce24b86841 | ||
|
|
f63ba541d7 | ||
|
|
a9f54473db | ||
|
|
eb5ea6536b | ||
|
|
2e9b64347d | ||
|
|
4fcff43fb5 | ||
|
|
260b61ba3b | ||
|
|
d0b7e4ea79 | ||
|
|
33c95c810a | ||
|
|
81105ff9de | ||
|
|
ced3113516 | ||
|
|
cbd208eea3 | ||
|
|
ad85825cab | ||
|
|
2fb816139a | ||
|
|
c9166b26c5 | ||
|
|
86d58065b3 | ||
|
|
1f265cc6d5 | ||
|
|
4474fdd4f9 | ||
|
|
f71eeab5be | ||
|
|
b3526415f9 | ||
|
|
471ded3efa | ||
|
|
e954d8c55e | ||
|
|
70f82c3967 | ||
|
|
707e07bbbc | ||
|
|
e89eb04427 | ||
|
|
ae0e82ee3a | ||
|
|
9ea5d20a3d | ||
|
|
fd69008484 | ||
|
|
3256aa8be9 | ||
|
|
add26a5b5f | ||
|
|
dc03263bef | ||
|
|
1897cd0b1b | ||
|
|
ba24958b37 | ||
|
|
52a2a0d89a | ||
|
|
91944da69e | ||
|
|
78e30a4d32 | ||
|
|
ccd6d1a38c | ||
|
|
f14c1be963 | ||
|
|
db5e92b72d | ||
|
|
3d3580b23f | ||
|
|
04d44c9965 | ||
|
|
82bd91d9d7 | ||
|
|
492533729d | ||
|
|
283b606c09 | ||
|
|
b0b5523f2b | ||
|
|
738797467d | ||
|
|
a2ee5705f4 | ||
|
|
cc1713b69a | ||
|
|
6f5e4c5c2e | ||
|
|
3e0b9c01b6 | ||
|
|
25218fea43 | ||
|
|
c907e569f1 | ||
|
|
b6bec6f7b7 | ||
|
|
31b5cfe7ef | ||
|
|
0efb3c5c95 | ||
|
|
d88f3169c8 | ||
|
|
3772e910df | ||
|
|
e995d45b53 | ||
|
|
669136bce7 | ||
|
|
2448e6df27 | ||
|
|
4c0b37db66 | ||
|
|
0ea3f3d36d | ||
|
|
cb7dc2059a | ||
|
|
e988bc9fae | ||
|
|
cb23a9e235 | ||
|
|
8d9623674d | ||
|
|
6d181ee69e | ||
|
|
2d97f8fa25 | ||
|
|
98a3c97820 | ||
|
|
89e1328ed0 | ||
|
|
5cb4db0353 | ||
|
|
dc43cd9a85 | ||
|
|
5a6a7386a8 | ||
|
|
4f545e31dd | ||
|
|
437c0a8913 | ||
|
|
268fccdb30 | ||
|
|
bb7689be93 | ||
|
|
bd63af69b2 | ||
|
|
e5d4358d61 | ||
|
|
0fa4962620 | ||
|
|
fe4d6229a4 | ||
|
|
99a1569d07 | ||
|
|
9fb5cd12be | ||
|
|
d85c737db7 | ||
|
|
a0cb5fcb3f |
46
CHANGELOG
46
CHANGELOG
@@ -1,3 +1,49 @@
|
||||
Hubzilla 11.2 (2026-03-26)
|
||||
Features
|
||||
- Introduce parse_webbie() for preparing webbies and URLs for webfinger usage
|
||||
- Allow to override cUrl useragent
|
||||
- New HQ system status widget for admins (sponsored by NLnet NGI0 Commons Fund/Performance Profiling)
|
||||
- Refactor drop_query_params() to deal with array params and add test
|
||||
|
||||
Maintenance
|
||||
- Remove private members from API docs
|
||||
- Remove custom CA certs
|
||||
- Add type annotations in Extend\Route
|
||||
- Set method visibility in Extend\Route
|
||||
- Add API docs and licence info to Extend\Route
|
||||
- Add a short sleep interval to Activity::init_background_fetch() when adding new work items in a loop
|
||||
- Add a short sleep interval to the convo daemon loop to spread the load for large collections
|
||||
- Use PHP matching rules in util/run_xgettext
|
||||
- Store translation templates as .pot instead of .po
|
||||
- Deprecate NULL_DATE constant in favor of DBA::get_null_date()
|
||||
- Composer require guzzlehttp/psr7
|
||||
- Update composer libs
|
||||
- Move HQ channel notifications widget HTML to template
|
||||
- Deprecate tags and attachment in activities
|
||||
- Update the nginx config example to meet the more modern approach
|
||||
|
||||
Bugfixes
|
||||
- Fix route and widget register() not deduplicating entries
|
||||
- Fix issue in route and widget unregister() where we unregistered even if only one of the two arguments did not match
|
||||
- Fix issue in Storage/Directory where we returned a partial path instead of throwing exception if a directory of a path could not be found
|
||||
- Fix possible endless loop in externals daemon
|
||||
- Fix fatal error in italian translation file
|
||||
- Fix mod network not displaying direct messages when filters active - issue #1973
|
||||
- Fix ghost notifications with reshared items - issue #1970
|
||||
- Fix issue with double typed objects in Lib/Activity
|
||||
- Fix events displaying event timezone instead of adjusted to timezone
|
||||
- Fix duplicated terms in activity object
|
||||
- Fix last modified timestamp not updating in attach_store()
|
||||
|
||||
Addons
|
||||
- Wopi: fix headers already set warning when serving the file to the client
|
||||
- Superblock: complete rewrite with extended functionality and added tests for version 3.0 (sponsored by NLnet NGI0 Commons Fund/Superblock)
|
||||
- Diaspora: use Diaspora/2 useragent when fetching hcards to prevent being redirected to some shady bot guard
|
||||
- Add composer config and autoload files for addons
|
||||
- Wopi: return early in construct_page hook and
|
||||
- Wopi: fix wrong hook name in uninstall function
|
||||
|
||||
|
||||
Hubzilla 11.0 (2026-01-30)
|
||||
Features
|
||||
- Rewrite Lib/MessageFilter (ported from forte) and add more tests
|
||||
|
||||
@@ -6,6 +6,7 @@ use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\ASCollection;
|
||||
use Zotlabs\Lib\ASCache;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Convo {
|
||||
|
||||
@@ -33,6 +34,7 @@ class Convo {
|
||||
}
|
||||
|
||||
$force = $argv[4] ?? false;
|
||||
$interval = Config::Get('queueworker', 'queue_interval', 500000);
|
||||
|
||||
foreach ($channels as $channel_id) {
|
||||
$channel = channelx_by_n($channel_id);
|
||||
@@ -46,6 +48,8 @@ class Convo {
|
||||
}
|
||||
|
||||
foreach ($messages as $message) {
|
||||
$network_fetch = false;
|
||||
|
||||
if (is_string($message)) {
|
||||
$cached = ASCache::Get($message);
|
||||
if ($cached) {
|
||||
@@ -54,6 +58,8 @@ class Convo {
|
||||
}
|
||||
else {
|
||||
// logger('convo_fetching: ' . $message);
|
||||
$network_fetch = true;
|
||||
|
||||
$data = Activity::fetch($message, $channel);
|
||||
if ($data) {
|
||||
ASCache::Set($message, $data);
|
||||
@@ -65,6 +71,12 @@ class Convo {
|
||||
$data = $message;
|
||||
}
|
||||
|
||||
if (!$network_fetch) {
|
||||
// Add some delay so that the DB will not be overwhelmed
|
||||
// Fetched from network will already have a slight delay
|
||||
usleep($interval);
|
||||
}
|
||||
|
||||
$AS = new ActivityStreams($data);
|
||||
if ($AS->is_valid() && is_array($AS->obj)) {
|
||||
$item = Activity::decode_note($AS);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\ObjCache;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
@@ -93,7 +94,7 @@ class Cron {
|
||||
// delete expired access tokens
|
||||
|
||||
$r = q("select atoken_id from atoken where atoken_expires > '%s' and atoken_expires < %s",
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
db_utcnow()
|
||||
);
|
||||
if ($r) {
|
||||
|
||||
@@ -74,6 +74,8 @@ class Externals {
|
||||
}
|
||||
}
|
||||
|
||||
$attempts++;
|
||||
|
||||
if (!$url) {
|
||||
continue;
|
||||
}
|
||||
@@ -85,7 +87,6 @@ class Externals {
|
||||
$blacklisted = true;
|
||||
}
|
||||
|
||||
$attempts++;
|
||||
|
||||
// make sure we can eventually break out if somebody blacklists all known sites
|
||||
|
||||
|
||||
@@ -9,10 +9,14 @@ class Onedirsync {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
if ($argc < 2 || is_int($argv[1]) === false) {
|
||||
logger('onedirsync: no update id');
|
||||
return;
|
||||
}
|
||||
|
||||
logger('onedirsync: start ' . intval($argv[1]));
|
||||
|
||||
if (($argc > 1) && (intval($argv[1])))
|
||||
$update_id = intval($argv[1]);
|
||||
$update_id = intval($argv[1]);
|
||||
|
||||
if (!$update_id) {
|
||||
logger('onedirsync: no update id');
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\ASCollection;
|
||||
@@ -15,10 +16,14 @@ class Onepoll {
|
||||
|
||||
static public function run($argc, $argv) {
|
||||
|
||||
if ($argc < 2 || is_int($argv[1]) === false) {
|
||||
logger('onepoll: no contact');
|
||||
return;
|
||||
}
|
||||
|
||||
logger('onepoll: start');
|
||||
|
||||
if (($argc > 1) && (intval($argv[1])))
|
||||
$contact_id = intval($argv[1]);
|
||||
$contact_id = intval($argv[1]);
|
||||
|
||||
if (!$contact_id) {
|
||||
logger('onepoll: no contact');
|
||||
@@ -34,7 +39,7 @@ class Onepoll {
|
||||
$contacts = q("SELECT abook.*, xchan.* FROM abook
|
||||
LEFT JOIN xchan ON xchan_hash = abook_xchan
|
||||
WHERE abook_id = %d",
|
||||
intval($contact_id)
|
||||
$contact_id
|
||||
);
|
||||
|
||||
if (!$contacts) {
|
||||
@@ -53,7 +58,7 @@ class Onepoll {
|
||||
|
||||
logger("onepoll: poll: ($contact_id) IMPORTER: {$importer['xchan_name']}, CONTACT: {$contact['xchan_name']}");
|
||||
|
||||
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= NULL_DATE))
|
||||
$last_update = ((($contact['abook_updated'] === $contact['abook_created']) || ($contact['abook_updated'] <= DBA::$dba->get_null_date()))
|
||||
? datetime_convert('UTC', 'UTC', 'now - 7 days')
|
||||
: datetime_convert('UTC', 'UTC', $contact['abook_updated'] . ' - 2 days')
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
class Poller {
|
||||
@@ -117,7 +118,7 @@ class Poller {
|
||||
|
||||
// if we've never connected with them, start the mark for death countdown from now
|
||||
|
||||
if ($c <= NULL_DATE) {
|
||||
if ($c <= DBA::$dba->get_null_date()) {
|
||||
q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($contact['abook_id'])
|
||||
@@ -173,7 +174,7 @@ class Poller {
|
||||
|
||||
if ($dirmode == DIRECTORY_MODE_SECONDARY || $dirmode == DIRECTORY_MODE_PRIMARY) {
|
||||
$r = q("SELECT * FROM updates WHERE ud_update = 1 AND (ud_last = '%s' OR ud_last > %s - INTERVAL %s)",
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('7 DAY')
|
||||
);
|
||||
@@ -184,7 +185,7 @@ class Poller {
|
||||
// If they didn't respond when we attempted before, back off to once a day
|
||||
// After 7 days we won't bother anymore
|
||||
|
||||
if ($rr['ud_last'] > NULL_DATE)
|
||||
if ($rr['ud_last'] > DBA::$dba->get_null_date())
|
||||
if ($rr['ud_last'] > datetime_convert('UTC', 'UTC', 'now - 1 day'))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -1,23 +1,106 @@
|
||||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018 The Hubzilla Community
|
||||
* SPDX-FileContributor: Zotlabs
|
||||
* SPDX-FileContributor: Mario <mario@mariovavti.com>
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Extend;
|
||||
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
/**
|
||||
* Class for managing routes.
|
||||
*
|
||||
* Routes connect a URL path to a module that will handle requests to that
|
||||
* path.
|
||||
*
|
||||
* For example by registering a route like this:
|
||||
*
|
||||
* ```php
|
||||
* Route::register(
|
||||
* __DIR__ . '/Mod_Myroute.php',
|
||||
* 'myroute'
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* Hubzilla will direct requests to the '/myroute' URL path to the 'Myroute'
|
||||
* controller located in the '/Mod_Myroute.php' file in the same directory as
|
||||
* the file this code was called from.
|
||||
*
|
||||
* Routes are stored persistently, so this function will typically be called from
|
||||
* the `<addon>_load()` function if called from an addon. Accordingly, the route must
|
||||
* be unregistered when no longer needed, like this:
|
||||
*
|
||||
* ```php
|
||||
* Route::unregister(
|
||||
* __DIR__ . '/Mod_Myroute.php',
|
||||
* 'myroute'
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* This will typically be called from the `<addon>_unload()` function in an addon.
|
||||
*/
|
||||
class Route {
|
||||
|
||||
static function register($file,$modname) {
|
||||
/**
|
||||
* Register a new route.
|
||||
*
|
||||
* Example:
|
||||
* ```php
|
||||
* Route::register(
|
||||
* __DIR__ . '/Mod_Myroute.php',
|
||||
* 'myroute'
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* The route is stored persistently, and must be unregistered when no longer needed.
|
||||
*
|
||||
* @param string $file The file containing the controller for handling requests to this route.
|
||||
* @param string $modname The name of the module (URL path).
|
||||
*
|
||||
* @see {@link Zotlabs::Extend::Route.unregister() unregister()}
|
||||
* @see {@link Zotlabs::Extend::Route.unregister_by_file() unregister_by_file()}
|
||||
*/
|
||||
public static function register(string $file, string $modname): void {
|
||||
$rt = self::get();
|
||||
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] === $file && $r[1] === $modname) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$rt[] = [ $file, $modname ];
|
||||
self::set($rt);
|
||||
}
|
||||
|
||||
static function unregister($file,$modname) {
|
||||
/**
|
||||
* Unregister a route.
|
||||
*
|
||||
* Example:
|
||||
* ```php
|
||||
* Route::unregister(
|
||||
* __DIR__ . '/Mod_Myroute.php',
|
||||
* 'myroute'
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* @param string $file The file containing the controller for handling requests to this route.
|
||||
* @param string $modname The name of the module (URL path).
|
||||
*
|
||||
* @see {@link Zotlabs::Extend::Route.register() register()}
|
||||
* @see {@link Zotlabs::Extend::Route.unregister_by_file() unregister_by_file()}
|
||||
*/
|
||||
public static function unregister(string $file, string $modname): void {
|
||||
$rt = self::get();
|
||||
if($rt) {
|
||||
$n = [];
|
||||
foreach($rt as $r) {
|
||||
if($r[0] !== $file && $r[1] !== $modname) {
|
||||
if(!($r[0] === $file && $r[1] === $modname)) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
@@ -25,7 +108,23 @@ class Route {
|
||||
}
|
||||
}
|
||||
|
||||
static function unregister_by_file($file) {
|
||||
/**
|
||||
* Unregister all routes by source file.
|
||||
*
|
||||
* Removes all persistently stored routes with hanclers in the
|
||||
* given source file.
|
||||
*
|
||||
* Example:
|
||||
* ```php
|
||||
* Route::unregister_by_file(__DIR__ . '/Mod_Myroute.php');
|
||||
* ```
|
||||
*
|
||||
* @param string $file The file containing the controllers to remove.
|
||||
*
|
||||
* @see {@link Zotlabs::Extend::Route.register() register()}
|
||||
* @see {@link Zotlabs::Extend::Route.unregister() unregister()}
|
||||
*/
|
||||
public static function unregister_by_file(string $file): void {
|
||||
$rt = self::get();
|
||||
if($rt) {
|
||||
$n = [];
|
||||
@@ -38,11 +137,18 @@ class Route {
|
||||
}
|
||||
}
|
||||
|
||||
static function get() {
|
||||
/**
|
||||
* Get an array of all defined routes.
|
||||
*
|
||||
* @return An array of routes, where each entry is an array
|
||||
* containing two elements, the file, and the module
|
||||
* name.
|
||||
*/
|
||||
public static function get(): array {
|
||||
return Config::Get('system','routes',[]);
|
||||
}
|
||||
|
||||
static function set($r) {
|
||||
private static function set(array $r): mixed {
|
||||
return Config::Set('system','routes',$r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,13 @@ class Widget {
|
||||
|
||||
static function register($file,$widget) {
|
||||
$rt = self::get();
|
||||
|
||||
foreach ($rt as $r) {
|
||||
if ($r[0] === $file && $r[1] === $widget) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$rt[] = [ $file, $widget ];
|
||||
self::set($rt);
|
||||
}
|
||||
@@ -17,7 +24,7 @@ class Widget {
|
||||
if($rt) {
|
||||
$n = [];
|
||||
foreach($rt as $r) {
|
||||
if($r[0] !== $file && $r[1] !== $widget) {
|
||||
if(!($r[0] === $file && $r[1] === $widget)) {
|
||||
$n[] = $r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ class ASCollection {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = null;
|
||||
|
||||
if (is_array($this->nextpage)) {
|
||||
$data = $this->nextpage;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Access\PermissionRoles;
|
||||
use Zotlabs\Access\Permissions;
|
||||
@@ -91,6 +92,8 @@ class Activity {
|
||||
|
||||
logger('fetch: ' . $url, LOGGER_DEBUG);
|
||||
|
||||
$start_timestamp = microtime(true);
|
||||
|
||||
if (strpos($url, 'x-zot:') === 0) {
|
||||
$x = ZotURL::fetch($url, $channel);
|
||||
}
|
||||
@@ -129,7 +132,6 @@ class Activity {
|
||||
}
|
||||
|
||||
$h = HTTPSig::create_sig($headers, $channel['channel_prvkey'], channel_url($channel), false);
|
||||
$start_timestamp = microtime(true);
|
||||
$x = z_fetch_url($url, true, $redirects, ['headers' => $h]);
|
||||
}
|
||||
|
||||
@@ -567,7 +569,7 @@ class Activity {
|
||||
$ret['published'] = datetime_convert('UTC', 'UTC', $i['created'], ATOM_TIME);
|
||||
if ($i['created'] !== $i['edited'])
|
||||
$ret['updated'] = datetime_convert('UTC', 'UTC', $i['edited'], ATOM_TIME);
|
||||
if ($i['expires'] > NULL_DATE) {
|
||||
if ($i['expires'] > DBA::$dba->get_null_date()) {
|
||||
$ret['expires'] = datetime_convert('UTC', 'UTC', $i['expires'], ATOM_TIME);
|
||||
}
|
||||
|
||||
@@ -592,7 +594,7 @@ class Activity {
|
||||
|
||||
$ret['commentPolicy'] = (($i['item_wall']) ? map_scope(PermissionLimits::Get($i['uid'], 'post_comments')) : '');
|
||||
|
||||
if (array_key_exists('comments_closed', $i) && $i['comments_closed'] !== EMPTY_STR && $i['comments_closed'] > NULL_DATE) {
|
||||
if (array_key_exists('comments_closed', $i) && $i['comments_closed'] !== EMPTY_STR && $i['comments_closed'] > DBA::$dba->get_null_date()) {
|
||||
if ($ret['commentPolicy']) {
|
||||
$ret['commentPolicy'] .= ' ';
|
||||
}
|
||||
@@ -648,6 +650,7 @@ class Activity {
|
||||
preg_match_all('/\[share(.*?)\](.*?)\[\/share\]/ism', $i['body'], $all_shares, PREG_SET_ORDER);
|
||||
|
||||
$quote_urls = [];
|
||||
$obj_links = [];
|
||||
|
||||
foreach ($all_shares as $share) {
|
||||
// Extract the link attribute from each [share] block if slated for quote
|
||||
@@ -1123,6 +1126,7 @@ class Activity {
|
||||
return [];
|
||||
}
|
||||
|
||||
/* Those should not be required in activities anymore after version 11
|
||||
$t = self::encode_taxonomy($i);
|
||||
if ($t) {
|
||||
$ret['tag'] = $t;
|
||||
@@ -1132,6 +1136,7 @@ class Activity {
|
||||
if ($a) {
|
||||
$ret['attachment'] = $a;
|
||||
}
|
||||
*/
|
||||
|
||||
if (intval($i['item_private']) === 0) {
|
||||
$ret['to'] = [ACTIVITY_PUBLIC_INBOX];
|
||||
@@ -1560,7 +1565,7 @@ class Activity {
|
||||
'abook_created' => datetime_convert(),
|
||||
'abook_updated' => datetime_convert(),
|
||||
'abook_connected' => datetime_convert(),
|
||||
'abook_dob' => NULL_DATE,
|
||||
'abook_dob' => DBA::$dba->get_null_date(),
|
||||
'abook_pending' => intval(($automatic) ? 0 : 1),
|
||||
'abook_instance' => z_root()
|
||||
]
|
||||
@@ -2012,6 +2017,8 @@ class Activity {
|
||||
$multi = true;
|
||||
}
|
||||
|
||||
$answer_found = false;
|
||||
|
||||
if ($response) {
|
||||
$mid = $response['mid'];
|
||||
$content = trim($response['title']);
|
||||
@@ -2041,7 +2048,6 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
$answer_found = false;
|
||||
$foundPrevious = false;
|
||||
if ($multi) {
|
||||
for ($c = 0; $c < count($o['anyOf']); $c++) {
|
||||
@@ -2083,7 +2089,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($pollItem['comments_closed'] > NULL_DATE) {
|
||||
if ($pollItem['comments_closed'] > DBA::$dba->get_null_date()) {
|
||||
if ($pollItem['comments_closed'] > datetime_convert()) {
|
||||
$o['closed'] = datetime_convert('UTC', 'UTC', $pollItem['comments_closed'], ATOM_TIME);
|
||||
// set this to force an update
|
||||
@@ -2138,11 +2144,13 @@ class Activity {
|
||||
$response_activity = false;
|
||||
$s = [];
|
||||
|
||||
$obj_type = is_array($act->objprop('type')) ? $act->objprop('type')[0] : $act->objprop('type');
|
||||
|
||||
// These activities should have been handled separately in the Inbox module and should not be turned into posts
|
||||
|
||||
if (
|
||||
in_array($act->type, ['Follow', 'Accept', 'Reject', 'Create', 'Update']) &&
|
||||
($act->objprop('type') === 'Follow' || ActivityStreams::is_an_actor($act->objprop('type')))
|
||||
($obj_type === 'Follow' || ActivityStreams::is_an_actor($obj_type))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -2215,7 +2223,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($act->type, ['Invite', 'Create']) && $act->objprop('type') === 'Event') {
|
||||
if (in_array($act->type, ['Invite', 'Create']) && $obj_type === 'Event') {
|
||||
$s['mid'] = $s['parent_mid'] = $act->id;
|
||||
}
|
||||
|
||||
@@ -2247,25 +2255,25 @@ class Activity {
|
||||
$mention = self::get_actor_bbmention($obj_actor['id']);
|
||||
|
||||
if ($act->type === 'Like') {
|
||||
$content['content'] = sprintf(t('Likes %1$s\'s %2$s'), $mention, $act->obj['type']) . EOL . EOL . ($content['content'] ?? '');
|
||||
$content['content'] = sprintf(t('Likes %1$s\'s %2$s'), $mention, $act->obj['type']);
|
||||
}
|
||||
if ($act->type === 'Dislike') {
|
||||
$content['content'] = sprintf(t('Doesn\'t like %1$s\'s %2$s'), $mention, $act->obj['type']) . EOL . EOL . ($content['content'] ?? '');
|
||||
$content['content'] = sprintf(t('Doesn\'t like %1$s\'s %2$s'), $mention, $act->obj['type']);
|
||||
}
|
||||
|
||||
// handle event RSVPs
|
||||
if (($act->objprop('type') === 'Event') || ($act->objprop('type') === 'Invite' && array_path_exists('object/type', $act->obj) && $act->obj['object']['type'] === 'Event')) {
|
||||
if (in_array($obj_type, ['Event', 'Invite'])) {
|
||||
if ($act->type === 'Accept') {
|
||||
$content['content'] = sprintf(t('Will attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? '');
|
||||
$content['content'] = sprintf(t('Will attend %s\'s event'), $mention);
|
||||
}
|
||||
if ($act->type === 'Reject') {
|
||||
$content['content'] = sprintf(t('Will not attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? '');
|
||||
$content['content'] = sprintf(t('Will not attend %s\'s event'), $mention);
|
||||
}
|
||||
if ($act->type === 'TentativeAccept') {
|
||||
$content['content'] = sprintf(t('May attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? '');
|
||||
$content['content'] = sprintf(t('May attend %s\'s event'), $mention);
|
||||
}
|
||||
if ($act->type === 'TentativeReject') {
|
||||
$content['content'] = sprintf(t('May not attend %s\'s event'), $mention) . EOL . EOL . ($content['content'] ?? '');
|
||||
$content['content'] = sprintf(t('May not attend %s\'s event'), $mention);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2299,7 +2307,7 @@ class Activity {
|
||||
if ($s['mid'] === $s['parent_mid']) {
|
||||
$s['item_thread_top'] = 1;
|
||||
$s['item_nocomment'] = 0;
|
||||
$s['comments_closed'] = NULL_DATE;
|
||||
$s['comments_closed'] = DBA::$dba->get_null_date();
|
||||
|
||||
// it is a parent node - decode the comment policy info if present
|
||||
if ($act->objprop('commentPolicy')) {
|
||||
@@ -2375,7 +2383,7 @@ class Activity {
|
||||
$s['verb'] = self::activity_mapper($act->type);
|
||||
|
||||
// Mastodon does not provide update timestamps when updating poll tallies which means race conditions may occur here.
|
||||
if ($act->type === 'Update' && $act->objprop('type') === 'Question' && $s['edited'] === $s['created']) {
|
||||
if ($act->type === 'Update' && $obj_type === 'Question' && $s['edited'] === $s['created']) {
|
||||
$s['edited'] = datetime_convert();
|
||||
}
|
||||
|
||||
@@ -2383,8 +2391,8 @@ class Activity {
|
||||
$s['item_deleted'] = 1;
|
||||
}
|
||||
|
||||
if ($act->objprop('type')) {
|
||||
$s['obj_type'] = self::activity_obj_mapper($act->obj['type']);
|
||||
if ($obj_type) {
|
||||
$s['obj_type'] = self::activity_obj_mapper($obj_type);
|
||||
}
|
||||
|
||||
$s['obj'] = $act->obj;
|
||||
@@ -2445,7 +2453,7 @@ class Activity {
|
||||
$s = self::bb_attach($s);
|
||||
}
|
||||
|
||||
if ($act->objprop('type') === 'Question' && in_array($act->type, ['Create', 'Update'])) {
|
||||
if ($obj_type === 'Question' && in_array($act->type, ['Create', 'Update'])) {
|
||||
if ($act->objprop('endTime')) {
|
||||
$s['comments_closed'] = datetime_convert('UTC', 'UTC', $act->obj['endTime']);
|
||||
}
|
||||
@@ -2457,7 +2465,7 @@ class Activity {
|
||||
|
||||
if (!$response_activity) {
|
||||
|
||||
if ($act->objprop('type') === 'Profile') {
|
||||
if ($obj_type === 'Profile') {
|
||||
$s['parent_mid'] = $s['mid'];
|
||||
$s['item_thread_top'] = 1;
|
||||
}
|
||||
@@ -2467,7 +2475,7 @@ class Activity {
|
||||
// right now just link to the largest mp4 we find that will fit in our
|
||||
// standard content region
|
||||
|
||||
if ($act->objprop('type') === 'Video') {
|
||||
if ($obj_type === 'Video') {
|
||||
|
||||
$vtypes = [
|
||||
'video/mp4',
|
||||
@@ -2549,7 +2557,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if ($act->objprop('type') === 'Audio') {
|
||||
if ($obj_type === 'Audio') {
|
||||
|
||||
$atypes = [
|
||||
'audio/mpeg',
|
||||
@@ -2581,7 +2589,7 @@ class Activity {
|
||||
|
||||
}
|
||||
|
||||
if ($act->objprop('type') === 'Image' && strpos($s['body'], 'zrl=') === false) {
|
||||
if ($obj_type === 'Image' && strpos($s['body'], 'zrl=') === false) {
|
||||
|
||||
$ptr = null;
|
||||
|
||||
@@ -2596,10 +2604,10 @@ class Activity {
|
||||
foreach ($ptr as $vurl) {
|
||||
if (strpos($s['body'], $vurl['href']) === false) {
|
||||
$bb_imgs = '[zmg]' . $vurl['href'] . '[/zmg]' . "\r\n";
|
||||
$s['body'] = $bb_imgs . $s['body'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$s['body'] = $bb_imgs . $s['body'];
|
||||
}
|
||||
elseif (is_string($act->obj['url'])) {
|
||||
if (strpos($s['body'], $act->obj['url']) === false) {
|
||||
@@ -2609,7 +2617,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if ($act->objprop('type') === 'Page' && !$s['body']) {
|
||||
if ($obj_type === 'Page' && !$s['body']) {
|
||||
|
||||
$ptr = null;
|
||||
$purl = EMPTY_STR;
|
||||
@@ -2649,7 +2657,7 @@ class Activity {
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($act->objprop('type'), ['Note', 'Article', 'Page', 'Question'])) {
|
||||
if (in_array($obj_type, ['Note', 'Article', 'Page', 'Question'])) {
|
||||
$ptr = null;
|
||||
|
||||
if (array_key_exists('url', $act->obj)) {
|
||||
@@ -2692,7 +2700,7 @@ class Activity {
|
||||
IConfig::Set($s, 'activitypub', 'recips', $act->raw_recips);
|
||||
}
|
||||
|
||||
if ($act->objprop('type') === 'Event' && $act->objprop('timezone')) {
|
||||
if ($obj_type === 'Event' && $act->objprop('timezone')) {
|
||||
IConfig::Set($s, 'event', 'timezone', $act->objprop('timezone'), true);
|
||||
}
|
||||
|
||||
@@ -3782,6 +3790,9 @@ class Activity {
|
||||
*/
|
||||
|
||||
public static function init_background_fetch(string $observer_hash = '') {
|
||||
|
||||
$interval = Config::Get('queueworker', 'queue_interval', 500000);
|
||||
|
||||
if (isset(App::$cache['zot_fetch_objects'])) {
|
||||
foreach (App::$cache['zot_fetch_objects'] as $mid => $info) {
|
||||
$force = $info['force'];
|
||||
@@ -3795,6 +3806,10 @@ class Activity {
|
||||
}
|
||||
|
||||
Master::Summon(['Zotconvo', $channels_str, $mid, $force]);
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3816,6 +3831,10 @@ class Activity {
|
||||
}
|
||||
|
||||
Master::Summon(['Fetchparents', $channels_str, $observer_hash, $mid, $force]);
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3832,6 +3851,10 @@ class Activity {
|
||||
}
|
||||
|
||||
Master::Summon(['Convo', $channels_str, $observer_hash, $mid, $force]);
|
||||
|
||||
if ($interval) {
|
||||
usleep($interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1028,12 +1028,7 @@ class Apps {
|
||||
if(! $syslist)
|
||||
return;
|
||||
|
||||
foreach($syslist as $k => $li) {
|
||||
if($li['guid'] === $guid) {
|
||||
$position = $k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$position = array_find_key($syslist, fn ($v) => $v['guid'] === $guid);
|
||||
if(! $position)
|
||||
return;
|
||||
|
||||
@@ -1082,12 +1077,7 @@ class Apps {
|
||||
if(! $syslist)
|
||||
return;
|
||||
|
||||
foreach($syslist as $k => $li) {
|
||||
if($li['guid'] === $guid) {
|
||||
$position = $k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$position = array_find_key($syslist, fn ($v) => $v['guid'] === $guid);
|
||||
if($position >= count($syslist) - 1)
|
||||
return;
|
||||
|
||||
|
||||
43
Zotlabs/Lib/DbStats.php
Normal file
43
Zotlabs/Lib/DbStats.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use DBA;
|
||||
|
||||
/**
|
||||
* Abstract class to obtain statistics from the database.
|
||||
*
|
||||
* This class should not be instantiated on it's own, but you can get
|
||||
* a concrete class for the configured database type of this site by
|
||||
* calling the `DbStats::getStats()` function.
|
||||
*/
|
||||
abstract class DbStats {
|
||||
|
||||
/**
|
||||
* Get an object for getting statistics from the database.
|
||||
*
|
||||
* @return DbStats The concrete class for obtaining the statistics from
|
||||
* this instances database.
|
||||
*/
|
||||
public static function getStats(): DbStats {
|
||||
return DBA::$dba->is_postgres()
|
||||
? new PostgresDbStats()
|
||||
: new MySQLDbStats();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of queries recorded by the database.
|
||||
*
|
||||
* @return int Number of queries.
|
||||
*/
|
||||
public abstract function getQueries(): int;
|
||||
|
||||
// Prevent instantiation of this class
|
||||
private function __construct() {}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Access\PermissionLimits;
|
||||
use Zotlabs\Access\Permissions;
|
||||
use Zotlabs\Daemon\Master;
|
||||
@@ -348,7 +349,7 @@ class Libzot {
|
||||
$next_birthday = datetime_convert('UTC', 'UTC', $record['data']['profile']['next_birthday']);
|
||||
}
|
||||
else {
|
||||
$next_birthday = NULL_DATE;
|
||||
$next_birthday = DBA::$dba->get_null_date();
|
||||
}
|
||||
|
||||
$profile_assign = get_pconfig($channel['channel_id'], 'system', 'profile_assign', '');
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
@@ -216,7 +217,7 @@ class Libzotdir {
|
||||
[
|
||||
'site_url' => DIRECTORY_FALLBACK_MASTER,
|
||||
'site_flags' => DIRECTORY_MODE_PRIMARY,
|
||||
'site_update' => NULL_DATE,
|
||||
'site_update' => DBA::$dba->get_null_date(),
|
||||
'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
|
||||
'site_realm' => DIRECTORY_REALM,
|
||||
'site_valid' => 1,
|
||||
@@ -247,7 +248,7 @@ class Libzotdir {
|
||||
|
||||
$token = Config::Get('system','realm_token');
|
||||
|
||||
$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
|
||||
$syncdate = (($rr['site_sync'] <= DBA::$dba->get_null_date()) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
|
||||
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
|
||||
|
||||
if (! $x['success'])
|
||||
@@ -724,7 +725,7 @@ class Libzotdir {
|
||||
|
||||
if ($u) {
|
||||
$x = q("UPDATE updates SET $date_sql $flag_sql ud_last = '%s', ud_host = '%s', ud_addr = '%s', ud_update = 0 WHERE ud_id = %d",
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
dbesc(z_root()),
|
||||
dbesc($addr),
|
||||
intval($u[0]['ud_id'])
|
||||
|
||||
37
Zotlabs/Lib/MySQLDbStats.php
Normal file
37
Zotlabs/Lib/MySQLDbStats.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use DBA;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Concrete implementation for getting stats from MySQL and MariaDB databases.
|
||||
*/
|
||||
class MySQLDbStats extends DbStats {
|
||||
|
||||
public function getQueries(): int {
|
||||
//
|
||||
// We can't use the regular Hubzilla db helper function here, as
|
||||
// it will only return information from a `SELECT` statement.
|
||||
//
|
||||
// Use the basic PDO access instead.
|
||||
//
|
||||
$query = DBA::$dba->db->prepare('SHOW STATUS LIKE "Queries"');
|
||||
$query->execute();
|
||||
|
||||
$result = $query->fetch(PDO::FETCH_ASSOC);
|
||||
logger(print_r($result, true));
|
||||
if (!empty($result)) {
|
||||
return $result['Value'] ?? -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
32
Zotlabs/Lib/PostgresDbStats.php
Normal file
32
Zotlabs/Lib/PostgresDbStats.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use DBA;
|
||||
|
||||
/**
|
||||
* Concrete implementation for getting stats from PostgreSQL databases.
|
||||
*/
|
||||
class PostgresDbStats extends DbStats {
|
||||
|
||||
public function getQueries(): int {
|
||||
$sqlGetQps = <<<'SQL'
|
||||
select (xact_commit + xact_rollback) as queries
|
||||
from pg_stat_database
|
||||
where datname='%s'
|
||||
SQL;
|
||||
|
||||
$result = q($sqlGetQps, DBA::$dba->dbname);
|
||||
if (!empty($result)) {
|
||||
return $result[0]['queries'] ?? -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,20 @@ use Zotlabs\Zot6\Zot6Handler;
|
||||
|
||||
class Queue {
|
||||
|
||||
/**
|
||||
* Get number of entries in the out queue.
|
||||
*
|
||||
* When delivery is successful, the item is removed from the out queue, so
|
||||
* the number of items in the queue reflects the number of pending delivery
|
||||
* attempts.
|
||||
*
|
||||
* @return int Number of items in the out queue.
|
||||
*/
|
||||
static function count(): int {
|
||||
$r = dbq('select count(*) as total from outq');
|
||||
return $r[0]['total'] ?? 0;
|
||||
}
|
||||
|
||||
static function update($id, $add_priority = 0) {
|
||||
|
||||
logger('queue: requeue item ' . $id,LOGGER_DEBUG);
|
||||
|
||||
28
Zotlabs/Lib/QueueWorkerStats.php
Normal file
28
Zotlabs/Lib/QueueWorkerStats.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
class QueueWorkerStats
|
||||
{
|
||||
public readonly int $size;
|
||||
public readonly int $active;
|
||||
|
||||
public function __construct() {
|
||||
$query = <<<'SQL'
|
||||
select count(*) as total from workerq
|
||||
union (select count(*) as qworkers from workerq where workerq_reservationid is not null)
|
||||
SQL;
|
||||
|
||||
$result = dbq('select count(*) as total from workerq');
|
||||
$this->size = !empty($result) ? $result[0]['total'] : -1;
|
||||
|
||||
$result = dbq('select count(*) as qworkers from workerq where workerq_reservationid is not null');
|
||||
$this->active = !empty($result) ? $result[0]['qworkers'] : -1;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Lib;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Access\AccessList;
|
||||
|
||||
require_once('include/text.php');
|
||||
@@ -415,7 +416,7 @@ class ThreadItem {
|
||||
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
|
||||
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created']),
|
||||
'editedtime' => (($item['edited'] != $item['created']) ? sprintf(t('Last edited %s'), relative_time($item['edited'])) : ''),
|
||||
'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf(t('Expires %s'), relative_time($item['expires'])) : ''),
|
||||
'expiretime' => (($item['expires'] > DBA::$dba->get_null_date()) ? sprintf(t('Expires %s'), relative_time($item['expires'])) : ''),
|
||||
'lock' => $lock,
|
||||
'locktype' => $locktype,
|
||||
'delayed' => (($item['item_delayed']) ? sprintf(t('Published %s'), relative_time($item['created'])) : ''),
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
require_once('include/account.php');
|
||||
@@ -90,7 +91,7 @@ class Admin extends \Zotlabs\Web\Controller {
|
||||
$r = q("SELECT COUNT(CASE WHEN account_id > 0 THEN 1 ELSE NULL END) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
|
||||
db_utcnow(),
|
||||
db_utcnow(),
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
intval(ACCOUNT_BLOCKED)
|
||||
);
|
||||
if ($r) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use DBA;
|
||||
|
||||
class Changeaddr extends \Zotlabs\Web\Controller {
|
||||
|
||||
@@ -29,7 +30,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
|
||||
if(! ($x && $x['account']))
|
||||
return;
|
||||
|
||||
if($account['account_password_changed'] > NULL_DATE) {
|
||||
if($account['account_password_changed'] > DBA::$dba->get_null_date()) {
|
||||
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
||||
if($account['account_password_changed'] > $d1) {
|
||||
notice( t('Channel name changes are not allowed within 48 hours of changing the account password.') . EOL);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
use Zotlabs\Access\AccessList;
|
||||
@@ -300,7 +301,7 @@ class Channel_calendar extends Controller {
|
||||
from event left join item on item.resource_id = event.event_hash
|
||||
where event.uid = %d and event.dtstart > '%s' and event.dtend > event.dtstart",
|
||||
intval(local_channel()),
|
||||
dbesc(NULL_DATE)
|
||||
dbesc(DBA::$dba->get_null_date())
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
@@ -232,7 +233,7 @@ class Dirsearch extends Controller {
|
||||
$spkt = array('transactions' => array());
|
||||
|
||||
$r = q("SELECT * FROM updates WHERE ud_update = 0 AND ud_last = '%s' AND ud_date >= '%s' ORDER BY ud_date DESC",
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
dbesc($sync)
|
||||
);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\PConfig;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
@@ -21,7 +22,7 @@ class Feed extends Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
$params['begin'] = $_REQUEST['date_begin'] ?? NULL_DATE;
|
||||
$params['begin'] = $_REQUEST['date_begin'] ?? DBA::$dba->get_null_date();
|
||||
$params['end'] = $_REQUEST['date_end'] ?? '';
|
||||
$params['type'] = 'xml';
|
||||
$params['pages'] = ((!empty($_REQUEST['pages'])) ? intval($_REQUEST['pages']) : 0);
|
||||
|
||||
@@ -7,6 +7,7 @@ require_once('include/import.php');
|
||||
require_once('include/perm_upgrade.php');
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use URLify;
|
||||
use Zotlabs\Daemon\Master;
|
||||
use Zotlabs\Lib\Config;
|
||||
@@ -331,7 +332,7 @@ class Import extends Controller {
|
||||
else {
|
||||
$photos = import_xchan_photo($xchan['xchan_photo_l'], $xchan['xchan_hash']);
|
||||
if ($photos[4])
|
||||
$photodate = NULL_DATE;
|
||||
$photodate = DBA::$dba->get_null_date();
|
||||
else
|
||||
$photodate = $xchan['xchan_photo_date'];
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use URLify;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\IConfig;
|
||||
@@ -209,7 +210,7 @@ class Item extends Controller {
|
||||
}
|
||||
|
||||
|
||||
$expires = NULL_DATE;
|
||||
$expires = DBA::$dba->get_null_date();
|
||||
|
||||
$route = '';
|
||||
$parent_item = null;
|
||||
@@ -559,7 +560,7 @@ class Item extends Controller {
|
||||
if (!empty($_POST['expire'])) {
|
||||
$expires = datetime_convert(date_default_timezone_get(), 'UTC', $_POST['expire']);
|
||||
if ($expires <= datetime_convert())
|
||||
$expires = NULL_DATE;
|
||||
$expires = DBA::$dba->get_null_date();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,7 +802,7 @@ class Item extends Controller {
|
||||
$item_origin = (($origin) ? 1 : 0);
|
||||
$item_consensus = (($consensus) ? 1 : 0);
|
||||
$item_nocomment = (($nocomment) ? 1 : 0);
|
||||
$comments_closed = (($nocomment) ? $comments_closed : NULL_DATE);
|
||||
$comments_closed = (($nocomment) ? $comments_closed : DBA::$dba->get_null_date());
|
||||
|
||||
// determine if this is a wall post
|
||||
|
||||
@@ -875,7 +876,7 @@ class Item extends Controller {
|
||||
|
||||
if ($obj['endTime']) {
|
||||
$d = datetime_convert('UTC','UTC', $obj['endTime']);
|
||||
if ($d > NULL_DATE) {
|
||||
if ($d > DBA::$dba->get_null_date()) {
|
||||
$comments_closed = $d;
|
||||
}
|
||||
}
|
||||
@@ -1075,12 +1076,14 @@ class Item extends Controller {
|
||||
killme();
|
||||
}
|
||||
|
||||
|
||||
$post = item_store($datarray, $execflag);
|
||||
|
||||
if ($post['success'] && intval($item_type) === ITEM_TYPE_POST) {
|
||||
$item = [$post['item']];
|
||||
xchan_query($item);
|
||||
$item = fetch_post_tags($item);
|
||||
// TODO: fetch_post_tags() will add term and iconfig twice if called twice and it looks like they are already added here
|
||||
//$item = fetch_post_tags($item);
|
||||
$encoded_item = Activity::build_packet(Activity::encode_activity($item[0]), $channel, false);
|
||||
ObjCache::Set($item[0]['mid'], $encoded_item);
|
||||
|
||||
|
||||
@@ -143,8 +143,11 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if(x($_GET, 'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen)
|
||||
if($search || $file || (!$pf && $cid) || $hashtags || $verb || $category || $conv || $unseen) {
|
||||
$nouveau = true;
|
||||
}
|
||||
|
||||
$dismiss_privacy_filter = array_intersect(['cid', 'star', 'conv', 'file', 'verb', 'cat', 'search'], array_keys($_GET));
|
||||
|
||||
$cid_r = [];
|
||||
|
||||
@@ -363,13 +366,14 @@ class Network extends \Zotlabs\Web\Controller {
|
||||
$sql_extra .= term_query('item', $file, TERM_FILE);
|
||||
}
|
||||
|
||||
if ($dm) {
|
||||
$sql_extra .= ' AND item.item_private = 2 ';
|
||||
if (!$dismiss_privacy_filter) {
|
||||
if ($dm) {
|
||||
$sql_extra .= ' AND item.item_private = 2 ';
|
||||
}
|
||||
else {
|
||||
$sql_extra .= ' AND item.item_private IN (0, 1) ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$sql_extra .= ' AND item.item_private IN (0, 1) ';
|
||||
}
|
||||
|
||||
|
||||
if($conv) {
|
||||
$item_thread_top = '';
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\ActivityStreams;
|
||||
use Zotlabs\Lib\Config;
|
||||
@@ -47,7 +48,7 @@ class Outbox extends Controller {
|
||||
|
||||
$params = [];
|
||||
|
||||
$params['begin'] = ((x($_REQUEST, 'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE);
|
||||
$params['begin'] = ((x($_REQUEST, 'date_begin')) ? $_REQUEST['date_begin'] : DBA::$dba->get_null_date());
|
||||
$params['end'] = ((x($_REQUEST, 'date_end')) ? $_REQUEST['date_end'] : '');
|
||||
$params['type'] = 'json';
|
||||
$params['pages'] = ((x($_REQUEST, 'pages')) ? intval($_REQUEST['pages']) : 0);
|
||||
|
||||
79
Zotlabs/Module/Perfstats.php
Normal file
79
Zotlabs/Module/Perfstats.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* Handler for perfstats requests.
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\DbStats;
|
||||
use Zotlabs\Lib\Queue;
|
||||
use Zotlabs\Lib\QueueWorkerStats;
|
||||
use Zotlabs\Web\Controller;
|
||||
|
||||
/**
|
||||
* Controller for the `/perfstats` module.
|
||||
*
|
||||
* Collects various performance stats for the site, and reponds with the stats
|
||||
* as a json array.
|
||||
*/
|
||||
class Perfstats extends Controller
|
||||
{
|
||||
public function init(): void {
|
||||
//
|
||||
// We only accept GET requests
|
||||
//
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
http_status_exit(400, 'Unsupported method');
|
||||
}
|
||||
|
||||
//
|
||||
// We only accept json requests
|
||||
//
|
||||
if (getBestSupportedMimeType(['application/json']) === null) {
|
||||
http_status_exit(400, 'No supported format');
|
||||
}
|
||||
|
||||
//
|
||||
// Only admins should be given access
|
||||
//
|
||||
if (!is_site_admin()) {
|
||||
http_status(401, 'Access denied');
|
||||
json_return_and_die(['error' => 'access denied']);
|
||||
}
|
||||
|
||||
$data = $this->getStats();
|
||||
json_return_and_die($data);
|
||||
}
|
||||
|
||||
private function getStats(): array {
|
||||
$stats = [];
|
||||
|
||||
if (function_exists('sys_getloadavg')) {
|
||||
$stats['loadavg'] = sys_getloadavg();
|
||||
}
|
||||
|
||||
$stats['dbqueries'] = $this->getNumQueries();
|
||||
$stats['outqueue'] = Queue::count();
|
||||
|
||||
$qwstats = new QueueWorkerStats();
|
||||
$stats['queueworkers'] = $qwstats->active;
|
||||
$stats['workqsz'] = $qwstats->size;
|
||||
|
||||
// Return a timestamp, so that it is possible to infer
|
||||
// changes of the stats over time. A resolution of
|
||||
// seconds should be good enough for our purposes.
|
||||
$stats['ts'] = time();
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
private function getNumQueries(): int {
|
||||
$stats = DbStats::getStats();
|
||||
return $stats->getQueries();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\Libsync;
|
||||
|
||||
@@ -340,7 +341,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
$with = ((x($_POST,'with')) ? escape_tags(trim($_POST['with'])) : '');
|
||||
|
||||
if(! strlen($howlong))
|
||||
$howlong = NULL_DATE;
|
||||
$howlong = DBA::$dba->get_null_date();
|
||||
else
|
||||
$howlong = datetime_convert(date_default_timezone_get(),'UTC',$howlong);
|
||||
|
||||
@@ -774,7 +775,7 @@ class Profiles extends \Zotlabs\Web\Controller {
|
||||
'$marital' => marital_selector($r[0]['marital']),
|
||||
'$marital_min' => marital_selector_min($r[0]['marital']),
|
||||
'$with' => array('with', t("Who (if applicable)"), $r[0]['partner'], t('Examples: cathy123, Cathy Williams, cathy@example.com')),
|
||||
'$howlong' => array('howlong', t('Since (date)'), ($r[0]['howlong'] <= NULL_DATE ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong']))),
|
||||
'$howlong' => array('howlong', t('Since (date)'), ($r[0]['howlong'] <= DBA::$dba->get_null_date() ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong']))),
|
||||
'$sexual' => sexpref_selector($r[0]['sexual']),
|
||||
'$sexual_min' => sexpref_selector_min($r[0]['sexual']),
|
||||
'$about' => array('about', t('Tell us about yourself'), $r[0]['about']),
|
||||
|
||||
@@ -142,7 +142,15 @@ class Regate extends \Zotlabs\Web\Controller {
|
||||
|
||||
if (($flags & ACCOUNT_PENDING ) == ACCOUNT_PENDING) {
|
||||
$nextpage = 'regate/' . bin2hex($did2) . $didx;
|
||||
q("COMMIT");
|
||||
$approve = send_reg_approval_email_from_register($r['reg_id']);
|
||||
if ($approve['success']) {
|
||||
q("COMMIT");
|
||||
} else {
|
||||
q("ROLLBACK");
|
||||
$msg_code = 'ZAR1237E';
|
||||
$msg = t('Account verification notify error');
|
||||
zar_log($msg_code . ' ' . $msg . ': ' . print_r($approve, true));
|
||||
}
|
||||
}
|
||||
elseif (($flags ^ REGISTER_AGREED) == 0) {
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use DBA;
|
||||
|
||||
class Removeaccount extends \Zotlabs\Web\Controller {
|
||||
|
||||
@@ -29,7 +30,7 @@ class Removeaccount extends \Zotlabs\Web\Controller {
|
||||
if(! ($x && $x['account']))
|
||||
return;
|
||||
|
||||
if($account['account_password_changed'] > NULL_DATE) {
|
||||
if($account['account_password_changed'] > DBA::$dba->get_null_date()) {
|
||||
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
||||
if($account['account_password_changed'] > $d1) {
|
||||
notice( t('Account removals are not allowed within 48 hours of changing the account password.') . EOL);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use DBA;
|
||||
|
||||
class Removeme extends \Zotlabs\Web\Controller {
|
||||
|
||||
@@ -29,7 +30,7 @@ class Removeme extends \Zotlabs\Web\Controller {
|
||||
if(! ($x && $x['account']))
|
||||
return;
|
||||
|
||||
if($account['account_password_changed'] > NULL_DATE) {
|
||||
if($account['account_password_changed'] > DBA::$dba->get_null_date()) {
|
||||
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
||||
if($account['account_password_changed'] > $d1) {
|
||||
notice( t('Channel removals are not allowed within 48 hours of changing the account password.') . EOL);
|
||||
|
||||
@@ -150,13 +150,14 @@ class Search extends Controller {
|
||||
// OR your own posts if you are a logged in member
|
||||
// No items will be shown if the member has a blocked profile wall.
|
||||
|
||||
$livesearch = '';
|
||||
|
||||
if ((!$update) && (!$load)) {
|
||||
|
||||
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
|
||||
// because browser prefetching might change it on us. We have to deliver it with the page.
|
||||
|
||||
$livesearch = '<div id="live-search"></div>' . "\r\n";
|
||||
$livesearch .= '<div id="live-search"></div>' . "\r\n";
|
||||
$livesearch .= "<script> var profile_uid = " . ((intval(local_channel())) ? local_channel() : (-1))
|
||||
. "; var netargs = '?f='; var profile_page = " . App::$pager['page'] . "; </script>\r\n";
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Web\Controller;
|
||||
@@ -136,7 +137,7 @@ class Sse extends Controller {
|
||||
|
||||
session_reset();
|
||||
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', DBA::$dba->get_null_date());
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
|
||||
if (ob_get_length() > 0) {
|
||||
|
||||
@@ -3,21 +3,21 @@ namespace Zotlabs\Module;
|
||||
|
||||
require_once('include/event.php');
|
||||
|
||||
|
||||
use DBA;
|
||||
|
||||
class Tasks extends \Zotlabs\Web\Controller {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
|
||||
|
||||
// logger('request: ' . print_r($_REQUEST,true));
|
||||
|
||||
|
||||
$arr = array();
|
||||
|
||||
if(argc() > 1 && argv(1) === 'fetch') {
|
||||
|
||||
if(argc() > 1 && argv(1) === 'fetch') {
|
||||
if(argc() > 2 && argv(2) === 'all')
|
||||
$arr['all'] = 1;
|
||||
|
||||
|
||||
$x = tasks_fetch($arr);
|
||||
$x['html'] = '';
|
||||
if($x['tasks']) {
|
||||
@@ -53,7 +53,7 @@ class Tasks extends \Zotlabs\Web\Controller {
|
||||
$event = $r[0];
|
||||
if($event['event_status'] === 'COMPLETED') {
|
||||
$event['event_status'] = 'IN-PROCESS';
|
||||
$event['event_status_date'] = NULL_DATE;
|
||||
$event['event_status_date'] = DBA::$dba->get_null_date();
|
||||
$event['event_percent'] = 0;
|
||||
$event['event_sequence'] = $event['event_sequence'] + 1;
|
||||
$event['edited'] = datetime_convert();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Zotlabs\Module;
|
||||
|
||||
use App;
|
||||
use DBA;
|
||||
use Zotlabs\Web\Controller;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\AccessList;
|
||||
@@ -84,7 +85,7 @@ class Tokens extends Controller {
|
||||
if(trim($_POST['expires']))
|
||||
$expires = datetime_convert(date_default_timezone_get(),'UTC',$_POST['expires']);
|
||||
else
|
||||
$expires = NULL_DATE;
|
||||
$expires = DBA::$dba->get_null_date();
|
||||
$max_atokens = service_class_fetch($channel['channel_id'],'access_tokens');
|
||||
if($max_atokens) {
|
||||
$r = q("select count(atoken_id) as total where atoken_uid = %d",
|
||||
@@ -290,7 +291,7 @@ class Tokens extends Controller {
|
||||
'$atoken' => $atoken,
|
||||
'$name' => array('name', t('Login Name') . ' <span class="required">*</span>', $atoken['atoken_name'] ?? '',''),
|
||||
'$token'=> array('token', t('Login Password') . ' <span class="required">*</span>', $atoken['atoken_token'] ?? new_token(), ''),
|
||||
'$expires'=> array('expires', t('Expires (yyyy-mm-dd)'), ((isset($atoken['atoken_expires']) && $atoken['atoken_expires'] > NULL_DATE) ? datetime_convert('UTC',date_default_timezone_get(),$atoken['atoken_expires']) : ''), ''),
|
||||
'$expires'=> array('expires', t('Expires (yyyy-mm-dd)'), ((isset($atoken['atoken_expires']) && $atoken['atoken_expires'] > DBA::$dba->get_null_date()) ? datetime_convert('UTC',date_default_timezone_get(),$atoken['atoken_expires']) : ''), ''),
|
||||
'$submit' => t('Submit'),
|
||||
'$delete' => t('Delete')
|
||||
));
|
||||
|
||||
@@ -519,8 +519,8 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
* @return void
|
||||
*/
|
||||
function getDir() {
|
||||
|
||||
logger('GetDir: ' . $this->ext_path, LOGGER_DEBUG);
|
||||
|
||||
$this->auth->log();
|
||||
$modulename = \App::$module;
|
||||
|
||||
@@ -538,7 +538,6 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
$file = trim($file, '/');
|
||||
$path_arr = explode('/', $file);
|
||||
|
||||
|
||||
if (! $path_arr)
|
||||
return;
|
||||
|
||||
@@ -558,9 +557,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
$this->auth->owner_id = $channel_id;
|
||||
$this->auth->owner_nick = $channel_name;
|
||||
|
||||
$path = '/' . $channel_name;
|
||||
$folder = '';
|
||||
$os_path = '';
|
||||
$not_found = '';
|
||||
|
||||
for ($x = 1; $x < count($path_arr); $x++) {
|
||||
$r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0",
|
||||
@@ -568,15 +567,31 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
|
||||
dbesc($path_arr[$x]),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
if ($r && intval($r[0]['is_dir'])) {
|
||||
$folder = $r[0]['hash'];
|
||||
if (strlen($os_path))
|
||||
$os_path .= '/';
|
||||
$os_path .= $folder;
|
||||
|
||||
$path = $path . '/' . $r[0]['filename'];
|
||||
if (strlen($os_path)) {
|
||||
$os_path .= '/';
|
||||
}
|
||||
|
||||
$os_path .= $folder;
|
||||
}
|
||||
else {
|
||||
// if we got a bogus path collect the
|
||||
if (strlen($not_found)) {
|
||||
$not_found .= ',';
|
||||
}
|
||||
|
||||
$not_found .= $path_arr[$x];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($not_found) {
|
||||
throw new DAV\Exception\NotFound("Path $file does not exist. One or more directories could not be found: $not_found");
|
||||
}
|
||||
|
||||
$this->folder_hash = $folder;
|
||||
$this->os_path = $os_path;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace Zotlabs\Widget;
|
||||
|
||||
use App;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Queue;
|
||||
use Zotlabs\Lib\QueueWorkerStats;
|
||||
|
||||
class Channel_activities {
|
||||
|
||||
@@ -25,6 +27,9 @@ class Channel_activities {
|
||||
self::$uid = local_channel();
|
||||
self::$channel = App::get_channel();
|
||||
|
||||
if (is_site_admin()) {
|
||||
self::get_system_status();
|
||||
}
|
||||
self::get_photos_activity();
|
||||
self::get_files_activity();
|
||||
self::get_webpages_activity();
|
||||
@@ -38,6 +43,8 @@ class Channel_activities {
|
||||
|
||||
call_hooks('channel_activities_widget', $hookdata);
|
||||
|
||||
$activity_html = '';
|
||||
|
||||
if ($hookdata['activities']) {
|
||||
$keys = array_column($hookdata['activities'], 'date');
|
||||
array_multisort($keys, SORT_DESC, $hookdata['activities']);
|
||||
@@ -46,10 +53,11 @@ class Channel_activities {
|
||||
$activity_html .= replace_macros(
|
||||
get_markup_template($a['tpl']),
|
||||
[
|
||||
'$url' => $a['url'],
|
||||
'$url' => $a['url'] ?? null,
|
||||
'$icon' => $a['icon'],
|
||||
'$label' => $a['label'],
|
||||
'$items' => $a['items']
|
||||
'$items' => $a['items'],
|
||||
'$labels' => $a['labels'] ?? [],
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -221,11 +229,17 @@ class Channel_activities {
|
||||
$footer .= intval($notices[0]['total']) . ' ' . tt('notice', 'notices', intval($notices[0]['total']), 'noun');
|
||||
}
|
||||
|
||||
$tpl = get_markup_template('manage_channel_item.tpl');
|
||||
|
||||
$i[] = [
|
||||
'url' => z_root() . '/manage/' . $rr['channel_id'],
|
||||
'title' => '',
|
||||
'summary' => '<div class="text-truncate lh-sm"><img src="' . $rr['xchan_photo_s'] . '" class="menu-img-2">' . '<strong>' . $rr['channel_name'] . '</strong><br><small class="text-body-secondary">' . $rr['xchan_addr'] . '</small></div>',
|
||||
'footer' => $footer
|
||||
'url' => z_root() . '/manage/' . $rr['channel_id'],
|
||||
'title' => '',
|
||||
'summary' => replace_macros($tpl, [
|
||||
'$photo' => $rr['xchan_photo_s'],
|
||||
'$name' => $rr['channel_name'],
|
||||
'$addr' => $rr['xchan_addr'],
|
||||
]),
|
||||
'footer' => $footer
|
||||
];
|
||||
|
||||
$channels_activity++;
|
||||
@@ -247,5 +261,29 @@ class Channel_activities {
|
||||
|
||||
}
|
||||
|
||||
private static function get_system_status(): void {
|
||||
self::$activities['status'] = [
|
||||
'label' => t('System status'),
|
||||
'icon' => 'gpu-card',
|
||||
'date' => datetime_convert(),
|
||||
'items' => [
|
||||
'loadavg' => '0 / 0 / 0',
|
||||
'dbqueries' => 0,
|
||||
'outqueue' => 0,
|
||||
'queueworkers' => 0,
|
||||
'workqsz' => 0,
|
||||
'ts' => time(),
|
||||
],
|
||||
'tpl' => 'system_status_widget.tpl',
|
||||
'labels' => [
|
||||
'loadavg' => t('Load average'),
|
||||
'dbqueries' => t('DB queries/sec'),
|
||||
'outqueue' => t('Output queue'),
|
||||
'queueworkers' => t('Queue workers'),
|
||||
'workqsz' => t('Work queue size'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Zotlabs\Widget;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Config;
|
||||
|
||||
/**
|
||||
@@ -60,7 +61,7 @@ class Pinned {
|
||||
$profile_link = chanlink_hash($item['author_xchan']);
|
||||
$profile_name = $author['xchan_name'];
|
||||
|
||||
$commentable = ($item['item_nocomment'] == 0 && $item['comments_closed'] == NULL_DATE ? true : false);
|
||||
$commentable = ($item['item_nocomment'] == 0 && $item['comments_closed'] == DBA::$dba->get_null_date() ? true : false);
|
||||
|
||||
$location = format_location($item);
|
||||
$isevent = false;
|
||||
@@ -131,7 +132,7 @@ class Pinned {
|
||||
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
|
||||
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
|
||||
'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r') ) : ''),
|
||||
'expiretime' => ($item['expires'] > NULL_DATE ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r') ) : ''),
|
||||
'expiretime' => ($item['expires'] > DBA::$dba->get_null_date() ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r') ) : ''),
|
||||
'verified' => $verified,
|
||||
'forged' => $forged,
|
||||
'location' => $location,
|
||||
|
||||
6
boot.php
6
boot.php
@@ -70,7 +70,7 @@ require_once('include/security.php');
|
||||
|
||||
|
||||
define('PLATFORM_NAME', 'hubzilla');
|
||||
define('STD_VERSION', '11.0');
|
||||
define('STD_VERSION', '11.2');
|
||||
define('ZOT_REVISION', '6.0');
|
||||
|
||||
define('DB_UPDATE_VERSION', 1265);
|
||||
@@ -1896,7 +1896,7 @@ function notice($s) {
|
||||
|
||||
$x = null;
|
||||
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', NULL_DATE);
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', DBA::$dba->get_null_date());
|
||||
|
||||
if (datetime_convert('UTC', 'UTC', $t) < datetime_convert('UTC', 'UTC', '- 30 seconds')) {
|
||||
set_xconfig($hash, 'sse', 'notifications', []);
|
||||
@@ -1945,7 +1945,7 @@ function info($s) {
|
||||
|
||||
$x = null;
|
||||
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', NULL_DATE);
|
||||
$t = get_xconfig($hash, 'sse', 'timestamp', DBA::$dba->get_null_date());
|
||||
|
||||
if (datetime_convert('UTC', 'UTC', $t) < datetime_convert('UTC', 'UTC', '- 30 seconds')) {
|
||||
set_xconfig($hash, 'sse', 'notifications', []);
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
"scssphp/scssphp": "^2.0.1",
|
||||
"twbs/bootstrap-icons": "^1.11",
|
||||
"macgirvin/http-message-signer": "^0.2.6",
|
||||
"root23/php-json-canonicalization": "^1.0"
|
||||
"root23/php-json-canonicalization": "^1.0",
|
||||
"guzzlehttp/psr7": "^2.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-yaml": "*",
|
||||
|
||||
219
composer.lock
generated
219
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "08bc7d463277e84c8db1ce8cf1a90b7b",
|
||||
"content-hash": "5593f8a57f112fef0e3e5bc50a0e9c26",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bakame/http-structured-fields",
|
||||
@@ -155,16 +155,16 @@
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.14.1",
|
||||
"version": "0.14.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/brick/math.git",
|
||||
"reference": "f05858549e5f9d7bb45875a75583240a38a281d0"
|
||||
"reference": "63422359a44b7f06cae63c3b429b59e8efcc0629"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0",
|
||||
"reference": "f05858549e5f9d7bb45875a75583240a38a281d0",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629",
|
||||
"reference": "63422359a44b7f06cae63c3b429b59e8efcc0629",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -203,7 +203,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/brick/math/issues",
|
||||
"source": "https://github.com/brick/math/tree/0.14.1"
|
||||
"source": "https://github.com/brick/math/tree/0.14.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -211,7 +211,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-24T14:40:29+00:00"
|
||||
"time": "2026-02-10T14:33:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bshaffer/oauth2-server-php",
|
||||
@@ -1014,20 +1014,20 @@
|
||||
},
|
||||
{
|
||||
"name": "league/uri",
|
||||
"version": "7.7.0",
|
||||
"version": "7.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri.git",
|
||||
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807"
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
|
||||
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"league/uri-interfaces": "^7.7",
|
||||
"league/uri-interfaces": "^7.8",
|
||||
"php": "^8.1",
|
||||
"psr/http-factory": "^1"
|
||||
},
|
||||
@@ -1041,11 +1041,11 @@
|
||||
"ext-gmp": "to improve IPV4 host parsing",
|
||||
"ext-intl": "to handle IDN host with the best performance",
|
||||
"ext-uri": "to use the PHP native URI class",
|
||||
"jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain",
|
||||
"league/uri-components": "Needed to easily manipulate URI objects components",
|
||||
"league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP",
|
||||
"jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
|
||||
"league/uri-components": "to provide additional tools to manipulate URI objects components",
|
||||
"league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
|
||||
"php-64bit": "to improve IPV4 host parsing",
|
||||
"rowbot/url": "to handle WHATWG URL",
|
||||
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
|
||||
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -1100,7 +1100,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.7.0"
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1108,20 +1108,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-07T16:02:06+00:00"
|
||||
"time": "2026-01-14T17:24:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/uri-interfaces",
|
||||
"version": "7.7.0",
|
||||
"version": "7.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri-interfaces.git",
|
||||
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c"
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
|
||||
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1134,7 +1134,7 @@
|
||||
"ext-gmp": "to improve IPV4 host parsing",
|
||||
"ext-intl": "to handle IDN host with the best performance",
|
||||
"php-64bit": "to improve IPV4 host parsing",
|
||||
"rowbot/url": "to handle WHATWG URL",
|
||||
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
|
||||
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -1184,7 +1184,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.7.0"
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1192,7 +1192,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-07T16:03:21+00:00"
|
||||
"time": "2026-01-15T06:54:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lukasreschke/id3parser",
|
||||
@@ -1236,22 +1236,21 @@
|
||||
},
|
||||
{
|
||||
"name": "macgirvin/http-message-signer",
|
||||
"version": "v0.2.12",
|
||||
"version": "v0.2.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/macgirvin/HTTP-Message-Signer.git",
|
||||
"reference": "6e5b25a5536576e5046f5b0a7db620b5eb451453"
|
||||
"reference": "b231228c630bf88ac3415b2ba28c057654c9fbea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/macgirvin/HTTP-Message-Signer/zipball/6e5b25a5536576e5046f5b0a7db620b5eb451453",
|
||||
"reference": "6e5b25a5536576e5046f5b0a7db620b5eb451453",
|
||||
"url": "https://api.github.com/repos/macgirvin/HTTP-Message-Signer/zipball/b231228c630bf88ac3415b2ba28c057654c9fbea",
|
||||
"reference": "b231228c630bf88ac3415b2ba28c057654c9fbea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"bakame/http-structured-fields": "^2.0",
|
||||
"ext-openssl": "*",
|
||||
"guzzlehttp/psr7": "^2.0",
|
||||
"paragonie/easy-ecc": "^1.3",
|
||||
"php": "^8.1",
|
||||
"phpseclib/phpseclib": "~3.0",
|
||||
@@ -1259,6 +1258,7 @@
|
||||
"psr/http-message": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/psr7": "^2.8",
|
||||
"phpunit/phpunit": "^10.0"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -1274,9 +1274,9 @@
|
||||
"description": "RFC 9421 HTTP Message Signer and Verifier for PSR-7 requests",
|
||||
"support": {
|
||||
"issues": "https://github.com/macgirvin/HTTP-Message-Signer/issues",
|
||||
"source": "https://github.com/macgirvin/HTTP-Message-Signer/tree/v0.2.12"
|
||||
"source": "https://github.com/macgirvin/HTTP-Message-Signer/tree/v0.2.13"
|
||||
},
|
||||
"time": "2025-12-02T18:48:05+00:00"
|
||||
"time": "2026-02-01T19:54:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "michelf/php-markdown",
|
||||
@@ -1791,20 +1791,21 @@
|
||||
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Text_LanguageDetect",
|
||||
"source": "https://github.com/pear/Text_LanguageDetect"
|
||||
},
|
||||
"abandoned": true,
|
||||
"time": "2023-02-27T20:54:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.48",
|
||||
"version": "3.0.49",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "64065a5679c50acb886e82c07aa139b0f757bb89"
|
||||
"reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/64065a5679c50acb886e82c07aa139b0f757bb89",
|
||||
"reference": "64065a5679c50acb886e82c07aa139b0f757bb89",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/6233a1e12584754e6b5daa69fe1289b47775c1b9",
|
||||
"reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1885,7 +1886,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.48"
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.49"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1901,7 +1902,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-15T11:51:42+00:00"
|
||||
"time": "2026-01-27T09:17:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib2_compat",
|
||||
@@ -3055,16 +3056,16 @@
|
||||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v5.7.0",
|
||||
"version": "v5.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/smarty-php/smarty.git",
|
||||
"reference": "73da7e90f302175a570662fcb0ba41f57b7a92ab"
|
||||
"reference": "78d259d3b971c59a0cd719c270cc5cbb740c36a7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/73da7e90f302175a570662fcb0ba41f57b7a92ab",
|
||||
"reference": "73da7e90f302175a570662fcb0ba41f57b7a92ab",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/78d259d3b971c59a0cd719c270cc5cbb740c36a7",
|
||||
"reference": "78d259d3b971c59a0cd719c270cc5cbb740c36a7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3119,7 +3120,7 @@
|
||||
"support": {
|
||||
"forum": "https://github.com/smarty-php/smarty/discussions",
|
||||
"issues": "https://github.com/smarty-php/smarty/issues",
|
||||
"source": "https://github.com/smarty-php/smarty/tree/v5.7.0"
|
||||
"source": "https://github.com/smarty-php/smarty/tree/v5.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3127,20 +3128,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-19T21:36:38+00:00"
|
||||
"time": "2026-02-15T14:27:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spomky-labs/otphp",
|
||||
"version": "11.4.1",
|
||||
"version": "11.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Spomky-Labs/otphp.git",
|
||||
"reference": "126c99b6cbbc18992cf3fba3b87931ba4e312482"
|
||||
"reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/126c99b6cbbc18992cf3fba3b87931ba4e312482",
|
||||
"reference": "126c99b6cbbc18992cf3fba3b87931ba4e312482",
|
||||
"url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad",
|
||||
"reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3185,7 +3186,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Spomky-Labs/otphp/issues",
|
||||
"source": "https://github.com/Spomky-Labs/otphp/tree/11.4.1"
|
||||
"source": "https://github.com/Spomky-Labs/otphp/tree/11.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3197,7 +3198,7 @@
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-05T13:20:36+00:00"
|
||||
"time": "2026-01-23T10:53:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "stephenhill/base58",
|
||||
@@ -3321,16 +3322,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v7.4.0",
|
||||
"version": "v7.4.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "d551b38811096d0be9c4691d406991b47c0c630a"
|
||||
"reference": "3ebc794fa5315e59fd122561623c2e2e4280538e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a",
|
||||
"reference": "d551b38811096d0be9c4691d406991b47c0c630a",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e",
|
||||
"reference": "3ebc794fa5315e59fd122561623c2e2e4280538e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3367,7 +3368,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.4.0"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.4.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3387,7 +3388,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-27T13:27:24+00:00"
|
||||
"time": "2026-02-25T16:50:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
@@ -4259,27 +4260,27 @@
|
||||
},
|
||||
{
|
||||
"name": "php-mock/php-mock",
|
||||
"version": "2.6.2",
|
||||
"version": "2.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mock/php-mock.git",
|
||||
"reference": "e134d210e4707c29724ebc7fe50d220123f0fdd9"
|
||||
"reference": "b59734f19765296bb0311942850d02288a224890"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock/zipball/e134d210e4707c29724ebc7fe50d220123f0fdd9",
|
||||
"reference": "e134d210e4707c29724ebc7fe50d220123f0fdd9",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock/zipball/b59734f19765296bb0311942850d02288a224890",
|
||||
"reference": "b59734f19765296bb0311942850d02288a224890",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0 || ^8.0",
|
||||
"phpunit/php-text-template": "^1 || ^2 || ^3 || ^4 || ^5"
|
||||
"phpunit/php-text-template": "^1 || ^2 || ^3 || ^4 || ^5 || ^6"
|
||||
},
|
||||
"replace": {
|
||||
"malkusch/php-mock": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0 || ^13.0",
|
||||
"squizlabs/php_codesniffer": "^3.8"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -4323,7 +4324,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-mock/php-mock/issues",
|
||||
"source": "https://github.com/php-mock/php-mock/tree/2.6.2"
|
||||
"source": "https://github.com/php-mock/php-mock/tree/2.7.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4331,29 +4332,29 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-18T19:59:14+00:00"
|
||||
"time": "2026-02-06T07:39:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-mock/php-mock-integration",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mock/php-mock-integration.git",
|
||||
"reference": "8ceb860f343a143af604efeb66a7a124381cc52e"
|
||||
"reference": "cbbf39705ec13dece5b04133cef4e2fd3137a345"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/8ceb860f343a143af604efeb66a7a124381cc52e",
|
||||
"reference": "8ceb860f343a143af604efeb66a7a124381cc52e",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/cbbf39705ec13dece5b04133cef4e2fd3137a345",
|
||||
"reference": "cbbf39705ec13dece5b04133cef4e2fd3137a345",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"php-mock/php-mock": "^2.5",
|
||||
"phpunit/php-text-template": "^1 || ^2 || ^3 || ^4 || ^5"
|
||||
"phpunit/php-text-template": "^1 || ^2 || ^3 || ^4 || ^5 || ^6"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12"
|
||||
"phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || ^13"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@@ -4386,7 +4387,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-mock/php-mock-integration/issues",
|
||||
"source": "https://github.com/php-mock/php-mock-integration/tree/3.0.0"
|
||||
"source": "https://github.com/php-mock/php-mock-integration/tree/3.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4394,26 +4395,26 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-08T19:22:38+00:00"
|
||||
"time": "2026-02-06T07:44:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-mock/php-mock-phpunit",
|
||||
"version": "2.14.0",
|
||||
"version": "2.15.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mock/php-mock-phpunit.git",
|
||||
"reference": "c074f7a260cb80bdc7cf0823dc23174bc49064e1"
|
||||
"reference": "701df15b183f25af663af134eb71353cd838b955"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/c074f7a260cb80bdc7cf0823dc23174bc49064e1",
|
||||
"reference": "c074f7a260cb80bdc7cf0823dc23174bc49064e1",
|
||||
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/701df15b183f25af663af134eb71353cd838b955",
|
||||
"reference": "701df15b183f25af663af134eb71353cd838b955",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7",
|
||||
"php-mock/php-mock-integration": "^3.0",
|
||||
"phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10.0.17 || ^11 || ^12.0.9"
|
||||
"phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10.0.17 || ^11 || ^12.0.9 || ^13"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.3.6"
|
||||
@@ -4454,7 +4455,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-mock/php-mock-phpunit/issues",
|
||||
"source": "https://github.com/php-mock/php-mock-phpunit/tree/2.14.0"
|
||||
"source": "https://github.com/php-mock/php-mock-phpunit/tree/2.15.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4462,7 +4463,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-19T21:07:31+00:00"
|
||||
"time": "2026-02-06T09:12:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpmd/phpmd",
|
||||
@@ -4549,11 +4550,11 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.33",
|
||||
"version": "2.1.40",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f",
|
||||
"reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
|
||||
"reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4598,7 +4599,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-05T10:24:31+00:00"
|
||||
"time": "2026-02-23T15:04:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
@@ -4923,16 +4924,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "10.5.60",
|
||||
"version": "10.5.63",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "f2e26f52f80ef77832e359205f216eeac00e320c"
|
||||
"reference": "33198268dad71e926626b618f3ec3966661e4d90"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f2e26f52f80ef77832e359205f216eeac00e320c",
|
||||
"reference": "f2e26f52f80ef77832e359205f216eeac00e320c",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33198268dad71e926626b618f3ec3966661e4d90",
|
||||
"reference": "33198268dad71e926626b618f3ec3966661e4d90",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4953,7 +4954,7 @@
|
||||
"phpunit/php-timer": "^6.0.0",
|
||||
"sebastian/cli-parser": "^2.0.1",
|
||||
"sebastian/code-unit": "^2.0.0",
|
||||
"sebastian/comparator": "^5.0.4",
|
||||
"sebastian/comparator": "^5.0.5",
|
||||
"sebastian/diff": "^5.1.1",
|
||||
"sebastian/environment": "^6.1.0",
|
||||
"sebastian/exporter": "^5.1.4",
|
||||
@@ -5004,7 +5005,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.60"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.63"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5028,7 +5029,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-06T07:50:42+00:00"
|
||||
"time": "2026-01-27T05:48:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -5253,16 +5254,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/comparator",
|
||||
"version": "5.0.4",
|
||||
"version": "5.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/comparator.git",
|
||||
"reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e"
|
||||
"reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e8e53097718d2b53cfb2aa859b06a41abf58c62e",
|
||||
"reference": "e8e53097718d2b53cfb2aa859b06a41abf58c62e",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d",
|
||||
"reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5318,7 +5319,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/comparator/issues",
|
||||
"security": "https://github.com/sebastianbergmann/comparator/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/5.0.4"
|
||||
"source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5338,7 +5339,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-09-07T05:25:07+00:00"
|
||||
"time": "2026-01-24T09:25:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/complexity",
|
||||
@@ -6117,16 +6118,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v7.4.3",
|
||||
"version": "v7.4.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/config.git",
|
||||
"reference": "800ce889e358a53a9678b3212b0c8cecd8c6aace"
|
||||
"reference": "9400e2f9226b3b64ebb0a8ae967ae84e54e39640"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/800ce889e358a53a9678b3212b0c8cecd8c6aace",
|
||||
"reference": "800ce889e358a53a9678b3212b0c8cecd8c6aace",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/9400e2f9226b3b64ebb0a8ae967ae84e54e39640",
|
||||
"reference": "9400e2f9226b3b64ebb0a8ae967ae84e54e39640",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6172,7 +6173,7 @@
|
||||
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/config/tree/v7.4.3"
|
||||
"source": "https://github.com/symfony/config/tree/v7.4.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6192,20 +6193,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-23T14:24:27+00:00"
|
||||
"time": "2026-02-25T16:50:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dependency-injection",
|
||||
"version": "v7.4.3",
|
||||
"version": "v7.4.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dependency-injection.git",
|
||||
"reference": "54122901b6d772e94f1e71a75e0533bc16563499"
|
||||
"reference": "a3f7d594ca53a34a7d39ae683fbca09408b0c598"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/54122901b6d772e94f1e71a75e0533bc16563499",
|
||||
"reference": "54122901b6d772e94f1e71a75e0533bc16563499",
|
||||
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a3f7d594ca53a34a7d39ae683fbca09408b0c598",
|
||||
"reference": "a3f7d594ca53a34a7d39ae683fbca09408b0c598",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6256,7 +6257,7 @@
|
||||
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/dependency-injection/tree/v7.4.3"
|
||||
"source": "https://github.com/symfony/dependency-injection/tree/v7.4.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6276,7 +6277,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-28T10:55:46+00:00"
|
||||
"time": "2026-02-25T16:50:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
@@ -6518,5 +6519,5 @@
|
||||
"platform-dev": {
|
||||
"ext-yaml": "*"
|
||||
},
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ function create_account_from_register($arr) {
|
||||
if ( ! $register ) return $result;
|
||||
|
||||
// account
|
||||
$expires = NULL_DATE;
|
||||
$expires = DBA::$dba->get_null_date();
|
||||
|
||||
$default_service_class = Config::Get('system','default_service_class');
|
||||
if($default_service_class === false)
|
||||
@@ -264,9 +264,10 @@ function create_account_from_register($arr) {
|
||||
$result['account']['parent'] = $result['account']['account_id'];
|
||||
}
|
||||
|
||||
$result['success'] = true;
|
||||
|
||||
call_hooks('register_account',$result);
|
||||
if ( send_reg_confirmation_email_from_register($arr['reg_id']) ) {
|
||||
$result['success'] = true;
|
||||
call_hooks('register_account',$result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -311,11 +312,59 @@ function verify_email_address(string $email): bool {
|
||||
pop_lang();
|
||||
|
||||
if(! $res)
|
||||
logger("send_reg_approval_email: failed sending email to: {$email}");
|
||||
logger("send_reg_verification_email: failed sending email to: {$email}");
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email to user confirming approved registration.
|
||||
*
|
||||
* @param int $reg_id The reg_id of the user (from register table)
|
||||
*
|
||||
* @return bool `true` if the email was sucessfully sent, otherwise `false`.
|
||||
*/
|
||||
function send_reg_confirmation_email_from_register(int $reg_id): bool {
|
||||
|
||||
$register = q("SELECT reg_email, reg_lang FROM register WHERE reg_id = %d", $reg_id);
|
||||
|
||||
if (empty($register)) {
|
||||
logger('send_reg_confirmation_email_from_register: could not find email address for for reg_id ' . $reg_id);
|
||||
return false;
|
||||
} else {
|
||||
logger('send_reg_confirmation_email_from_register: sending confirmation email to ' . $register[0]['reg_email']);
|
||||
}
|
||||
|
||||
if(strlen($register['reg_lang'])) {
|
||||
push_lang($register['reg_lang']);
|
||||
} else {
|
||||
push_lang('en');
|
||||
}
|
||||
|
||||
$email_msg = replace_macros(get_intltext_template('register_approved_eml.tpl'), array(
|
||||
'$sitename' => Config::Get('system','sitename'),
|
||||
'$siteurl' => z_root(),
|
||||
'$email' => $register[0]['reg_email'],
|
||||
));
|
||||
|
||||
$res = z_mail(
|
||||
[
|
||||
'toEmail' => $register[0]['reg_email'],
|
||||
'messageSubject' => sprintf( t('Registration approved at %s'), Config::Get('system','sitename')),
|
||||
'textVersion' => $email_msg,
|
||||
]
|
||||
);
|
||||
|
||||
pop_lang();
|
||||
|
||||
if ($res) {
|
||||
return true;
|
||||
} else {
|
||||
logger('send_reg_confirmation_email_from_register: failed to send confirmation email to ' . $register[0]['reg_email']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function send_reg_approval_email($arr) {
|
||||
|
||||
@@ -392,6 +441,88 @@ function send_reg_approval_email($arr) {
|
||||
return($delivered ? true : false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* send_reg_approval_email_from_register
|
||||
* @author ltning
|
||||
* @since 2026-01-25
|
||||
*
|
||||
* Account approval after verification based on table register.
|
||||
* This function sends email to admin(s).
|
||||
*
|
||||
*/
|
||||
function send_reg_approval_email_from_register(int $reg_id): array {
|
||||
|
||||
$result = array('success' => false, 'message' => 'rid:' . $reg_id);
|
||||
$now = datetime_convert();
|
||||
|
||||
$register = q("SELECT * FROM register WHERE reg_id = %d",
|
||||
intval($reg_id)
|
||||
);
|
||||
|
||||
if (empty($register)) {
|
||||
logger('send_reg_approval_email: could not find data for reg_id ' . $reg_id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
$r = q("select * from account where (account_roles & %d) >= 4096",
|
||||
intval(ACCOUNT_ROLE_ADMIN)
|
||||
);
|
||||
|
||||
$admins = array();
|
||||
|
||||
foreach($r as $rr) {
|
||||
if (strlen($rr['account_email'])) {
|
||||
$admins[] = array('email' => $rr['account_email'], 'lang' => $rr['account_lang']);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($admins)) {
|
||||
logger('send_reg_approval_email: could not find any admins to notify for reg_id ' . $reg_id);
|
||||
return $result;
|
||||
}
|
||||
|
||||
$delivered = 0;
|
||||
|
||||
foreach($admins as $admin) {
|
||||
if (strlen($admin['lang'])) {
|
||||
push_lang($admin['lang']);
|
||||
} else {
|
||||
push_lang('en');
|
||||
}
|
||||
|
||||
$email_msg = replace_macros(get_intltext_template('register_verify_eml_no_links.tpl'), array(
|
||||
'$sitename' => Config::Get('system','sitename'),
|
||||
'$siteurl' => z_root(),
|
||||
'$email' => $register[0]['reg_email'],
|
||||
'$details' => $register[0]['reg_atip']
|
||||
));
|
||||
|
||||
$res = z_mail(
|
||||
[
|
||||
'toEmail' => $admin['email'],
|
||||
'messageSubject' => sprintf( t('Registration request at %s'), Config::Get('system','sitename')),
|
||||
'textVersion' => $email_msg,
|
||||
]
|
||||
);
|
||||
|
||||
if ($res) {
|
||||
$delivered ++;
|
||||
} else {
|
||||
logger('send_reg_approval_email: failed to ' . $admin['email'] . 'reg_email: ' . $register[0]['reg_email']);
|
||||
}
|
||||
|
||||
pop_lang();
|
||||
}
|
||||
|
||||
$result['delivered'] = $delivered;
|
||||
if($delivered > 0) {
|
||||
$result['success'] = true;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
function send_register_success_email($email,$password) {
|
||||
|
||||
$email_msg = replace_macros(get_intltext_template('register_open_eml.tpl'), array(
|
||||
@@ -770,7 +901,7 @@ function downgrade_accounts() {
|
||||
and account_expires > '%s'
|
||||
and account_expires < %s ",
|
||||
intval(ACCOUNT_EXPIRED),
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
db_getfunc('UTC_TIMESTAMP')
|
||||
);
|
||||
|
||||
@@ -784,7 +915,7 @@ function downgrade_accounts() {
|
||||
q("UPDATE account set account_service_class = '%s', account_expires = '%s'
|
||||
where account_id = %d",
|
||||
dbesc($basic),
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
intval($rr['account_id'])
|
||||
);
|
||||
$ret = array('account' => $rr);
|
||||
@@ -1083,7 +1214,7 @@ function get_pending_accounts($get_all = false) {
|
||||
function remove_expired_registrations() {
|
||||
q("DELETE FROM register WHERE (reg_expires < '%s' OR reg_expires = '%s') AND (reg_flags & %d) > 0",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(NULL_DATE),
|
||||
dbesc(DBA::$dba->get_null_date()),
|
||||
dbesc(ACCOUNT_UNVERIFIED)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
$records = 10;
|
||||
}
|
||||
if(! $_REQUEST['since'])
|
||||
$start = NULL_DATE;
|
||||
$start = DBA::$dba->get_null_date();
|
||||
else {
|
||||
$start = datetime_convert(date_default_timezone_get(),'UTC', $_REQUEST['since']);
|
||||
}
|
||||
@@ -210,7 +210,7 @@
|
||||
$start = ((array_key_exists('start',$_REQUEST)) ? intval($_REQUEST['start']) : 0);
|
||||
$records = ((array_key_exists('records',$_REQUEST)) ? intval($_REQUEST['records']) : 0);
|
||||
|
||||
$since = ((array_key_exists('since',$_REQUEST)) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['since']) : NULL_DATE);
|
||||
$since = ((array_key_exists('since',$_REQUEST)) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['since']) : DBA::$dba->get_null_date());
|
||||
$until = ((array_key_exists('until',$_REQUEST)) ? datetime_convert(date_default_timezone_get(),'UTC',$_REQUEST['until']) : datetime_convert());
|
||||
|
||||
$x = attach_list_files(api_user(),get_observer_hash(),$hash,$filename,$filetype,'created asc',$start,$records, $since, $until);
|
||||
|
||||
@@ -226,7 +226,7 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $
|
||||
$limit = " LIMIT " . intval($entries) . " OFFSET " . intval($start) . " ";
|
||||
|
||||
if(! $since)
|
||||
$since = NULL_DATE;
|
||||
$since = DBA::$dba->get_null_date();
|
||||
|
||||
if(! $until)
|
||||
$until = datetime_convert();
|
||||
@@ -660,6 +660,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
dbesc($arr['hash']),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
if(! $x) {
|
||||
logger('update file source not found');
|
||||
$ret['message'] = t('Cannot locate file to revise/update');
|
||||
@@ -729,14 +730,14 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$direct = null;
|
||||
|
||||
if($pathname) {
|
||||
$x = attach_mkdirp($channel, $observer_hash, $darr);
|
||||
$folder_hash = (($x['success']) ? $x['data']['hash'] : '');
|
||||
$direct = (($x['success']) ? $x['data'] : null);
|
||||
$new_dir = attach_mkdirp($channel, $observer_hash, $darr);
|
||||
$folder_hash = (($new_dir['success']) ? $new_dir['data']['hash'] : '');
|
||||
$direct = (($new_dir['success']) ? $new_dir['data'] : null);
|
||||
if((! $str_contact_allow) && (! $str_group_allow) && (! $str_contact_deny) && (! $str_group_deny)) {
|
||||
$str_contact_allow = $x['data']['allow_cid'];
|
||||
$str_group_allow = $x['data']['allow_gid'];
|
||||
$str_contact_deny = $x['data']['deny_cid'];
|
||||
$str_group_deny = $x['data']['deny_gid'];
|
||||
$str_contact_allow = $new_dir['data']['allow_cid'];
|
||||
$str_group_allow = $new_dir['data']['allow_gid'];
|
||||
$str_contact_deny = $new_dir['data']['deny_cid'];
|
||||
$str_group_deny = $new_dir['data']['deny_gid'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1302,7 +1302,7 @@ function channel_export_items_page($channel_id, $start, $finish, $page = 0, $lim
|
||||
}
|
||||
|
||||
if(! $start)
|
||||
$start = NULL_DATE;
|
||||
$start = DBA::$dba->get_null_date();
|
||||
else
|
||||
$start = datetime_convert('UTC', 'UTC', $start);
|
||||
|
||||
@@ -1823,7 +1823,7 @@ function advanced_profile() {
|
||||
if(App::$profile['partner'])
|
||||
$profile['marital']['partner'] = zidify_links(bbcode(App::$profile['partner']));
|
||||
|
||||
if(strlen(App::$profile['howlong']) && App::$profile['howlong'] > NULL_DATE) {
|
||||
if(strlen(App::$profile['howlong']) && App::$profile['howlong'] > DBA::$dba->get_null_date()) {
|
||||
$profile['howlong'] = relative_date(App::$profile['howlong'], t('for %1$d %2$s'));
|
||||
}
|
||||
|
||||
@@ -2649,10 +2649,10 @@ function channel_store_lowlevel($arr) {
|
||||
'channel_eprvkey' => ((array_key_exists('channel_eprvkey',$arr)) ? $arr['channel_eprvkey'] : ''),
|
||||
'channel_notifyflags' => ((array_key_exists('channel_notifyflags',$arr)) ? $arr['channel_notifyflags'] : '65535'),
|
||||
'channel_pageflags' => ((array_key_exists('channel_pageflags',$arr)) ? $arr['channel_pageflags'] : '0'),
|
||||
'channel_dirdate' => ((array_key_exists('channel_dirdate',$arr)) ? $arr['channel_dirdate'] : NULL_DATE),
|
||||
'channel_lastpost' => ((array_key_exists('channel_lastpost',$arr)) ? $arr['channel_lastpost'] : NULL_DATE),
|
||||
'channel_deleted' => ((array_key_exists('channel_deleted',$arr)) ? $arr['channel_deleted'] : NULL_DATE),
|
||||
'channel_active' => ((array_key_exists('channel_active',$arr)) ? $arr['channel_active'] : NULL_DATE),
|
||||
'channel_dirdate' => ((array_key_exists('channel_dirdate',$arr)) ? $arr['channel_dirdate'] : DBA::$dba->get_null_date()),
|
||||
'channel_lastpost' => ((array_key_exists('channel_lastpost',$arr)) ? $arr['channel_lastpost'] : DBA::$dba->get_null_date()),
|
||||
'channel_deleted' => ((array_key_exists('channel_deleted',$arr)) ? $arr['channel_deleted'] : DBA::$dba->get_null_date()),
|
||||
'channel_active' => ((array_key_exists('channel_active',$arr)) ? $arr['channel_active'] : DBA::$dba->get_null_date()),
|
||||
'channel_max_anon_mail' => ((array_key_exists('channel_max_anon_mail',$arr)) ? $arr['channel_max_anon_mail'] : '10'),
|
||||
'channel_max_friend_req' => ((array_key_exists('channel_max_friend_req',$arr)) ? $arr['channel_max_friend_req'] : '10'),
|
||||
'channel_expire_days' => ((array_key_exists('channel_expire_days',$arr)) ? $arr['channel_expire_days'] : '0'),
|
||||
@@ -2695,7 +2695,7 @@ function profile_store_lowlevel($arr) {
|
||||
'gender' => ((array_key_exists('gender',$arr)) ? $arr['gender'] : ''),
|
||||
'marital' => ((array_key_exists('marital',$arr)) ? $arr['marital'] : ''),
|
||||
'partner' => ((array_key_exists('partner',$arr)) ? $arr['partner'] : ''),
|
||||
'howlong' => ((array_key_exists('howlong',$arr)) ? $arr['howlong'] : NULL_DATE),
|
||||
'howlong' => ((array_key_exists('howlong',$arr)) ? $arr['howlong'] : DBA::$dba->get_null_date()),
|
||||
'sexual' => ((array_key_exists('sexual',$arr)) ? $arr['sexual'] : ''),
|
||||
'politic' => ((array_key_exists('politic',$arr)) ? $arr['politic'] : ''),
|
||||
'religion' => ((array_key_exists('religion',$arr)) ? $arr['religion'] : ''),
|
||||
|
||||
@@ -12,10 +12,10 @@ function abook_store_lowlevel($arr) {
|
||||
'abook_my_perms' => ((array_key_exists('abook_my_perms',$arr)) ? $arr['abook_my_perms'] : 0),
|
||||
'abook_their_perms' => ((array_key_exists('abook_their_perms',$arr)) ? $arr['abook_their_perms'] : 0),
|
||||
'abook_closeness' => ((array_key_exists('abook_closeness',$arr)) ? $arr['abook_closeness'] : 99),
|
||||
'abook_created' => ((array_key_exists('abook_created',$arr)) ? $arr['abook_created'] : NULL_DATE),
|
||||
'abook_updated' => ((array_key_exists('abook_updated',$arr)) ? $arr['abook_updated'] : NULL_DATE),
|
||||
'abook_connected' => ((array_key_exists('abook_connected',$arr)) ? $arr['abook_connected'] : NULL_DATE),
|
||||
'abook_dob' => ((array_key_exists('abook_dob',$arr)) ? $arr['abook_dob'] : NULL_DATE),
|
||||
'abook_created' => ((array_key_exists('abook_created',$arr)) ? $arr['abook_created'] : DBA::$dba->get_null_date()),
|
||||
'abook_updated' => ((array_key_exists('abook_updated',$arr)) ? $arr['abook_updated'] : DBA::$dba->get_null_date()),
|
||||
'abook_connected' => ((array_key_exists('abook_connected',$arr)) ? $arr['abook_connected'] : DBA::$dba->get_null_date()),
|
||||
'abook_dob' => ((array_key_exists('abook_dob',$arr)) ? $arr['abook_dob'] : DBA::$dba->get_null_date()),
|
||||
'abook_flags' => ((array_key_exists('abook_flags',$arr)) ? $arr['abook_flags'] : 0),
|
||||
'abook_blocked' => ((array_key_exists('abook_blocked',$arr)) ? $arr['abook_blocked'] : 0),
|
||||
'abook_ignored' => ((array_key_exists('abook_ignored',$arr)) ? $arr['abook_ignored'] : 0),
|
||||
|
||||
@@ -630,7 +630,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
|
||||
'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'),
|
||||
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
|
||||
'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''),
|
||||
'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
|
||||
'expiretime' => (($item['expires'] > DBA::$dba->get_null_date()) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''),
|
||||
'location' => $location,
|
||||
'divider' => false,
|
||||
'indent' => '',
|
||||
|
||||
@@ -101,19 +101,13 @@ abstract class dba_driver {
|
||||
public $error = false;
|
||||
|
||||
/**
|
||||
* @brief Connect to the database.
|
||||
* Connects to the database.
|
||||
*
|
||||
* This abstract function needs to be implemented in the real driver.
|
||||
*
|
||||
* @param string $server DB server name
|
||||
* @param string $scheme DB scheme
|
||||
* @param string $port DB port
|
||||
* @param string $user DB username
|
||||
* @param string $pass DB password
|
||||
* @param string $db database name
|
||||
* @return bool
|
||||
*/
|
||||
abstract function connect($server, $scheme, $port, $user, $pass, $db, $db_charset);
|
||||
abstract function connect(): bool;
|
||||
|
||||
/**
|
||||
* @brief Perform a DB query with the SQL statement $sql.
|
||||
@@ -147,18 +141,27 @@ abstract class dba_driver {
|
||||
*/
|
||||
abstract function getdriver();
|
||||
|
||||
function __construct($server, $scheme, $port, $user,$pass,$db,$db_charset,$install = false) {
|
||||
if(($install) && (! $this->install($server, $scheme, $port, $user, $pass, $db, $db_charset))) {
|
||||
function __construct(
|
||||
readonly string $server,
|
||||
readonly string $scheme,
|
||||
readonly string $port,
|
||||
readonly string $user,
|
||||
protected string $pass,
|
||||
readonly string $dbname,
|
||||
readonly string $db_charset,
|
||||
$install = false)
|
||||
{
|
||||
if ($install && ! $this->install()) {
|
||||
return;
|
||||
}
|
||||
$this->connect($server, $scheme, $port, $user, $pass, $db, $db_charset);
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
function get_null_date() {
|
||||
return \DBA::$null_date;
|
||||
}
|
||||
|
||||
function get_install_script() {
|
||||
public static function get_install_script() {
|
||||
$platform_name = \Zotlabs\Lib\System::get_platform_name();
|
||||
if(file_exists('install/' . $platform_name . '/' . \DBA::$install_script))
|
||||
return 'install/' . $platform_name . '/' . \DBA::$install_script;
|
||||
@@ -174,8 +177,8 @@ abstract class dba_driver {
|
||||
return \DBA::$utc_now;
|
||||
}
|
||||
|
||||
function install($server,$scheme,$port,$user,$pass,$db) {
|
||||
if (!(strlen($server) && strlen($user))){
|
||||
function install() {
|
||||
if (!strlen($this->server) && strlen($this->user)) {
|
||||
$this->connected = false;
|
||||
$this->db = null;
|
||||
return false;
|
||||
@@ -269,7 +272,7 @@ function dbg($state) {
|
||||
function dbesc($str) {
|
||||
|
||||
if(is_null_date($str))
|
||||
$str = NULL_DATE;
|
||||
$str = DBA::$dba->get_null_date();
|
||||
|
||||
if(\DBA::$dba && \DBA::$dba->connected)
|
||||
return(\DBA::$dba->escape($str));
|
||||
@@ -286,7 +289,7 @@ function dbunescbin($str) {
|
||||
|
||||
function dbescdate($date) {
|
||||
if(is_null_date($date))
|
||||
return \DBA::$dba->escape(NULL_DATE);
|
||||
return \DBA::$dba->escape(DBA::$dba->get_null_date());
|
||||
|
||||
return \DBA::$dba->escape($date);
|
||||
}
|
||||
@@ -389,7 +392,7 @@ function dbq($sql) {
|
||||
function dbesc_array_cb(&$item, $key) {
|
||||
if(is_string($item)) {
|
||||
if(is_null_date($item))
|
||||
$item = NULL_DATE;
|
||||
$item = DBA::$dba->get_null_date();
|
||||
$item = dbesc($item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,31 +14,35 @@ class dba_pdo extends dba_driver {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see dba_driver::connect()
|
||||
*/
|
||||
function connect($server, $scheme, $port, $user, $pass, $db, $db_charset) {
|
||||
function connect(): bool {
|
||||
|
||||
$this->driver_dbtype = $scheme;
|
||||
$this->driver_dbtype = $this->scheme;
|
||||
|
||||
if(strpbrk($server,':;')) {
|
||||
$dsn = $this->driver_dbtype . ':unix_socket=' . trim($server, ':;');
|
||||
if(strpbrk($this->server,':;')) {
|
||||
$dsn = $this->driver_dbtype . ':unix_socket=' . trim($this->server, ':;');
|
||||
}
|
||||
else {
|
||||
$dsn = $this->driver_dbtype . ':host=' . $server . (intval($port) ? ';port=' . $port : '');
|
||||
$dsn = $this->driver_dbtype
|
||||
. ':host='
|
||||
. $this->server
|
||||
. (intval($this->port) ? ';port=' . $this->port : '');
|
||||
}
|
||||
|
||||
$dsn .= ';dbname=' . $db;
|
||||
$dsn .= ';dbname=' . $this->dbname;
|
||||
|
||||
if ($this->driver_dbtype === 'mysql') {
|
||||
$dsn .= ';charset=' . $db_charset;
|
||||
$dsn .= ';charset=' . $this->db_charset;
|
||||
}
|
||||
else {
|
||||
$dsn .= ";options='--client_encoding=" . $db_charset . "'";
|
||||
$dsn .= ";options='--client_encoding=" . $this->db_charset . "'";
|
||||
}
|
||||
|
||||
try {
|
||||
$this->db = new PDO($dsn,$user,$pass);
|
||||
$this->db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
|
||||
$this->db = new PDO($dsn, $this->user, $this->pass);
|
||||
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->server_version = $this->db->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
|
||||
@@ -162,7 +162,7 @@ function format_event_obj($jobject) {
|
||||
'$dtend_dt' => $dtend_dt,
|
||||
'$allday' => $allday,
|
||||
'$oneday' => $oneday,
|
||||
'$event_tz' => ['label' => t('Timezone'), 'value' => (($tz === date_default_timezone_get()) ? '' : $tz)]
|
||||
'$tz' => ['label' => t('Timezone'), 'value' => (($tz && $tz !== date_default_timezone_get()) ? date_default_timezone_get() : '')]
|
||||
));
|
||||
|
||||
$event['content'] = replace_macros(get_markup_template('event_item_content.tpl'), array(
|
||||
@@ -537,14 +537,14 @@ function event_store_event($arr) {
|
||||
$arr['deny_gid'] = $arr['deny_gid'] ?? '';
|
||||
|
||||
if (! $arr['dtend']) {
|
||||
$arr['dtend'] = NULL_DATE;
|
||||
$arr['dtend'] = DBA::$dba->get_null_date();
|
||||
$arr['nofinish'] = 1;
|
||||
}
|
||||
|
||||
if(array_key_exists('event_status_date',$arr))
|
||||
$arr['event_status_date'] = datetime_convert('UTC','UTC', $arr['event_status_date']);
|
||||
else
|
||||
$arr['event_status_date'] = NULL_DATE;
|
||||
$arr['event_status_date'] = DBA::$dba->get_null_date();
|
||||
|
||||
|
||||
$existing_event = null;
|
||||
|
||||
@@ -25,7 +25,7 @@ function get_public_feed($channel, $params) {
|
||||
$params = [];
|
||||
|
||||
$params['type'] = ((x($params,'type')) ? $params['type'] : 'xml');
|
||||
$params['begin'] = ((x($params,'begin')) ? $params['begin'] : NULL_DATE);
|
||||
$params['begin'] = ((x($params,'begin')) ? $params['begin'] : DBA::$dba->get_null_date());
|
||||
$params['end'] = ((x($params,'end')) ? $params['end'] : datetime_convert('UTC','UTC','now'));
|
||||
$params['start'] = ((x($params,'start')) ? $params['start'] : 0);
|
||||
$params['records'] = ((x($params,'records')) ? $params['records'] : 40);
|
||||
@@ -1302,7 +1302,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
|
||||
if($r) {
|
||||
$parent_item = $r[0];
|
||||
if(intval($parent_item['item_nocomment']) || $parent_item['comment_policy'] === 'none'
|
||||
|| ($parent_item['comments_closed'] > NULL_DATE && $parent_item['comments_closed'] < datetime_convert())) {
|
||||
|| ($parent_item['comments_closed'] > DBA::$dba->get_null_date() && $parent_item['comments_closed'] < datetime_convert())) {
|
||||
logger('comments disabled for post ' . $parent_item['mid']);
|
||||
continue;
|
||||
}
|
||||
@@ -1459,7 +1459,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
|
||||
|
||||
$datarray['owner_xchan'] = $contact['xchan_hash'];
|
||||
|
||||
if(array_key_exists('created',$datarray) && $datarray['created'] > NULL_DATE && $expire_days) {
|
||||
if(array_key_exists('created',$datarray) && $datarray['created'] > DBA::$dba->get_null_date() && $expire_days) {
|
||||
$t1 = $datarray['created'];
|
||||
$t2 = datetime_convert('UTC','UTC','now - ' . $expire_days . 'days');
|
||||
if($t1 < $t2) {
|
||||
|
||||
@@ -35,8 +35,8 @@ function hubloc_store_lowlevel($arr) {
|
||||
'hubloc_callback' => ((array_key_exists('hubloc_callback',$arr)) ? $arr['hubloc_callback'] : ''),
|
||||
'hubloc_connect' => ((array_key_exists('hubloc_connect',$arr)) ? $arr['hubloc_connect'] : ''),
|
||||
'hubloc_sitekey' => ((array_key_exists('hubloc_sitekey',$arr)) ? $arr['hubloc_sitekey'] : ''),
|
||||
'hubloc_updated' => ((array_key_exists('hubloc_updated',$arr)) ? $arr['hubloc_updated'] : NULL_DATE),
|
||||
'hubloc_connected' => ((array_key_exists('hubloc_connected',$arr)) ? $arr['hubloc_connected'] : NULL_DATE),
|
||||
'hubloc_updated' => ((array_key_exists('hubloc_updated',$arr)) ? $arr['hubloc_updated'] : DBA::$dba->get_null_date()),
|
||||
'hubloc_connected' => ((array_key_exists('hubloc_connected',$arr)) ? $arr['hubloc_connected'] : DBA::$dba->get_null_date()),
|
||||
'hubloc_primary' => ((array_key_exists('hubloc_primary',$arr)) ? $arr['hubloc_primary'] : 0),
|
||||
'hubloc_orphancheck' => ((array_key_exists('hubloc_orphancheck',$arr)) ? $arr['hubloc_orphancheck'] : 0),
|
||||
'hubloc_error' => ((array_key_exists('hubloc_error',$arr)) ? $arr['hubloc_error'] : 0),
|
||||
@@ -52,9 +52,9 @@ function site_store_lowlevel($arr) {
|
||||
'site_url' => ((array_key_exists('site_url',$arr)) ? $arr['site_url'] : ''),
|
||||
'site_access' => ((array_key_exists('site_access',$arr)) ? $arr['site_access'] : 0),
|
||||
'site_flags' => ((array_key_exists('site_flags',$arr)) ? $arr['site_flags'] : 0),
|
||||
'site_update' => ((array_key_exists('site_update',$arr)) ? $arr['site_update'] : NULL_DATE),
|
||||
'site_pull' => ((array_key_exists('site_pull',$arr)) ? $arr['site_pull'] : NULL_DATE),
|
||||
'site_sync' => ((array_key_exists('site_sync',$arr)) ? $arr['site_sync'] : NULL_DATE),
|
||||
'site_update' => ((array_key_exists('site_update',$arr)) ? $arr['site_update'] : DBA::$dba->get_null_date()),
|
||||
'site_pull' => ((array_key_exists('site_pull',$arr)) ? $arr['site_pull'] : DBA::$dba->get_null_date()),
|
||||
'site_sync' => ((array_key_exists('site_sync',$arr)) ? $arr['site_sync'] : DBA::$dba->get_null_date()),
|
||||
'site_directory' => ((array_key_exists('site_directory',$arr)) ? $arr['site_directory'] : ''),
|
||||
'site_register' => ((array_key_exists('site_register',$arr)) ? $arr['site_register'] : 0),
|
||||
'site_sellpage' => ((array_key_exists('site_sellpage',$arr)) ? $arr['site_sellpage'] : ''),
|
||||
@@ -362,7 +362,7 @@ function z6_discover() {
|
||||
// find unregistered zot6 clone hublocs
|
||||
|
||||
$c = q("select channel_hash, channel_portable_id from channel where channel_deleted = '%s'",
|
||||
dbesc(NULL_DATE)
|
||||
dbesc(DBA::$dba->get_null_date())
|
||||
);
|
||||
if ($c) {
|
||||
foreach ($c as $entry) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\Apps;
|
||||
use Zotlabs\Lib\Config;
|
||||
use Zotlabs\Lib\IConfig;
|
||||
@@ -532,9 +533,9 @@ function sync_apps($channel, $apps) {
|
||||
);
|
||||
}
|
||||
|
||||
if((! $app['app_created']) || ($app['app_created'] <= NULL_DATE))
|
||||
if((! $app['app_created']) || ($app['app_created'] <= DBA::$dba->get_null_date()))
|
||||
$app['app_created'] = datetime_convert();
|
||||
if((! $app['app_edited']) || ($app['app_edited'] <= NULL_DATE))
|
||||
if((! $app['app_edited']) || ($app['app_edited'] <= DBA::$dba->get_null_date()))
|
||||
$app['app_edited'] = datetime_convert();
|
||||
|
||||
$app['app_channel'] = $channel['channel_id'];
|
||||
@@ -746,9 +747,9 @@ function sync_chatrooms($channel, $chatrooms) {
|
||||
unset($chatroom['cr_aid']);
|
||||
unset($chatroom['cr_uid']);
|
||||
|
||||
if((! $chatroom['cr_created']) || ($chatroom['cr_created'] <= NULL_DATE))
|
||||
if((! $chatroom['cr_created']) || ($chatroom['cr_created'] <= DBA::$dba->get_null_date()))
|
||||
$chatroom['cr_created'] = datetime_convert();
|
||||
if((! $chatroom['cr_edited']) || ($chatroom['cr_edited'] <= NULL_DATE))
|
||||
if((! $chatroom['cr_edited']) || ($chatroom['cr_edited'] <= DBA::$dba->get_null_date()))
|
||||
$chatroom['cr_edited'] = datetime_convert();
|
||||
|
||||
$chatroom['cr_aid'] = $channel['channel_account_id'];
|
||||
|
||||
@@ -232,7 +232,7 @@ function comments_are_now_closed($item) {
|
||||
return $x['closed'];
|
||||
}
|
||||
|
||||
if($item['comments_closed'] > NULL_DATE) {
|
||||
if($item['comments_closed'] > DBA::$dba->get_null_date()) {
|
||||
$d = datetime_convert();
|
||||
if($d > $item['comments_closed'])
|
||||
return true;
|
||||
@@ -732,14 +732,14 @@ function get_item_elements($x,$allow_code = false) {
|
||||
|
||||
$arr['expires'] = ((!empty($x['expires']) && $x['expires'])
|
||||
? datetime_convert('UTC','UTC',$x['expires'])
|
||||
: NULL_DATE);
|
||||
: DBA::$dba->get_null_date());
|
||||
|
||||
$arr['commented'] = ((!empty($x['commented']) && $x['commented'])
|
||||
? datetime_convert('UTC','UTC',$x['commented'])
|
||||
: $arr['created']);
|
||||
$arr['comments_closed'] = ((!empty($x['comments_closed']) && $x['comments_closed'])
|
||||
? datetime_convert('UTC','UTC',$x['comments_closed'])
|
||||
: NULL_DATE);
|
||||
: DBA::$dba->get_null_date());
|
||||
|
||||
$arr['title'] = (($x['title']) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
|
||||
@@ -1210,7 +1210,7 @@ function encode_item($item,$mirror = false,$zap_compat = false) {
|
||||
if($y = encode_item_flags($item))
|
||||
$x['flags'] = $y;
|
||||
|
||||
if($item['comments_closed'] > NULL_DATE)
|
||||
if($item['comments_closed'] > DBA::$dba->get_null_date())
|
||||
$x['comments_closed'] = $item['comments_closed'];
|
||||
|
||||
$x['public_scope'] = $item['public_policy'];
|
||||
@@ -1773,9 +1773,9 @@ function item_store($arr, $allow_exec = false, $deliver = true, $addAndSync = tr
|
||||
$arr['owner_xchan'] = ((!empty($arr['owner_xchan'])) ? notags(trim($arr['owner_xchan'])) : '');
|
||||
$arr['created'] = ((!empty($arr['created']) !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert());
|
||||
$arr['edited'] = ((!empty($arr['edited']) !== false) ? datetime_convert('UTC','UTC',$arr['edited']) : datetime_convert());
|
||||
$arr['expires'] = ((!empty($arr['expires']) !== false) ? datetime_convert('UTC','UTC',$arr['expires']) : NULL_DATE);
|
||||
$arr['expires'] = ((!empty($arr['expires']) !== false) ? datetime_convert('UTC','UTC',$arr['expires']) : DBA::$dba->get_null_date());
|
||||
$arr['commented'] = ((!empty($arr['commented']) !== false) ? datetime_convert('UTC','UTC',$arr['commented']) : datetime_convert());
|
||||
$arr['comments_closed'] = ((!empty($arr['comments_closed']) !== false) ? datetime_convert('UTC','UTC',$arr['comments_closed']) : NULL_DATE);
|
||||
$arr['comments_closed'] = ((!empty($arr['comments_closed']) !== false) ? datetime_convert('UTC','UTC',$arr['comments_closed']) : DBA::$dba->get_null_date());
|
||||
$arr['html'] = ((array_key_exists('html',$arr)) ? $arr['html'] : '');
|
||||
|
||||
if($deliver) {
|
||||
@@ -4440,7 +4440,7 @@ function zot_feed($uid, $observer_hash, $arr) {
|
||||
}
|
||||
|
||||
if (!$mindate)
|
||||
$mindate = NULL_DATE;
|
||||
$mindate = DBA::$dba->get_null_date();
|
||||
|
||||
$mindate = dbesc($mindate);
|
||||
|
||||
@@ -4458,7 +4458,7 @@ function zot_feed($uid, $observer_hash, $arr) {
|
||||
|
||||
$limit = " LIMIT 5000 ";
|
||||
|
||||
if ($mindate > NULL_DATE) {
|
||||
if ($mindate > DBA::$dba->get_null_date()) {
|
||||
$sql_extra .= " and ( created > '$mindate' or changed > '$mindate' ) ";
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,6 @@ use Zotlabs\Web\HTTPSig;
|
||||
* @brief Network related functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns path to CA file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_capath() {
|
||||
return appdirpath() . '/library/cacert.pem';
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fetches an URL.
|
||||
*
|
||||
@@ -63,12 +54,17 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
|
||||
|
||||
@curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
@curl_setopt($ch, CURLINFO_HEADER_OUT, true);
|
||||
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
|
||||
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
|
||||
@curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; zot)');
|
||||
@curl_setopt($ch, CURLOPT_ENCODING, '');
|
||||
|
||||
if (!empty($opts['useragent'])) {
|
||||
@curl_setopt($ch, CURLOPT_USERAGENT, $opts['useragent']);
|
||||
}
|
||||
else {
|
||||
@curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; zot)');
|
||||
}
|
||||
|
||||
$ciphers = @Config::Get('system','curl_ssl_ciphers');
|
||||
if($ciphers)
|
||||
@curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers);
|
||||
@@ -256,13 +252,18 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
|
||||
|
||||
@curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
@curl_setopt($ch, CURLINFO_HEADER_OUT, true);
|
||||
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
|
||||
@curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
|
||||
@curl_setopt($ch, CURLOPT_POST,1);
|
||||
@curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
|
||||
@curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; zot)");
|
||||
@curl_setopt($ch, CURLOPT_ENCODING, '');
|
||||
|
||||
if (!empty($opts['useragent'])) {
|
||||
@curl_setopt($ch, CURLOPT_USERAGENT, $opts['useragent']);
|
||||
}
|
||||
else {
|
||||
@curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; zot)');
|
||||
}
|
||||
|
||||
$ciphers = @Config::Get('system','curl_ssl_ciphers');
|
||||
if($ciphers)
|
||||
@curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, $ciphers);
|
||||
@@ -1220,39 +1221,62 @@ function discover_by_webbie($webbie, $protocol = '') {
|
||||
* @return boolean|string false or associative array from result JSON
|
||||
*/
|
||||
function webfinger_rfc7033($webbie, $zot = false) {
|
||||
$parsed = parse_webbie($webbie);
|
||||
|
||||
if(filter_var($webbie, FILTER_VALIDATE_EMAIL)) {
|
||||
$lhs = substr($webbie,0,strpos($webbie,'@'));
|
||||
$rhs = substr($webbie,strpos($webbie,'@')+1);
|
||||
$resource = urlencode('acct:' . $webbie);
|
||||
}
|
||||
elseif(filter_var($webbie, FILTER_VALIDATE_URL)) {
|
||||
$m = parse_url($webbie);
|
||||
if($m) {
|
||||
if($m['scheme'] !== 'https')
|
||||
return false;
|
||||
|
||||
$rhs = $m['host'] . (array_key_exists('port', $m) ? ':' . $m['port'] : '');
|
||||
$resource = urlencode($webbie);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!$parsed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
logger('fetching url from resource: ' . $rhs . ':' . $webbie);
|
||||
logger('fetching url from resource: ' . $parsed['host'] . ':' . $parsed['resource']);
|
||||
|
||||
$counter = 0;
|
||||
$s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''),
|
||||
false, $counter, [ 'headers' => [ 'Accept: application/jrd+json, application/json, */*' ] ]);
|
||||
$s = z_fetch_url('https://' . $parsed['host'] . '/.well-known/webfinger?f=&resource=' . $parsed['resource'] . (($zot) ? '&zot=1' : ''),
|
||||
false, 0, [ 'headers' => [ 'Accept: application/jrd+json, application/json, */*' ] ]);
|
||||
|
||||
if($s['success']) {
|
||||
$j = json_decode($s['body'], true);
|
||||
return($j);
|
||||
return $j;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function parse_webbie($webbie) {
|
||||
$parsed = parse_url($webbie);
|
||||
|
||||
if (!$parsed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($parsed['scheme'])) {
|
||||
$parsed['scheme'] = 'acct';
|
||||
}
|
||||
|
||||
if (in_array($parsed['scheme'], ['http', 'https'])) {
|
||||
$result['host'] = $parsed['host'] . ((isset($parsed['port'])) ? ':' . $parsed['port'] : '');
|
||||
$result['resource'] = urlencode($webbie);
|
||||
}
|
||||
elseif ($parsed['scheme'] === 'acct') {
|
||||
$parts = explode('@', ltrim($parsed['path'], '@'));
|
||||
|
||||
if (count($parts) !== 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result['host'] = $parts[1];
|
||||
$result['resource'] = urlencode('acct:' . $parts[0] . '@' . $parts[1]);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($result['host'], $result['resource'])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function old_webfinger($webbie) {
|
||||
|
||||
$host = '';
|
||||
@@ -1838,13 +1862,20 @@ function probe_api_path($host) {
|
||||
}
|
||||
|
||||
|
||||
function scrape_vcard($url) {
|
||||
function scrape_vcard($url, $useragent = '') {
|
||||
|
||||
$ret = array();
|
||||
|
||||
logger('url=' . $url);
|
||||
|
||||
$x = z_fetch_url($url);
|
||||
$opts = [];
|
||||
|
||||
if ($useragent) {
|
||||
$opts['useragent'] = $useragent;
|
||||
}
|
||||
|
||||
$x = z_fetch_url($url, opts: $opts);
|
||||
|
||||
if(! $x['success']) {
|
||||
logger('ERROR fetching URL');
|
||||
return $ret;
|
||||
|
||||
@@ -2017,7 +2017,7 @@ function format_poll($item,$s,$opts) {
|
||||
|
||||
$message = (($totalResponses) ? sprintf(tt('%d Vote in total', '%d Votes in total', $totalResponses, 'noun'), $totalResponses) . EOL : '');
|
||||
|
||||
if ($item['comments_closed'] > NULL_DATE) {
|
||||
if ($item['comments_closed'] > DBA::$dba->get_null_date()) {
|
||||
$t = datetime_convert('UTC',date_default_timezone_get(), $item['comments_closed'], 'Y-m-d H:i');
|
||||
$closed = ((datetime_convert() > $item['comments_closed']) ? true : false);
|
||||
if ($closed) {
|
||||
|
||||
@@ -31,9 +31,9 @@ function xchan_store_lowlevel($arr) {
|
||||
'xchan_network' => ((array_key_exists('xchan_network',$arr)) ? $arr['xchan_network'] : ''),
|
||||
'xchan_instance_url' => ((array_key_exists('xchan_instance_url',$arr)) ? $arr['xchan_instance_url'] : ''),
|
||||
'xchan_flags' => ((array_key_exists('xchan_flags',$arr)) ? intval($arr['xchan_flags']) : 0),
|
||||
'xchan_photo_date' => ((array_key_exists('xchan_photo_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_photo_date']) : NULL_DATE),
|
||||
'xchan_name_date' => ((array_key_exists('xchan_name_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_name_date']) : NULL_DATE),
|
||||
'xchan_updated' => ((array_key_exists('xchan_updated',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_updated']) : NULL_DATE),
|
||||
'xchan_photo_date' => ((array_key_exists('xchan_photo_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_photo_date']) : DBA::$dba->get_null_date()),
|
||||
'xchan_name_date' => ((array_key_exists('xchan_name_date',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_name_date']) : DBA::$dba->get_null_date()),
|
||||
'xchan_updated' => ((array_key_exists('xchan_updated',$arr)) ? datetime_convert('UTC','UTC',$arr['xchan_updated']) : DBA::$dba->get_null_date()),
|
||||
'xchan_hidden' => ((array_key_exists('xchan_hidden',$arr)) ? intval($arr['xchan_hidden']) : 0),
|
||||
'xchan_orphan' => ((array_key_exists('xchan_orphan',$arr)) ? intval($arr['xchan_orphan']) : 0),
|
||||
'xchan_censored' => ((array_key_exists('xchan_censored',$arr)) ? intval($arr['xchan_censored']) : 0),
|
||||
|
||||
@@ -150,28 +150,29 @@ function clean_query_string($s = '') {
|
||||
*/
|
||||
|
||||
function drop_query_params($s, $p) {
|
||||
$unescaped = unescape_tags($s);
|
||||
$parsed = parse_url($unescaped);
|
||||
|
||||
$s = unescape_tags($s);
|
||||
|
||||
$parsed = parse_url($s);
|
||||
$query = '';
|
||||
$query_args = null;
|
||||
|
||||
if(isset($parsed['query'])) {
|
||||
parse_str($parsed['query'], $query_args);
|
||||
if (empty($parsed['query'])) {
|
||||
// No query parameters were found, return the original string
|
||||
return $s;
|
||||
}
|
||||
|
||||
if(is_array($query_args)) {
|
||||
foreach($query_args as $k => $v) {
|
||||
if(in_array($k, $p))
|
||||
continue;
|
||||
$query .= (($query) ? '&' : '') . urlencode($k) . '=' . urlencode($v);
|
||||
$query_args = [];
|
||||
|
||||
parse_str($parsed['query'], $query_args);
|
||||
|
||||
foreach($query_args as $k => $v) {
|
||||
if (in_array($k, $p)) {
|
||||
unset($query_args[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
unset($parsed['query']);
|
||||
|
||||
if($query) {
|
||||
$query = http_build_query($query_args, '', '&');
|
||||
|
||||
if ($query) {
|
||||
$parsed['query'] = $query;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,150 +1,73 @@
|
||||
##
|
||||
# Red Nginx configuration
|
||||
# by Olaf Conradi
|
||||
#
|
||||
# On Debian based distributions you can add this file to
|
||||
# /etc/nginx/sites-available
|
||||
#
|
||||
# Then customize to your needs. To enable the configuration
|
||||
# symlink it to /etc/nginx/sites-enabled and reload Nginx using
|
||||
#
|
||||
# service nginx reload
|
||||
##
|
||||
|
||||
##
|
||||
# You should look at the following URL's in order to grasp a solid understanding
|
||||
# of Nginx configuration files in order to fully unleash the power of Nginx.
|
||||
#
|
||||
# http://wiki.nginx.org/Pitfalls
|
||||
# http://wiki.nginx.org/QuickStart
|
||||
# http://wiki.nginx.org/Configuration
|
||||
##
|
||||
|
||||
##
|
||||
# This configuration assumes your domain is example.net
|
||||
# You have a separate subdomain red.example.net
|
||||
# You want all red traffic to be https
|
||||
# You have an SSL certificate and key for your subdomain
|
||||
# You have PHP FastCGI Process Manager (php5-fpm) running on localhost
|
||||
# You have Red installed in /var/www/red
|
||||
##
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name red.example.net;
|
||||
server_name hub.example.org;
|
||||
|
||||
index index.php;
|
||||
root /var/www/red;
|
||||
rewrite ^ https://red.example.net$request_uri? permanent;
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
##
|
||||
# Configure Red with SSL
|
||||
#
|
||||
# All requests are routed to the front controller
|
||||
# except for certain known file types like images, css, etc.
|
||||
# Those are served statically whenever possible with a
|
||||
# fall back to the front controller (needed for avatars, for example)
|
||||
##
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name red.example.net;
|
||||
server_name hub.example.org;
|
||||
|
||||
ssl on;
|
||||
ssl_certificate /etc/nginx/ssl/red.example.net.chain.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/example.net.key;
|
||||
ssl_session_timeout 5m;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;
|
||||
ssl_prefer_server_ciphers on;
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
http2 on;
|
||||
|
||||
fastcgi_param HTTPS on;
|
||||
## Quic and HTTP3 Requires Nginx >= 1.25.0
|
||||
## https://nginx.org/en/docs/quic.html
|
||||
# listen [::]:443 quic reuseport;
|
||||
# listen 443 quic reuseport;
|
||||
# http3 on;
|
||||
|
||||
index index.php;
|
||||
charset utf-8;
|
||||
root /var/www/red;
|
||||
access_log /var/log/nginx/red.log;
|
||||
#Uncomment the following line to include a standard configuration file
|
||||
#Note that the most specific rule wins and your standard configuration
|
||||
#will therefore *add* to this file, but not override it.
|
||||
#include standard.conf
|
||||
# allow uploads up to 20MB in size
|
||||
client_max_body_size 20m;
|
||||
client_body_buffer_size 128k;
|
||||
## Headers for Quic and HTTP3
|
||||
# add_header alt-svc 'h3=":443"; ma=86400' always;
|
||||
|
||||
include mime.types;
|
||||
## SSL Cerver certificat settings
|
||||
ssl_certificate /etc/letsencrypt/live/hub.example.org/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/hub.example.org/privkey.pem;
|
||||
ssl_trusted_certificate /etc/letsencrypt/live/hub.example.org/chain.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
|
||||
# rewrite to front controller as default rule
|
||||
location / {
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^(.*)$ /index.php?q=$1;
|
||||
## Basic folder and files settings
|
||||
root /var/www/hub.example.org;
|
||||
index index.php;
|
||||
|
||||
## How big files are users allowed to upload
|
||||
client_max_body_size 20m;
|
||||
client_body_buffer_size 128k;
|
||||
|
||||
include mime.types;
|
||||
|
||||
location / {
|
||||
try_files $uri /index.php?q=$uri&$args;
|
||||
}
|
||||
}
|
||||
|
||||
# make sure webfinger and other well known services aren't blocked
|
||||
# by denying dot files and rewrite request to the front controller
|
||||
location ^~ /.well-known/ {
|
||||
allow all;
|
||||
if (!-e $request_filename) {
|
||||
rewrite ^(.*)$ /index.php?q=$1;
|
||||
location ^~ /.well-known/ {
|
||||
allow all;
|
||||
try_files $uri /index.php?q=$uri&$args;
|
||||
}
|
||||
}
|
||||
|
||||
# statically serve these file types when possible
|
||||
# otherwise fall back to front controller
|
||||
# allow browser to cache them
|
||||
# added .htm for advanced source code editor library
|
||||
# location ~* \.(jpg|jpeg|gif|png|ico|css|js|htm|html|map|ttf|woff|woff2|svg)$ {
|
||||
# expires 30d;
|
||||
# try_files $uri /index.php?q=$uri&$args;
|
||||
# }
|
||||
location ~* \.(jpg|jpeg|gif|png|ico|css|js|htm|html|map|ttf|woff|woff2|svg)$ {
|
||||
expires max;
|
||||
try_files $uri /index.php?q=$uri&$args;
|
||||
}
|
||||
|
||||
# block these file types
|
||||
location ~* \.(tpl|md|tgz|log|out)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
# or a unix socket
|
||||
location ~* \.php$ {
|
||||
# Zero-day exploit defense.
|
||||
# http://forum.nginx.org/read.php?2,88845,page=3
|
||||
# Won't work properly (404 error) if the file is not stored on this
|
||||
# server, which is entirely possible with php-fpm/php-fcgi.
|
||||
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on
|
||||
# another machine. And then cross your fingers that you won't get hacked.
|
||||
try_files $uri =404;
|
||||
|
||||
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
|
||||
# With php5-cgi alone:
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
|
||||
# With php5-fpm:
|
||||
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||
|
||||
include fastcgi_params;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
|
||||
# deny access to all dot files
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
#deny access to store
|
||||
|
||||
location ~ /store {
|
||||
deny all;
|
||||
}
|
||||
|
||||
#deny access to util
|
||||
location ~ /util {
|
||||
deny all;
|
||||
}
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
fastcgi_pass unix:/var/run/php/php-fpm.sock;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
fastcgi_param HTTPS $https;
|
||||
}
|
||||
|
||||
## block hidden files, extensions, and directories
|
||||
location ~* \.(bak|tpl|md|tgz|log|out)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~* /(?:\.git|store|util)(?:/|$) {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
|
||||
3301
library/cacert.pem
3301
library/cacert.pem
File diff suppressed because it is too large
Load Diff
41
tests/unit/Lib/DbStatsTest.php
Normal file
41
tests/unit/Lib/DbStatsTest.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/* Test cases for DbStats
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Harald Eilertsen <haraldei@anduin.net>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit\Lib;
|
||||
|
||||
use DBA;
|
||||
use Zotlabs\Lib\DbStats;
|
||||
use Zotlabs\Tests\Unit\UnitTestCase;
|
||||
|
||||
class DbStatsTest extends UnitTestCase
|
||||
{
|
||||
public function testGetQueries(): void {
|
||||
$stats = DbStats::getStats();
|
||||
$this->assertNotNull($stats);
|
||||
$this->assertInstanceOf(DbStats::class, $stats);
|
||||
|
||||
$numQueries = $stats->getQueries();
|
||||
$this->assertNotEquals(0, $numQueries);
|
||||
|
||||
if (!DBA::$dba->is_postgres()) {
|
||||
//
|
||||
// Postgres will only update the stats once the transaction
|
||||
// is committed or rolled back. As we wrap the tests in a
|
||||
// transaction to begin with, the stats won't change here,
|
||||
// so we skip this test on Postgres.
|
||||
//
|
||||
dbq("select * from account");
|
||||
dbq("select * from channel");
|
||||
dbq("select * from xchan");
|
||||
|
||||
$numMoreQueries = $stats->getQueries();
|
||||
$this->assertGreaterThan($numQueries, $numMoreQueries);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,17 +35,21 @@ class TestCase extends UnitTestCase {
|
||||
$this->goaway_stub = null;
|
||||
}
|
||||
|
||||
protected function do_request(string $method, string $uri, array $query = [], array $params = []): void {
|
||||
$_GET['q'] = $uri;
|
||||
$_GET = array_merge($_GET, $query);
|
||||
$_POST = $params;
|
||||
protected function do_request(array $args): void {
|
||||
// string $uri, array $query = [], array $params = []): void {
|
||||
$_GET['q'] = $args['uri'];
|
||||
$_GET = array_merge($_GET, $args['query'] ?? []);
|
||||
$_POST = $args['post_params'] ?? [];
|
||||
|
||||
$_SERVER['REQUEST_METHOD'] = $method;
|
||||
$_SERVER['REQUEST_METHOD'] = $args['method'];
|
||||
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
|
||||
$_SERVER['QUERY_STRING'] = "q={$uri}";
|
||||
$_SERVER['REQUEST_URI'] = $uri;
|
||||
$_SERVER['HTTP_CONTENT_TYPE'] = 'text/html';
|
||||
$_SERVER['HTTP_CONTENT_LENGTH'] = 0;
|
||||
$_SERVER['QUERY_STRING'] = "q={$args['uri']}";
|
||||
$_SERVER['REQUEST_URI'] = $args['uri'];
|
||||
$_SERVER['HTTP_CONTENT_TYPE'] = $args['content_type'] ?? 'text/html';
|
||||
$_SERVER['HTTP_CONTENT_LENGTH'] = strlen($args['body'] ?? 0);
|
||||
if (!empty($args['body'])) {
|
||||
$_SERVER['HTTP_POST_BODY'] = $args['body'];
|
||||
}
|
||||
|
||||
// phpcs:disable Generic.PHP.DisallowRequestSuperglobal.Found
|
||||
$_REQUEST = array_merge($_GET, $_POST);
|
||||
@@ -58,6 +62,15 @@ class TestCase extends UnitTestCase {
|
||||
$router->Dispatch();
|
||||
}
|
||||
|
||||
protected function ajax_request(string $method, string $uri, array $params): void {
|
||||
$this->do_request([
|
||||
'method' => $method,
|
||||
'uri' => $uri,
|
||||
'content_type' => 'application/json',
|
||||
'body' => json_encode($params),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate a GET request.
|
||||
*
|
||||
@@ -67,7 +80,11 @@ class TestCase extends UnitTestCase {
|
||||
* as keys.
|
||||
*/
|
||||
protected function get(string $uri, array $query = []): void {
|
||||
$this->do_request('GET', $uri, $query);
|
||||
$this->do_request([
|
||||
'method' => 'GET',
|
||||
'uri' => $uri,
|
||||
'query' => $query
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +98,12 @@ class TestCase extends UnitTestCase {
|
||||
* as keys.
|
||||
*/
|
||||
protected function post(string $uri, array $query = [], array $params = []): void {
|
||||
$this->do_request('POST', $uri, $query, $params);
|
||||
$this->do_request([
|
||||
'method' => 'POST',
|
||||
'uri' => $uri,
|
||||
'query' => $query,
|
||||
'post_params' => $params
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -181,7 +181,7 @@ class UnitTestCase extends TestCase {
|
||||
* directory of the process, which should normally
|
||||
* be the Hubzilla root directory.
|
||||
*/
|
||||
private function loadFixture($file) : void {
|
||||
public function loadFixture($file) : void {
|
||||
$table_name = basename($file, '.yml');
|
||||
$data = yaml_parse_file($file)[$table_name];
|
||||
|
||||
|
||||
@@ -119,4 +119,37 @@ class NetworkTest extends Zotlabs\Tests\Unit\UnitTestCase {
|
||||
{
|
||||
$this->assertEquals('', unparse_url([]));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that the parse_webbie function.
|
||||
*
|
||||
* @dataProvider parse_webbie_provider
|
||||
*/
|
||||
public function test_parse_webbie(string $webbie, array|false $expected) : void {
|
||||
$this->assertEquals($expected, parse_webbie($webbie));
|
||||
}
|
||||
|
||||
public static function parse_webbie_provider() : array {
|
||||
return [
|
||||
// test valid webfinger address
|
||||
['test@example.net', ['host' => 'example.net', 'resource' => urlencode('acct:test@example.net')]],
|
||||
|
||||
// test valid webfinger address with scheme
|
||||
['acct:test@example.net', ['host' => 'example.net', 'resource' => urlencode('acct:test@example.net')]],
|
||||
|
||||
// test address with leading @
|
||||
['@test@example.net', ['host' => 'example.net', 'resource' => urlencode('acct:test@example.net')]],
|
||||
|
||||
// test address with missing user
|
||||
['@example.net', false],
|
||||
|
||||
// test URL
|
||||
['https://example.net/channel/test', ['host' => 'example.net', 'resource' => urlencode('https://example.net/channel/test')]],
|
||||
|
||||
// test unsupported URL
|
||||
['ftp://example.net/channel/test', false],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,27 +8,67 @@
|
||||
|
||||
namespace Zotlabs\Tests\Unit;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Before;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
|
||||
class XChanTest extends UnitTestCase {
|
||||
|
||||
public function testXChanFetchShouldRejectInvalidArgs(): void {
|
||||
$addr = 'example';
|
||||
$guid = Libzot::new_uid($addr);
|
||||
$hash = Libzot::make_xchan_hash($guid, 'dummy-public-key');
|
||||
private string $addr;
|
||||
private string $guid;
|
||||
private string $hash;
|
||||
|
||||
#[Before]
|
||||
public function populateXChans(): void {
|
||||
$this->addr = 'example';
|
||||
$this->guid = Libzot::new_uid($this->addr);
|
||||
$this->hash = Libzot::make_xchan_hash($this->guid, 'dummy-public-key');
|
||||
|
||||
xchan_store_lowlevel([
|
||||
'xchan_hash' => $hash,
|
||||
'xchan_guid' => $guid,
|
||||
'xchan_addr' => $addr,
|
||||
'xchan_hash' => $this->hash,
|
||||
'xchan_guid' => $this->guid,
|
||||
'xchan_addr' => $this->addr,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testXChanFetchReturnsStoredXchan(): void {
|
||||
$byHash = xchan_fetch(['hash' => $this->hash]);
|
||||
$this->assertIsArray($byHash);
|
||||
$this->assertEquals($this->addr, $byHash['address']);
|
||||
$this->assertEquals($this->guid, $byHash['guid']);
|
||||
$this->assertEquals($this->hash, $byHash['hash']);
|
||||
|
||||
$byGuid = xchan_fetch(['guid' => $this->guid]);
|
||||
$this->assertIsArray($byGuid);
|
||||
$this->assertEquals($this->addr, $byGuid['address']);
|
||||
$this->assertEquals($this->guid, $byGuid['guid']);
|
||||
$this->assertEquals($this->hash, $byGuid['hash']);
|
||||
|
||||
$byAddr = xchan_fetch(['address' => $this->addr]);
|
||||
$this->assertIsArray($byAddr);
|
||||
$this->assertEquals($this->addr, $byAddr['address']);
|
||||
$this->assertEquals($this->guid, $byAddr['guid']);
|
||||
$this->assertEquals($this->hash, $byAddr['hash']);
|
||||
}
|
||||
|
||||
public function testXChanFetchShouldRejectInvalidArgs(): void {
|
||||
// Trivial SQL Injection
|
||||
$this->assertFalse(xchan_fetch(['hash' => "{$hash}' or 1=1; -- "]));
|
||||
$this->assertFalse(xchan_fetch(['guid' => "{$guid}' or 1=1; -- "]));
|
||||
$this->assertFalse(xchan_fetch(['address' => "{$addr}' or 1=1; -- "]));
|
||||
$this->assertFalse(xchan_fetch(['hash' => "{$this->hash}' or 1=1; -- "]));
|
||||
$this->assertFalse(xchan_fetch(['guid' => "{$this->guid}' or 1=1; -- "]));
|
||||
$this->assertFalse(xchan_fetch(['address' => "{$this->addr}' or 1=1; -- "]));
|
||||
|
||||
// Not a valid key
|
||||
$this->assertFalse(xchan_fetch(['wrongkey' => $hash]));
|
||||
$this->assertFalse(xchan_fetch(['wrongkey' => $this->hash]));
|
||||
|
||||
// Empty values
|
||||
$this->assertFalse(xchan_fetch(['hash' => '']));
|
||||
$this->assertFalse(xchan_fetch(['guid' => '']));
|
||||
$this->assertFalse(xchan_fetch(['address' => '']));
|
||||
|
||||
// Non existing xchan hash/guid/address
|
||||
$this->assertFalse(xchan_fetch([
|
||||
'hash' => Libzot::make_xchan_hash(Libzot::new_uid('nobody'), 'another-dummy-key')
|
||||
]));
|
||||
$this->assertFalse(xchan_fetch(['guid' => Libzot::new_uid('nobody')]));
|
||||
$this->assertFalse(xchan_fetch(['address' => 'nobody']));
|
||||
}
|
||||
}
|
||||
|
||||
35
tests/unit/includes/ZidTest.php
Normal file
35
tests/unit/includes/ZidTest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 The Hubzilla Community
|
||||
* SPDX-FileContributor: Mario Vavti <mario@mariovavti.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit;
|
||||
|
||||
class ZidTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Test the drop_query_params function.
|
||||
*
|
||||
* @dataProvider drop_query_params_provider
|
||||
*/
|
||||
public function test_drop_query_params(string $url, array $drop_params, string $expected) : void {
|
||||
$this->assertEquals(escape_tags($expected), drop_query_params($url, $drop_params));
|
||||
}
|
||||
|
||||
public static function drop_query_params_provider() : array {
|
||||
return [
|
||||
// Query params with array
|
||||
['https://www.example.net/en/pro/detail/some-detail?tx_news_pi1%5Bday%5D=15&tx_news_pi1%5Bmonth%5D=3&tx_news_pi1%5Byear%5D=2026&cHash=85200a0007de8fecd4cd55199146e19c', ['zid', 'f'], 'https://www.example.net/en/pro/detail/some-detail?tx_news_pi1%5Bday%5D=15&tx_news_pi1%5Bmonth%5D=3&tx_news_pi1%5Byear%5D=2026&cHash=85200a0007de8fecd4cd55199146e19c'],
|
||||
// Query params with zid
|
||||
['https://www.example.net/channel/test?zid=test@example.net', ['zid', 'f'], 'https://www.example.net/channel/test'],
|
||||
// Query params with zid and empty f
|
||||
['https://www.example.net/channel/test?f=&zid=test@example.net', ['zid', 'f'], 'https://www.example.net/channel/test'],
|
||||
// Query params with zid and empty f encoded
|
||||
['https://www.example.net/channel/test?f=&zid=test@example.net', ['zid', 'f'], 'https://www.example.net/channel/test'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ HTML_FILE_EXTENSION = .html
|
||||
HTML_COLORSTYLE = TOGGLE
|
||||
GENERATE_LATEX = NO
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
REFERENCED_BY_RELATION = YES
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,12 +22,12 @@ if [ $ADDONMODE ]
|
||||
then
|
||||
cd "$FULLPATH/../addon/$ADDONNAME"
|
||||
mkdir -p "$FULLPATH/../addon/$ADDONNAME/lang/C"
|
||||
OUTFILE="$FULLPATH/../addon/$ADDONNAME/lang/C/hmessages.po"
|
||||
OUTFILE="$FULLPATH/../addon/$ADDONNAME/lang/C/hmessages.pot"
|
||||
FINDSTARTDIR="."
|
||||
FINDOPTS=
|
||||
else
|
||||
cd "$FULLPATH/../view/lang/en/"
|
||||
OUTFILE="$FULLPATH/hmessages.po"
|
||||
OUTFILE="$FULLPATH/hmessages.pot"
|
||||
FINDSTARTDIR="../../../"
|
||||
# skip addon folder
|
||||
FINDOPTS="( -wholename */store -o -wholename */vendor -o -wholename */extend ) -prune -o"
|
||||
@@ -59,7 +59,7 @@ for f in $(find -L "$FINDSTARTDIR" $FINDOPTS -name "*.php" -type f)
|
||||
do
|
||||
if [ ! -d "$f" ]
|
||||
then
|
||||
xgettext $KEYWORDS $OPTS -j -o "$OUTFILE" --from-code=UTF-8 "$f" > /dev/null 2>&1
|
||||
xgettext $KEYWORDS $OPTS -L PHP -j -o "$OUTFILE" --from-code=UTF-8 "$f" > /dev/null 2>&1
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
113
vendor/brick/math/CHANGELOG.md
vendored
113
vendor/brick/math/CHANGELOG.md
vendored
@@ -2,6 +2,118 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.14.8](https://github.com/brick/math/releases/tag/0.14.8) - 2026-02-10
|
||||
|
||||
🗑️ **Deprecations**
|
||||
|
||||
- Method `BigInteger::testBit()` is deprecated, use `isBitSet()` instead
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- New method: `BigInteger::isBitSet()` (replaces `testBit()`)
|
||||
- New method: `BigNumber::toString()` (alias of magic method `__toString()`)
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- Performance optimization of `BigRational` comparison methods
|
||||
- More exceptions have been documented with `@throws` annotations
|
||||
|
||||
## [0.14.7](https://github.com/brick/math/releases/tag/0.14.7) - 2026-02-07
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `clamp()` is now available on the base `BigNumber` class
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- Improved `@throws` exception documentation
|
||||
|
||||
## [0.14.6](https://github.com/brick/math/releases/tag/0.14.6) - 2026-02-05
|
||||
|
||||
🗑️ **Deprecations**
|
||||
|
||||
- Not passing a `$scale` to `BigDecimal::dividedBy()` is deprecated; **`$scale` will be required in 0.15**
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- `BigRational::toFloat()` never returns `NAN` anymore
|
||||
|
||||
## [0.14.5](https://github.com/brick/math/releases/tag/0.14.5) - 2026-02-03
|
||||
|
||||
🗑️ **Deprecations**
|
||||
|
||||
- Not passing a rounding mode to `BigInteger::sqrt()` and `BigDecimal::sqrt()` triggers a deprecation notice: **the default rounding mode will change from `Down` to `Unnecessary` in 0.15**
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::sqrt()` and `BigDecimal::sqrt()` now support rounding
|
||||
- `abs()` and `negated()` methods are now available on the base `BigNumber` class
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- Alphabet is now checked for duplicate characters in `BigInteger::(from|to)ArbitraryBase()`
|
||||
- `BigNumber::ofNullable()` is now marked as `@pure`
|
||||
|
||||
## [0.14.4](https://github.com/brick/math/releases/tag/0.14.4) - 2026-02-02
|
||||
|
||||
🗑️ **Deprecations**
|
||||
|
||||
- Passing a negative modulus to `BigInteger::mod()` is deprecated to align with Euclidean modulo semantics; it will throw `NegativeNumberException` in 0.15
|
||||
- Method `BigDecimal::stripTrailingZeros()` is deprecated, use `strippedOfTrailingZeros()` instead
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- `BigInteger::modPow()` now accepts negative bases
|
||||
- New method: `BigDecimal::strippedOfTrailingZeros()` (replaces `stripTrailingZeros()`)
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- `clamp()` methods are now marked as `@pure`
|
||||
|
||||
## [0.14.3](https://github.com/brick/math/releases/tag/0.14.3) - 2026-02-01
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- New method: `BigInteger::lcm()`
|
||||
- New method: `BigInteger::lcmAll()`
|
||||
- New method: `BigRational::toRepeatingDecimalString()`
|
||||
|
||||
🐛 **Bug fixes**
|
||||
|
||||
- `BigInteger::gcdAll()` / `gcdMultiple()` could return a negative result when used with a single negative number
|
||||
|
||||
## [0.14.2](https://github.com/brick/math/releases/tag/0.14.2) - 2026-01-30
|
||||
|
||||
🗑️ **Deprecations**
|
||||
|
||||
- **Passing `float` values to `of()` or arithmetic methods is deprecated** and will be removed in 0.15; cast to string explicitly to preserve the previous behaviour (#105)
|
||||
- **Accessing `RoundingMode` enum cases through upper snake case (e.g. `HALF_UP`) is deprecated**, use the pascal case version (e.g. `HalfUp`) instead
|
||||
- Method `BigInteger::gcdMultiple()` is deprecated, use `gcdAll()` instead
|
||||
- Method `BigDecimal::exactlyDividedBy()` is deprecated, use `dividedByExact()` instead
|
||||
- Method `BigDecimal::getIntegralPart()` is deprecated (will be removed in 0.15, and re-introduced as returning `BigInteger` in 0.16)
|
||||
- Method `BigDecimal::getFractionalPart()` is deprecated (will be removed in 0.15, and re-introduced as returning `BigDecimal` with a different meaning in 0.16)
|
||||
- Method `BigRational::nd()` is deprecated, use `ofFraction()` instead
|
||||
- Method `BigRational::quotient()` is deprecated, use `getIntegralPart()` instead
|
||||
- Method `BigRational::remainder()` is deprecated, use `$number->getNumerator()->remainder($number->getDenominator())` instead
|
||||
- Method `BigRational::quotientAndRemainder()` is deprecated, use `$number->getNumerator()->quotientAndRemainder($number->getDenominator())` instead
|
||||
|
||||
✨ **New features**
|
||||
|
||||
- New method: `BigInteger::gcdAll()` (replaces `gcdMultiple()`)
|
||||
- New method: `BigRational::clamp()`
|
||||
- New method: `BigRational::ofFraction()` (replaces `nd()`)
|
||||
- New method: `BigRational::getIntegralPart()` (replaces `quotient()`)
|
||||
- New method: `BigRational::getFractionalPart()`
|
||||
|
||||
👌 **Improvements**
|
||||
|
||||
- `BigInteger::modInverse()` now accepts `BigNumber|int|float|string` instead of just `BigInteger`
|
||||
- `BigInteger::gcdMultiple()` now accepts `BigNumber|int|float|string` instead of just `BigInteger`
|
||||
|
||||
🐛 **Bug fixes**
|
||||
|
||||
- `BigInteger::clamp()` and `BigDecimal::clamp()` now throw an exception on inverted bounds, instead of returning an incorrect result
|
||||
|
||||
## [0.14.1](https://github.com/brick/math/releases/tag/0.14.1) - 2025-11-24
|
||||
|
||||
✨ **New features**
|
||||
@@ -520,4 +632,3 @@ Added `BigDecimal::divideAndRemainder()`
|
||||
## [0.1.0](https://github.com/brick/math/releases/tag/0.1.0) - 2014-08-31
|
||||
|
||||
First beta release.
|
||||
|
||||
|
||||
14
vendor/brick/math/phpstan.neon
vendored
14
vendor/brick/math/phpstan.neon
vendored
@@ -1,14 +0,0 @@
|
||||
parameters:
|
||||
level: 10
|
||||
checkUninitializedProperties: true
|
||||
paths:
|
||||
- src
|
||||
ignoreErrors:
|
||||
- '~Impure call to function array_shift\(\) in pure method~'
|
||||
- '~Possibly impure call to function assert\(\) in pure method~'
|
||||
- '~Possibly impure call to function hex2bin\(\) in pure method~'
|
||||
- '~Possibly impure call to function preg_match\(\) in pure method~'
|
||||
- '~Impure static variable in pure method Brick\\Math\\Big(Integer|Decimal|Rational)::(zero|one|ten)\(\)~'
|
||||
-
|
||||
message: '~Parameter #\d \$\S+ of function bc\S+ expects numeric-string, string given~'
|
||||
path: src/Internal/Calculator/BcMathCalculator.php
|
||||
273
vendor/brick/math/src/BigDecimal.php
vendored
273
vendor/brick/math/src/BigDecimal.php
vendored
@@ -7,23 +7,34 @@ namespace Brick\Math;
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NegativeNumberException;
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
use Brick\Math\Internal\Calculator;
|
||||
use Brick\Math\Internal\CalculatorRegistry;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use Override;
|
||||
|
||||
use function func_num_args;
|
||||
use function in_array;
|
||||
use function intdiv;
|
||||
use function max;
|
||||
use function rtrim;
|
||||
use function sprintf;
|
||||
use function str_pad;
|
||||
use function str_repeat;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use function trigger_error;
|
||||
|
||||
use const E_USER_DEPRECATED;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
/**
|
||||
* Immutable, arbitrary-precision signed decimal numbers.
|
||||
* An arbitrarily large decimal number.
|
||||
*
|
||||
* This class is immutable.
|
||||
*
|
||||
* The scale of the number is the number of digits after the decimal point. It is always positive or zero.
|
||||
*/
|
||||
final readonly class BigDecimal extends BigNumber
|
||||
{
|
||||
@@ -62,15 +73,21 @@ final readonly class BigDecimal extends BigNumber
|
||||
*
|
||||
* Example: `(12345, 3)` will result in the BigDecimal `12.345`.
|
||||
*
|
||||
* A negative scale is normalized to zero by appending zeros to the unscaled value.
|
||||
*
|
||||
* Example: `(12345, -3)` will result in the BigDecimal `12345000`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger.
|
||||
* @param int $scale The scale of the number. If negative, the scale will be set to zero
|
||||
* and the unscaled value will be adjusted accordingly.
|
||||
*
|
||||
* @throws MathException If the value is not valid, or is not convertible to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public static function ofUnscaledValue(BigNumber|int|float|string $value, int $scale = 0): BigDecimal
|
||||
{
|
||||
$value = (string) BigInteger::of($value);
|
||||
$value = BigInteger::of($value)->toString();
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($value !== '0') {
|
||||
@@ -159,7 +176,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$value = CalculatorRegistry::get()->add($a, $b);
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
$scale = max($this->scale, $that->scale);
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
@@ -186,7 +203,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$value = CalculatorRegistry::get()->sub($a, $b);
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
$scale = max($this->scale, $that->scale);
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
@@ -198,7 +215,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
|
||||
* @throws MathException If the multiplier is not valid, or is not convertible to a BigDecimal.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -223,16 +240,19 @@ final readonly class BigDecimal extends BigNumber
|
||||
/**
|
||||
* Returns the result of the division of this number by the given one, at the given scale.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor.
|
||||
* @param int|null $scale The desired scale, or null to use the scale of this number.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
* @param int|null $scale The desired scale. Omitting this parameter is deprecated; it will be required in 0.15.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary.
|
||||
*
|
||||
* @throws InvalidArgumentException If the scale or rounding mode is invalid.
|
||||
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
|
||||
* @throws InvalidArgumentException If the scale is negative.
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
* @throws RoundingNecessaryException If RoundingMode::Unnecessary is used and the result cannot be represented
|
||||
* exactly at the given scale.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
|
||||
public function dividedBy(BigNumber|int|float|string $that, ?int $scale = null, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
@@ -241,9 +261,15 @@ final readonly class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
if ($scale === null) {
|
||||
// @phpstan-ignore-next-line
|
||||
trigger_error(
|
||||
'Not passing a $scale to BigDecimal::dividedBy() is deprecated. ' .
|
||||
'Use $a->dividedBy($b, $a->getScale(), $roundingMode) to retain current behavior.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
$scale = $this->scale;
|
||||
} elseif ($scale < 0) {
|
||||
throw new InvalidArgumentException('Scale cannot be negative.');
|
||||
throw new InvalidArgumentException('Scale must not be negative.');
|
||||
}
|
||||
|
||||
if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) {
|
||||
@@ -263,14 +289,37 @@ final readonly class BigDecimal extends BigNumber
|
||||
*
|
||||
* The scale of the result is automatically calculated to fit all the fraction digits.
|
||||
*
|
||||
* @deprecated Will be removed in 0.15. Use dividedByExact() instead.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
|
||||
* or the result yields an infinite number of digits.
|
||||
*/
|
||||
public function exactlyDividedBy(BigNumber|int|float|string $that): BigDecimal
|
||||
{
|
||||
trigger_error(
|
||||
'BigDecimal::exactlyDividedBy() is deprecated and will be removed in 0.15. Use dividedByExact() instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return $this->dividedByExact($that);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exact result of the division of this number by the given one.
|
||||
*
|
||||
* The scale of the result is automatically calculated to fit all the fraction digits.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
* @throws RoundingNecessaryException If the result yields an infinite number of digits.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function exactlyDividedBy(BigNumber|int|float|string $that): BigDecimal
|
||||
public function dividedByExact(BigNumber|int|float|string $that): BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
@@ -298,30 +347,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dividedBy($that, $scale)->stripTrailingZeros();
|
||||
}
|
||||
|
||||
/**
|
||||
* Limits (clamps) this number between the given minimum and maximum values.
|
||||
*
|
||||
* If the number is lower than $min, returns a copy of $min.
|
||||
* If the number is greater than $max, returns a copy of $max.
|
||||
* Otherwise, returns this number unchanged.
|
||||
*
|
||||
* @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigDecimal.
|
||||
* @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If min/max are not convertible to a BigDecimal.
|
||||
*/
|
||||
public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max): BigDecimal
|
||||
{
|
||||
if ($this->isLessThan($min)) {
|
||||
return BigDecimal::of($min);
|
||||
} elseif ($this->isGreaterThan($max)) {
|
||||
return BigDecimal::of($max);
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $this->dividedBy($that, $scale)->strippedOfTrailingZeros();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,9 +385,17 @@ final readonly class BigDecimal extends BigNumber
|
||||
*
|
||||
* The quotient has a scale of `0`.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7.5` quotient `3` returns `2`
|
||||
* - `7.5` quotient `-3` returns `-2`
|
||||
* - `-7.5` quotient `3` returns `-2`
|
||||
* - `-7.5` quotient `-3` returns `2`
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -385,10 +419,19 @@ final readonly class BigDecimal extends BigNumber
|
||||
* Returns the remainder of the division of this number by the given one.
|
||||
*
|
||||
* The remainder has a scale of `max($this->scale, $that->scale)`.
|
||||
* The remainder, when non-zero, has the same sign as the dividend.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7.5` remainder `3` returns `1.5`
|
||||
* - `7.5` remainder `-3` returns `1.5`
|
||||
* - `-7.5` remainder `3` returns `-1.5`
|
||||
* - `-7.5` remainder `-3` returns `-1.5`
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -405,7 +448,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
|
||||
$remainder = CalculatorRegistry::get()->divR($p, $q);
|
||||
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
$scale = max($this->scale, $that->scale);
|
||||
|
||||
return new BigDecimal($remainder, $scale);
|
||||
}
|
||||
@@ -415,11 +458,19 @@ final readonly class BigDecimal extends BigNumber
|
||||
*
|
||||
* The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7.5` quotientAndRemainder `3` returns [`2`, `1.5`]
|
||||
* - `7.5` quotientAndRemainder `-3` returns [`-2`, `1.5`]
|
||||
* - `-7.5` quotientAndRemainder `3` returns [`-2`, `-1.5`]
|
||||
* - `-7.5` quotientAndRemainder `-3` returns [`2`, `-1.5`]
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return array{BigDecimal, BigDecimal} An array containing the quotient and the remainder.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigDecimal.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -436,7 +487,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
|
||||
[$quotient, $remainder] = CalculatorRegistry::get()->divQR($p, $q);
|
||||
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
$scale = max($this->scale, $that->scale);
|
||||
|
||||
$quotient = new BigDecimal($quotient, 0);
|
||||
$remainder = new BigDecimal($remainder, $scale);
|
||||
@@ -445,17 +496,34 @@ final readonly class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of this number, rounded down to the given number of decimals.
|
||||
* Returns the square root of this number, rounded to the given scale according to the given rounding mode.
|
||||
*
|
||||
* @throws InvalidArgumentException If the scale is negative.
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
* @param int $scale The target scale. Must be non-negative.
|
||||
* @param RoundingMode $roundingMode The rounding mode to use, defaults to Down.
|
||||
* ⚠️ WARNING: the default rounding mode was kept as Down for backward
|
||||
* compatibility, but will change to Unnecessary in version 0.15. Pass a rounding
|
||||
* mode explicitly to avoid this upcoming breaking change.
|
||||
*
|
||||
* @throws InvalidArgumentException If the scale is negative.
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
* @throws RoundingNecessaryException If RoundingMode::Unnecessary is used and the result cannot be represented
|
||||
* exactly at the given scale.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function sqrt(int $scale): BigDecimal
|
||||
public function sqrt(int $scale, RoundingMode $roundingMode = RoundingMode::Down): BigDecimal
|
||||
{
|
||||
if (func_num_args() === 1) {
|
||||
// @phpstan-ignore-next-line
|
||||
trigger_error(
|
||||
'The default rounding mode of BigDecimal::sqrt() will change from Down to Unnecessary in version 0.15. ' .
|
||||
'Pass a rounding mode explicitly to avoid this breaking change.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
}
|
||||
|
||||
if ($scale < 0) {
|
||||
throw new InvalidArgumentException('Scale cannot be negative.');
|
||||
throw new InvalidArgumentException('Scale must not be negative.');
|
||||
}
|
||||
|
||||
if ($this->value === '0') {
|
||||
@@ -467,28 +535,44 @@ final readonly class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
$value = $this->value;
|
||||
$addDigits = 2 * $scale - $this->scale;
|
||||
$inputScale = $this->scale;
|
||||
|
||||
if ($addDigits > 0) {
|
||||
// add zeros
|
||||
$value .= str_repeat('0', $addDigits);
|
||||
} elseif ($addDigits < 0) {
|
||||
// trim digits
|
||||
if (-$addDigits >= strlen($this->value)) {
|
||||
// requesting a scale too low, will always yield a zero result
|
||||
return new BigDecimal('0', $scale);
|
||||
}
|
||||
|
||||
$value = substr($value, 0, $addDigits);
|
||||
if ($inputScale % 2 !== 0) {
|
||||
$value .= '0';
|
||||
$inputScale++;
|
||||
}
|
||||
|
||||
$value = CalculatorRegistry::get()->sqrt($value);
|
||||
$calculator = CalculatorRegistry::get();
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
// Keep one extra digit for rounding.
|
||||
$intermediateScale = max($scale, intdiv($inputScale, 2)) + 1;
|
||||
$value .= str_repeat('0', 2 * $intermediateScale - $inputScale);
|
||||
|
||||
$sqrt = $calculator->sqrt($value);
|
||||
$isExact = $calculator->mul($sqrt, $sqrt) === $value;
|
||||
|
||||
if (! $isExact) {
|
||||
if ($roundingMode === RoundingMode::Unnecessary) {
|
||||
throw RoundingNecessaryException::roundingNecessary();
|
||||
}
|
||||
|
||||
// Non-perfect-square sqrt is irrational, so the true value is strictly above this sqrt floor.
|
||||
// Add one at the intermediate scale to guarantee Up/Ceiling round up at the target scale.
|
||||
if (in_array($roundingMode, [RoundingMode::Up, RoundingMode::Ceiling], true)) {
|
||||
$sqrt = $calculator->add($sqrt, '1');
|
||||
}
|
||||
|
||||
// Irrational sqrt cannot land exactly on a midpoint; treat tie-to-down modes as HalfUp.
|
||||
elseif (in_array($roundingMode, [RoundingMode::HalfDown, RoundingMode::HalfEven, RoundingMode::HalfFloor], true)) {
|
||||
$roundingMode = RoundingMode::HalfUp;
|
||||
}
|
||||
}
|
||||
|
||||
return (new BigDecimal($sqrt, $intermediateScale))->toScale($scale, $roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
|
||||
* Returns a copy of this BigDecimal with the decimal point moved to the left by the given number of places.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -506,7 +590,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
|
||||
* Returns a copy of this BigDecimal with the decimal point moved to the right by the given number of places.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -536,9 +620,24 @@ final readonly class BigDecimal extends BigNumber
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
|
||||
*
|
||||
* @pure
|
||||
* @deprecated Use strippedOfTrailingZeros() instead.
|
||||
*/
|
||||
public function stripTrailingZeros(): BigDecimal
|
||||
{
|
||||
trigger_error(
|
||||
'BigDecimal::stripTrailingZeros() is deprecated, use strippedOfTrailingZeros() instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return $this->strippedOfTrailingZeros();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function strippedOfTrailingZeros(): BigDecimal
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return $this;
|
||||
@@ -566,22 +665,8 @@ final readonly class BigDecimal extends BigNumber
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this number.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function abs(): BigDecimal
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this number.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function negated(): BigDecimal
|
||||
#[Override]
|
||||
public function negated(): static
|
||||
{
|
||||
return new BigDecimal(CalculatorRegistry::get()->neg($this->value), $this->scale);
|
||||
}
|
||||
@@ -660,10 +745,15 @@ final readonly class BigDecimal extends BigNumber
|
||||
*
|
||||
* Example: `-123.456` => `-123`.
|
||||
*
|
||||
* @pure
|
||||
* @deprecated Will be removed in 0.15 and re-introduced as returning BigInteger in 0.16.
|
||||
*/
|
||||
public function getIntegralPart(): string
|
||||
{
|
||||
trigger_error(
|
||||
'BigDecimal::getIntegralPart() is deprecated and will be removed in 0.15. It will be re-introduced as returning BigInteger in 0.16.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
if ($this->scale === 0) {
|
||||
return $this->value;
|
||||
}
|
||||
@@ -680,10 +770,15 @@ final readonly class BigDecimal extends BigNumber
|
||||
*
|
||||
* Examples: `-123.456` => '456', `123` => ''.
|
||||
*
|
||||
* @pure
|
||||
* @deprecated Will be removed in 0.15 and re-introduced as returning BigDecimal with a different meaning in 0.16.
|
||||
*/
|
||||
public function getFractionalPart(): string
|
||||
{
|
||||
trigger_error(
|
||||
'BigDecimal::getFractionalPart() is deprecated and will be removed in 0.15. It will be re-introduced as returning BigDecimal with a different meaning in 0.16.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
if ($this->scale === 0) {
|
||||
return '';
|
||||
}
|
||||
@@ -700,7 +795,13 @@ final readonly class BigDecimal extends BigNumber
|
||||
*/
|
||||
public function hasNonZeroFractionalPart(): bool
|
||||
{
|
||||
return $this->getFractionalPart() !== str_repeat('0', $this->scale);
|
||||
if ($this->scale === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||
|
||||
return substr($value, -$this->scale) !== str_repeat('0', $this->scale);
|
||||
}
|
||||
|
||||
#[Override]
|
||||
@@ -727,7 +828,7 @@ final readonly class BigDecimal extends BigNumber
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal
|
||||
{
|
||||
if ($scale === $this->scale) {
|
||||
return $this;
|
||||
@@ -745,14 +846,14 @@ final readonly class BigDecimal extends BigNumber
|
||||
#[Override]
|
||||
public function toFloat(): float
|
||||
{
|
||||
return (float) (string) $this;
|
||||
return (float) $this->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return numeric-string
|
||||
*/
|
||||
#[Override]
|
||||
public function __toString(): string
|
||||
public function toString(): string
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
/** @var numeric-string */
|
||||
|
||||
352
vendor/brick/math/src/BigInteger.php
vendored
352
vendor/brick/math/src/BigInteger.php
vendored
@@ -9,6 +9,7 @@ use Brick\Math\Exception\IntegerOverflowException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NegativeNumberException;
|
||||
use Brick\Math\Exception\NumberFormatException;
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
use Brick\Math\Internal\Calculator;
|
||||
use Brick\Math\Internal\CalculatorRegistry;
|
||||
use InvalidArgumentException;
|
||||
@@ -18,7 +19,9 @@ use Override;
|
||||
use function assert;
|
||||
use function bin2hex;
|
||||
use function chr;
|
||||
use function count_chars;
|
||||
use function filter_var;
|
||||
use function func_num_args;
|
||||
use function hex2bin;
|
||||
use function in_array;
|
||||
use function intdiv;
|
||||
@@ -32,14 +35,15 @@ use function str_repeat;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
use function trigger_error;
|
||||
|
||||
use const E_USER_DEPRECATED;
|
||||
use const FILTER_VALIDATE_INT;
|
||||
|
||||
/**
|
||||
* An arbitrary-size integer.
|
||||
* An arbitrarily large integer number.
|
||||
*
|
||||
* All methods accepting a number as a parameter accept either a BigInteger instance,
|
||||
* an integer, or a string representing an arbitrary size integer.
|
||||
* This class is immutable.
|
||||
*/
|
||||
final readonly class BigInteger extends BigNumber
|
||||
{
|
||||
@@ -85,7 +89,7 @@ final readonly class BigInteger extends BigNumber
|
||||
public static function fromBase(string $number, int $base): BigInteger
|
||||
{
|
||||
if ($number === '') {
|
||||
throw new NumberFormatException('The number cannot be empty.');
|
||||
throw new NumberFormatException('The number must not be empty.');
|
||||
}
|
||||
|
||||
if ($base < 2 || $base > 36) {
|
||||
@@ -103,7 +107,7 @@ final readonly class BigInteger extends BigNumber
|
||||
}
|
||||
|
||||
if ($number === '') {
|
||||
throw new NumberFormatException('The number cannot be empty.');
|
||||
throw new NumberFormatException('The number must not be empty.');
|
||||
}
|
||||
|
||||
$number = ltrim($number, '0');
|
||||
@@ -137,20 +141,23 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Parses a string containing an integer in an arbitrary base, using a custom alphabet.
|
||||
*
|
||||
* Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers.
|
||||
* This method is byte-oriented: the alphabet is interpreted as a sequence of single-byte characters.
|
||||
* Multibyte UTF-8 characters are not supported.
|
||||
*
|
||||
* Because this method accepts any single-byte character, including dash, it does not handle negative numbers.
|
||||
*
|
||||
* @param string $number The number to parse.
|
||||
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
||||
*
|
||||
* @throws NumberFormatException If the given number is empty or contains invalid chars for the given alphabet.
|
||||
* @throws InvalidArgumentException If the alphabet does not contain at least 2 chars.
|
||||
* @throws InvalidArgumentException If the alphabet does not contain at least 2 chars, or contains duplicates.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public static function fromArbitraryBase(string $number, string $alphabet): BigInteger
|
||||
{
|
||||
if ($number === '') {
|
||||
throw new NumberFormatException('The number cannot be empty.');
|
||||
throw new NumberFormatException('The number must not be empty.');
|
||||
}
|
||||
|
||||
$base = strlen($alphabet);
|
||||
@@ -159,6 +166,10 @@ final readonly class BigInteger extends BigNumber
|
||||
throw new InvalidArgumentException('The alphabet must contain at least 2 chars.');
|
||||
}
|
||||
|
||||
if (strlen(count_chars($alphabet, 3)) !== $base) {
|
||||
throw new InvalidArgumentException('The alphabet must not contain duplicate chars.');
|
||||
}
|
||||
|
||||
$pattern = '/[^' . preg_quote($alphabet, '/') . ']/';
|
||||
|
||||
if (preg_match($pattern, $number, $matches) === 1) {
|
||||
@@ -229,7 +240,7 @@ final readonly class BigInteger extends BigNumber
|
||||
public static function randomBits(int $numBits, ?callable $randomBytesGenerator = null): BigInteger
|
||||
{
|
||||
if ($numBits < 0) {
|
||||
throw new InvalidArgumentException('The number of bits cannot be negative.');
|
||||
throw new InvalidArgumentException('The number of bits must not be negative.');
|
||||
}
|
||||
|
||||
if ($numBits === 0) {
|
||||
@@ -253,7 +264,7 @@ final readonly class BigInteger extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a pseudo-random number between `$min` and `$max`.
|
||||
* Generates a pseudo-random number between `$min` and `$max`, inclusive.
|
||||
*
|
||||
* Using the default random bytes generator, this method is suitable for cryptographic use.
|
||||
*
|
||||
@@ -275,7 +286,7 @@ final readonly class BigInteger extends BigNumber
|
||||
$max = BigInteger::of($max);
|
||||
|
||||
if ($min->isGreaterThan($max)) {
|
||||
throw new MathException('$min cannot be greater than $max.');
|
||||
throw new MathException('$min must be less than or equal to $max.');
|
||||
}
|
||||
|
||||
if ($min->isEqualTo($max)) {
|
||||
@@ -345,14 +356,23 @@ final readonly class BigInteger extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the greatest common divisor of the given numbers.
|
||||
*
|
||||
* The GCD is always positive, unless all numbers are zero, in which case it is zero.
|
||||
*
|
||||
* @param BigNumber|int|float|string $a The first number. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string ...$n The additional numbers. Each number must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If one of the parameters cannot be converted to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public static function gcdMultiple(BigInteger $a, BigInteger ...$n): BigInteger
|
||||
public static function gcdAll(BigNumber|int|float|string $a, BigNumber|int|float|string ...$n): BigInteger
|
||||
{
|
||||
$result = $a;
|
||||
$result = BigInteger::of($a)->abs();
|
||||
|
||||
foreach ($n as $next) {
|
||||
$result = $result->gcd($next);
|
||||
$result = $result->gcd(BigInteger::of($next));
|
||||
|
||||
if ($result->isEqualTo(1)) {
|
||||
return $result;
|
||||
@@ -362,6 +382,49 @@ final readonly class BigInteger extends BigNumber
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the least common multiple of the given numbers.
|
||||
*
|
||||
* The LCM is always positive, unless one of the numbers is zero, in which case it is zero.
|
||||
*
|
||||
* @param BigNumber|int|float|string $a The first number. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string ...$n The additional numbers. Each number must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If one of the parameters cannot be converted to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public static function lcmAll(BigNumber|int|float|string $a, BigNumber|int|float|string ...$n): BigInteger
|
||||
{
|
||||
$result = BigInteger::of($a)->abs();
|
||||
|
||||
foreach ($n as $next) {
|
||||
$result = $result->lcm(BigInteger::of($next));
|
||||
|
||||
if ($result->isZero()) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use gcdAll() instead.
|
||||
*
|
||||
* @param BigNumber|int|float|string $a The first number. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string ...$n The subsequent numbers. Must be convertible to BigInteger.
|
||||
*/
|
||||
public static function gcdMultiple(BigNumber|int|float|string $a, BigNumber|int|float|string ...$n): BigInteger
|
||||
{
|
||||
trigger_error(
|
||||
'BigInteger::gcdMultiple() is deprecated and will be removed in version 0.15. Use gcdAll() instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return self::gcdAll($a, ...$n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of this number and the given one.
|
||||
*
|
||||
@@ -415,7 +478,7 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigInteger.
|
||||
* @throws MathException If the multiplier is not valid, or is not convertible to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -440,14 +503,15 @@ final readonly class BigInteger extends BigNumber
|
||||
* Returns the result of the division of this number by the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigInteger, is zero,
|
||||
* or RoundingMode::UNNECESSARY is used and the remainder is not zero.
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigInteger.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
* @throws RoundingNecessaryException If RoundingMode::Unnecessary is used and the remainder is not zero.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigInteger
|
||||
public function dividedBy(BigNumber|int|float|string $that, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigInteger
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
@@ -464,29 +528,6 @@ final readonly class BigInteger extends BigNumber
|
||||
return new BigInteger($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limits (clamps) this number between the given minimum and maximum values.
|
||||
*
|
||||
* If the number is lower than $min, returns a copy of $min.
|
||||
* If the number is greater than $max, returns a copy of $max.
|
||||
* Otherwise, returns this number unchanged.
|
||||
*
|
||||
* @param BigNumber|int|float|string $min The minimum. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string $max The maximum. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If min/max are not convertible to a BigInteger.
|
||||
*/
|
||||
public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max): BigInteger
|
||||
{
|
||||
if ($this->isLessThan($min)) {
|
||||
return BigInteger::of($min);
|
||||
} elseif ($this->isGreaterThan($max)) {
|
||||
return BigInteger::of($max);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this number exponentiated to the given value.
|
||||
*
|
||||
@@ -518,8 +559,16 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Returns the quotient of the division of this number by the given one.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7` quotient `3` returns `2`
|
||||
* - `7` quotient `-3` returns `-2`
|
||||
* - `-7` quotient `3` returns `-2`
|
||||
* - `-7` quotient `-3` returns `2`
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigInteger.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
@@ -546,8 +595,16 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* The remainder, when non-zero, has the same sign as the dividend.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7` remainder `3` returns `1`
|
||||
* - `7` remainder `-3` returns `1`
|
||||
* - `-7` remainder `3` returns `-1`
|
||||
* - `-7` remainder `-3` returns `-1`
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigInteger.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
@@ -572,10 +629,18 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of this number by the given one.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7` quotientAndRemainder `3` returns [`2`, `1`]
|
||||
* - `7` quotientAndRemainder `-3` returns [`-2`, `1`]
|
||||
* - `-7` quotientAndRemainder `3` returns [`-2`, `-1`]
|
||||
* - `-7` quotientAndRemainder `-3` returns [`2`, `-1`]
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return array{BigInteger, BigInteger} An array containing the quotient and the remainder.
|
||||
*
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigInteger.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
@@ -606,6 +671,7 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the divisor is not valid, or is not convertible to a BigInteger.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
@@ -614,10 +680,18 @@ final readonly class BigInteger extends BigNumber
|
||||
{
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::modulusMustNotBeZero();
|
||||
}
|
||||
|
||||
if ($that->isNegative()) {
|
||||
// @phpstan-ignore-next-line
|
||||
trigger_error(
|
||||
'Passing a negative modulus to BigInteger::mod() is deprecated and will throw a NegativeNumberException in 0.15.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
}
|
||||
|
||||
$value = CalculatorRegistry::get()->mod($this->value, $that->value);
|
||||
|
||||
return new BigInteger($value);
|
||||
@@ -626,6 +700,9 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Returns the modular multiplicative inverse of this BigInteger modulo $m.
|
||||
*
|
||||
* @param BigNumber|int|float|string $m The modulus. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the modulus is not valid, or is not convertible to a BigInteger.
|
||||
* @throws DivisionByZeroException If $m is zero.
|
||||
* @throws NegativeNumberException If $m is negative.
|
||||
* @throws MathException If this BigInteger has no multiplicative inverse mod m (that is, this BigInteger
|
||||
@@ -633,8 +710,10 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function modInverse(BigInteger $m): BigInteger
|
||||
public function modInverse(BigNumber|int|float|string $m): BigInteger
|
||||
{
|
||||
$m = BigInteger::of($m);
|
||||
|
||||
if ($m->value === '0') {
|
||||
throw DivisionByZeroException::modulusMustNotBeZero();
|
||||
}
|
||||
@@ -659,12 +738,13 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Returns this number raised into power with modulo.
|
||||
*
|
||||
* This operation only works on positive numbers.
|
||||
* This operation requires a non-negative exponent and a strictly positive modulus.
|
||||
*
|
||||
* @param BigNumber|int|float|string $exp The exponent. Must be positive or zero.
|
||||
* @param BigNumber|int|float|string $mod The modulus. Must be strictly positive.
|
||||
* @param BigNumber|int|float|string $exp The exponent. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string $mod The modulus. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws NegativeNumberException If any of the operands is negative.
|
||||
* @throws MathException If the exponent or modulus is not valid, or is not convertible to a BigInteger.
|
||||
* @throws NegativeNumberException If the exponent or modulus is negative.
|
||||
* @throws DivisionByZeroException If the modulus is zero.
|
||||
*
|
||||
* @pure
|
||||
@@ -674,8 +754,12 @@ final readonly class BigInteger extends BigNumber
|
||||
$exp = BigInteger::of($exp);
|
||||
$mod = BigInteger::of($mod);
|
||||
|
||||
if ($this->isNegative() || $exp->isNegative() || $mod->isNegative()) {
|
||||
throw new NegativeNumberException('The operands cannot be negative.');
|
||||
if ($exp->isNegative()) {
|
||||
throw new NegativeNumberException('The exponent cannot be negative.');
|
||||
}
|
||||
|
||||
if ($mod->isNegative()) {
|
||||
throw new NegativeNumberException('The modulus cannot be negative.');
|
||||
}
|
||||
|
||||
if ($mod->isZero()) {
|
||||
@@ -692,7 +776,9 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* The GCD is always positive, unless both operands are zero, in which case it is zero.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the operand is not valid, or is not convertible to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -714,41 +800,107 @@ final readonly class BigInteger extends BigNumber
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer square root number of this number, rounded down.
|
||||
* Returns the least common multiple of this number and the given one.
|
||||
*
|
||||
* The result is the largest x such that x² ≤ n.
|
||||
* The LCM is always positive, unless at least one operand is zero, in which case it is zero.
|
||||
*
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the operand is not valid, or is not convertible to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function sqrt(): BigInteger
|
||||
public function lcm(BigNumber|int|float|string $that): BigInteger
|
||||
{
|
||||
if ($this->value[0] === '-') {
|
||||
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
|
||||
$that = BigInteger::of($that);
|
||||
|
||||
if ($this->isZero() || $that->isZero()) {
|
||||
return BigInteger::zero();
|
||||
}
|
||||
|
||||
$value = CalculatorRegistry::get()->sqrt($this->value);
|
||||
$value = CalculatorRegistry::get()->lcm($this->value, $that->value);
|
||||
|
||||
return new BigInteger($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this number.
|
||||
* Returns the integer square root of this number, rounded according to the given rounding mode.
|
||||
*
|
||||
* @param RoundingMode $roundingMode The rounding mode to use, defaults to Down.
|
||||
* ⚠️ WARNING: the default rounding mode was kept as Down for backward
|
||||
* compatibility, but will change to Unnecessary in version 0.15. Pass a rounding
|
||||
* mode explicitly to avoid this upcoming breaking change.
|
||||
*
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
* @throws RoundingNecessaryException If RoundingMode::Unnecessary is used, and the number is not a perfect square.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function abs(): BigInteger
|
||||
public function sqrt(RoundingMode $roundingMode = RoundingMode::Down): BigInteger
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
if (func_num_args() === 0) {
|
||||
// @phpstan-ignore-next-line
|
||||
trigger_error(
|
||||
'The default rounding mode of BigInteger::sqrt() will change from Down to Unnecessary in version 0.15. ' .
|
||||
'Pass a rounding mode explicitly to avoid this breaking change.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->value[0] === '-') {
|
||||
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
|
||||
}
|
||||
|
||||
$calculator = CalculatorRegistry::get();
|
||||
|
||||
$sqrt = $calculator->sqrt($this->value);
|
||||
|
||||
// For Down and Floor (equivalent for non-negative numbers), return floor sqrt
|
||||
if ($roundingMode === RoundingMode::Down || $roundingMode === RoundingMode::Floor) {
|
||||
return new BigInteger($sqrt);
|
||||
}
|
||||
|
||||
// Check if the sqrt is exact
|
||||
$s2 = $calculator->mul($sqrt, $sqrt);
|
||||
$remainder = $calculator->sub($this->value, $s2);
|
||||
|
||||
if ($remainder === '0') {
|
||||
// sqrt is exact
|
||||
return new BigInteger($sqrt);
|
||||
}
|
||||
|
||||
// sqrt is not exact
|
||||
if ($roundingMode === RoundingMode::Unnecessary) {
|
||||
throw RoundingNecessaryException::roundingNecessary();
|
||||
}
|
||||
|
||||
// For Up and Ceiling (equivalent for non-negative numbers), round up
|
||||
if ($roundingMode === RoundingMode::Up || $roundingMode === RoundingMode::Ceiling) {
|
||||
return new BigInteger($calculator->add($sqrt, '1'));
|
||||
}
|
||||
|
||||
// For Half* modes, compare our number to the midpoint of the interval [s², (s+1)²[.
|
||||
// The midpoint is s² + s + 0.5. Comparing n >= s² + s + 0.5 with remainder = n − s²
|
||||
// is equivalent to comparing 2*remainder >= 2*s + 1.
|
||||
$twoRemainder = $calculator->mul($remainder, '2');
|
||||
$threshold = $calculator->add($calculator->mul($sqrt, '2'), '1');
|
||||
$cmp = $calculator->cmp($twoRemainder, $threshold);
|
||||
|
||||
// We're supposed to increment (round up) when:
|
||||
// - HalfUp, HalfCeiling => $cmp >= 0
|
||||
// - HalfDown, HalfFloor => $cmp > 0
|
||||
// - HalfEven => $cmp > 0 || ($cmp === 0 && $sqrt % 2 === 1)
|
||||
// But 2*remainder is always even and 2*s + 1 is always odd, so $cmp is never zero.
|
||||
// Therefore, all Half* modes simplify to:
|
||||
if ($cmp > 0) {
|
||||
$sqrt = $calculator->add($sqrt, '1');
|
||||
}
|
||||
|
||||
return new BigInteger($sqrt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inverse of this number.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function negated(): BigInteger
|
||||
#[Override]
|
||||
public function negated(): static
|
||||
{
|
||||
return new BigInteger(CalculatorRegistry::get()->neg($this->value));
|
||||
}
|
||||
@@ -758,7 +910,9 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* This method returns a negative BigInteger if and only if both operands are negative.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the operand is not valid, or is not convertible to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -774,7 +928,9 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* This method returns a negative BigInteger if and only if either of the operands is negative.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the operand is not valid, or is not convertible to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -790,7 +946,9 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* This method returns a negative BigInteger if and only if exactly one of the operands is negative.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to an integer number.
|
||||
* @param BigNumber|int|float|string $that The operand. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If the operand is not valid, or is not convertible to a BigInteger.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -814,6 +972,8 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Returns the integer left shifted by a given number of bits.
|
||||
*
|
||||
* @throws InvalidArgumentException If the number of bits is out of range.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function shiftedLeft(int $distance): BigInteger
|
||||
@@ -832,6 +992,8 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Returns the integer right shifted by a given number of bits.
|
||||
*
|
||||
* @throws InvalidArgumentException If the number of bits is out of range.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function shiftedRight(int $distance): BigInteger
|
||||
@@ -850,7 +1012,7 @@ final readonly class BigInteger extends BigNumber
|
||||
return $this->quotient($operand);
|
||||
}
|
||||
|
||||
return $this->dividedBy($operand, RoundingMode::UP);
|
||||
return $this->dividedBy($operand, RoundingMode::Up);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -897,6 +1059,26 @@ final readonly class BigInteger extends BigNumber
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if and only if the designated bit is set.
|
||||
*
|
||||
* Computes ((this & (1<<n)) != 0).
|
||||
*
|
||||
* @param int $n The bit to test, 0-based.
|
||||
*
|
||||
* @throws InvalidArgumentException If the bit to test is negative.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function isBitSet(int $n): bool
|
||||
{
|
||||
if ($n < 0) {
|
||||
throw new InvalidArgumentException('The bit to test cannot be negative.');
|
||||
}
|
||||
|
||||
return $this->shiftedRight($n)->isOdd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this number is even.
|
||||
*
|
||||
@@ -922,19 +1104,20 @@ final readonly class BigInteger extends BigNumber
|
||||
*
|
||||
* Computes ((this & (1<<n)) != 0).
|
||||
*
|
||||
* @deprecated Use isBitSet().
|
||||
*
|
||||
* @param int $n The bit to test, 0-based.
|
||||
*
|
||||
* @throws InvalidArgumentException If the bit to test is negative.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function testBit(int $n): bool
|
||||
{
|
||||
if ($n < 0) {
|
||||
throw new InvalidArgumentException('The bit to test cannot be negative.');
|
||||
}
|
||||
trigger_error(
|
||||
'The BigInteger::testBit() method is deprecated, use isBitSet() instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return $this->shiftedRight($n)->isOdd();
|
||||
return $this->isBitSet($n);
|
||||
}
|
||||
|
||||
#[Override]
|
||||
@@ -974,7 +1157,7 @@ final readonly class BigInteger extends BigNumber
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal
|
||||
{
|
||||
return $this->toBigDecimal()->toScale($scale, $roundingMode);
|
||||
}
|
||||
@@ -1022,13 +1205,16 @@ final readonly class BigInteger extends BigNumber
|
||||
/**
|
||||
* Returns a string representation of this number in an arbitrary base with a custom alphabet.
|
||||
*
|
||||
* Because this method accepts an alphabet with any character, including dash, it does not handle negative numbers;
|
||||
* This method is byte-oriented: the alphabet is interpreted as a sequence of single-byte characters.
|
||||
* Multibyte UTF-8 characters are not supported.
|
||||
*
|
||||
* Because this method accepts any single-byte character, including dash, it does not handle negative numbers;
|
||||
* a NegativeNumberException will be thrown when attempting to call this method on a negative number.
|
||||
*
|
||||
* @param string $alphabet The alphabet, for example '01' for base 2, or '01234567' for base 8.
|
||||
*
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
* @throws InvalidArgumentException If the given alphabet does not contain at least 2 chars.
|
||||
* @throws InvalidArgumentException If the alphabet does not contain at least 2 chars, or contains duplicates.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -1040,6 +1226,10 @@ final readonly class BigInteger extends BigNumber
|
||||
throw new InvalidArgumentException('The alphabet must contain at least 2 chars.');
|
||||
}
|
||||
|
||||
if (strlen(count_chars($alphabet, 3)) !== $base) {
|
||||
throw new InvalidArgumentException('The alphabet must not contain duplicate chars.');
|
||||
}
|
||||
|
||||
if ($this->value[0] === '-') {
|
||||
throw new NegativeNumberException(__FUNCTION__ . '() does not support negative numbers.');
|
||||
}
|
||||
@@ -1115,7 +1305,7 @@ final readonly class BigInteger extends BigNumber
|
||||
* @return numeric-string
|
||||
*/
|
||||
#[Override]
|
||||
public function __toString(): string
|
||||
public function toString(): string
|
||||
{
|
||||
/** @var numeric-string */
|
||||
return $this->value;
|
||||
|
||||
149
vendor/brick/math/src/BigNumber.php
vendored
149
vendor/brick/math/src/BigNumber.php
vendored
@@ -26,9 +26,10 @@ use function str_contains;
|
||||
use function str_repeat;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use function trigger_error;
|
||||
|
||||
use const E_USER_DEPRECATED;
|
||||
use const FILTER_VALIDATE_INT;
|
||||
|
||||
use const PREG_UNMATCHED_AS_NULL;
|
||||
|
||||
/**
|
||||
@@ -60,7 +61,7 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
'/^' .
|
||||
'(?<sign>[\-\+])?' .
|
||||
'(?<numerator>[0-9]+)' .
|
||||
'\/?' .
|
||||
'\/' .
|
||||
'(?<denominator>[0-9]+)' .
|
||||
'$/';
|
||||
|
||||
@@ -72,7 +73,7 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
*
|
||||
* - BigNumber instances are returned as is
|
||||
* - integer numbers are returned as BigInteger
|
||||
* - floating point numbers are converted to a string then parsed as such
|
||||
* - floating point numbers are converted to a string then parsed as such (deprecated, will be removed in 0.15)
|
||||
* - strings containing a `/` character are returned as BigRational
|
||||
* - strings containing a `.` character or using an exponential notation are returned as BigDecimal
|
||||
* - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
|
||||
@@ -109,8 +110,10 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
* @throws NumberFormatException If the format of the number is not valid.
|
||||
* @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
|
||||
* @throws RoundingNecessaryException If the value cannot be converted to an instance of the subclass without rounding.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public static function ofNullable(BigNumber|int|float|string|null $value): ?static
|
||||
final public static function ofNullable(BigNumber|int|float|string|null $value): ?static
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return null;
|
||||
@@ -122,11 +125,15 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
/**
|
||||
* Returns the minimum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
* If several values are equal and minimal, the first one is returned.
|
||||
* This can affect the concrete return type when calling this method on BigNumber.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers must be convertible to an
|
||||
* instance of the class this method is called on.
|
||||
*
|
||||
* @throws InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
* @throws MathException If a number is not valid, or is not convertible to an instance of the class
|
||||
* this method is called on.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -152,11 +159,15 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
/**
|
||||
* Returns the maximum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
* If several values are equal and maximal, the first one is returned.
|
||||
* This can affect the concrete return type when calling this method on BigNumber.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers must be convertible to an
|
||||
* instance of the class this method is called on.
|
||||
*
|
||||
* @throws InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
* @throws MathException If a number is not valid, or is not convertible to an instance of the class
|
||||
* this method is called on.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -188,11 +199,12 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
* When called on BigInteger, BigDecimal, or BigRational, sum() requires that all values can be converted to that
|
||||
* specific subclass, and returns a result of the same type.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The values to add. All values must be convertible to the class on
|
||||
* which this method is called.
|
||||
* @param BigNumber|int|float|string ...$values The numbers to add. All the numbers must be convertible to an
|
||||
* instance of the class this method is called on.
|
||||
*
|
||||
* @throws InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
* @throws MathException If a number is not valid, or is not convertible to an instance of the class
|
||||
* this method is called on.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -218,6 +230,8 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
/**
|
||||
* Checks if this number is equal to the given one.
|
||||
*
|
||||
* @throws MathException If the given number is not valid.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
final public function isEqualTo(BigNumber|int|float|string $that): bool
|
||||
@@ -226,7 +240,9 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly lower than the given one.
|
||||
* Checks if this number is strictly less than the given one.
|
||||
*
|
||||
* @throws MathException If the given number is not valid.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -236,7 +252,9 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is lower than or equal to the given one.
|
||||
* Checks if this number is less than or equal to the given one.
|
||||
*
|
||||
* @throws MathException If the given number is not valid.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -248,6 +266,8 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
/**
|
||||
* Checks if this number is strictly greater than the given one.
|
||||
*
|
||||
* @throws MathException If the given number is not valid.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
final public function isGreaterThan(BigNumber|int|float|string $that): bool
|
||||
@@ -258,6 +278,8 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
/**
|
||||
* Checks if this number is greater than or equal to the given one.
|
||||
*
|
||||
* @throws MathException If the given number is not valid.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
final public function isGreaterThanOrEqualTo(BigNumber|int|float|string $that): bool
|
||||
@@ -315,6 +337,23 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
return $this->getSign() >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this number.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
final public function abs(): static
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this number.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
abstract public function negated(): static;
|
||||
|
||||
/**
|
||||
* Returns the sign of this number.
|
||||
*
|
||||
@@ -339,6 +378,41 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
*/
|
||||
abstract public function compareTo(BigNumber|int|float|string $that): int;
|
||||
|
||||
/**
|
||||
* Limits (clamps) this number between the given minimum and maximum values.
|
||||
*
|
||||
* If the number is lower than $min, returns $min.
|
||||
* If the number is greater than $max, returns $max.
|
||||
* Otherwise, returns this number unchanged.
|
||||
*
|
||||
* @param BigNumber|int|float|string $min The minimum. Must be convertible to an instance of the class this method is called on.
|
||||
* @param BigNumber|int|float|string $max The maximum. Must be convertible to an instance of the class this method is called on.
|
||||
*
|
||||
* @throws MathException If min/max are not convertible to an instance of the class this method is called on.
|
||||
* @throws InvalidArgumentException If min is greater than max.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
final public function clamp(BigNumber|int|float|string $min, BigNumber|int|float|string $max): static
|
||||
{
|
||||
$min = static::of($min);
|
||||
$max = static::of($max);
|
||||
|
||||
if ($min->isGreaterThan($max)) {
|
||||
throw new InvalidArgumentException('Minimum value must be less than or equal to maximum value.');
|
||||
}
|
||||
|
||||
if ($this->isLessThan($min)) {
|
||||
return $min;
|
||||
}
|
||||
|
||||
if ($this->isGreaterThan($max)) {
|
||||
return $max;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this number to a BigInteger.
|
||||
*
|
||||
@@ -367,15 +441,16 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
/**
|
||||
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
|
||||
*
|
||||
* @param int $scale The scale of the resulting `BigDecimal`.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to UNNECESSARY.
|
||||
* @param int $scale The scale of the resulting `BigDecimal`. Must be non-negative.
|
||||
* @param RoundingMode $roundingMode An optional rounding mode, defaults to Unnecessary.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
|
||||
* This only applies when RoundingMode::UNNECESSARY is used.
|
||||
* @throws InvalidArgumentException If the scale is negative.
|
||||
* @throws RoundingNecessaryException If RoundingMode::Unnecessary is used, and this number cannot be converted to
|
||||
* the given scale without rounding.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal;
|
||||
abstract public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal;
|
||||
|
||||
/**
|
||||
* Returns the exact value of this number as a native integer.
|
||||
@@ -397,26 +472,35 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
*
|
||||
* If the number is greater than the largest representable floating point number, positive infinity is returned.
|
||||
* If the number is less than the smallest representable floating point number, negative infinity is returned.
|
||||
* This method never returns NaN.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
abstract public function toFloat(): float;
|
||||
|
||||
#[Override]
|
||||
final public function jsonSerialize(): string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this number.
|
||||
*
|
||||
* The output of this method can be parsed by the `of()` factory method;
|
||||
* this will yield an object equal to this one, without any information loss.
|
||||
* The output of this method can be parsed by the `of()` factory method; this will yield an object equal to this
|
||||
* one, but possibly of a different type if instantiated through `BigNumber::of()`.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
abstract public function __toString(): string;
|
||||
abstract public function toString(): string;
|
||||
|
||||
#[Override]
|
||||
final public function jsonSerialize(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @pure
|
||||
*/
|
||||
final public function __toString(): string
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden by subclasses to convert a BigNumber to an instance of the subclass.
|
||||
@@ -480,6 +564,13 @@ abstract readonly class BigNumber implements JsonSerializable, Stringable
|
||||
}
|
||||
|
||||
if (is_float($value)) {
|
||||
// @phpstan-ignore-next-line
|
||||
trigger_error(
|
||||
'Passing floats to BigNumber::of() and arithmetic methods is deprecated and will be removed in 0.15. ' .
|
||||
'Cast the float to string explicitly to preserve the previous behaviour.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
if (is_nan($value)) {
|
||||
$value = 'NAN';
|
||||
} else {
|
||||
|
||||
228
vendor/brick/math/src/BigRational.php
vendored
228
vendor/brick/math/src/BigRational.php
vendored
@@ -12,10 +12,22 @@ use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use Override;
|
||||
|
||||
use function is_finite;
|
||||
use function max;
|
||||
use function min;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use function trigger_error;
|
||||
|
||||
use const E_USER_DEPRECATED;
|
||||
|
||||
/**
|
||||
* An arbitrarily large rational number.
|
||||
*
|
||||
* This class is immutable.
|
||||
*
|
||||
* Fractions are automatically simplified to lowest terms. For example, `2/4` becomes `1/2`.
|
||||
* The denominator is always strictly positive; the sign is carried by the numerator.
|
||||
*/
|
||||
final readonly class BigRational extends BigNumber
|
||||
{
|
||||
@@ -63,16 +75,42 @@ final readonly class BigRational extends BigNumber
|
||||
* If the denominator is negative, the signs of both the numerator and the denominator
|
||||
* will be inverted to ensure that the denominator is always positive.
|
||||
*
|
||||
* @deprecated Use ofFraction() instead.
|
||||
*
|
||||
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws NumberFormatException If an argument does not represent a valid number.
|
||||
* @throws RoundingNecessaryException If an argument represents a non-integer number.
|
||||
* @throws DivisionByZeroException If the denominator is zero.
|
||||
*/
|
||||
public static function nd(
|
||||
BigNumber|int|float|string $numerator,
|
||||
BigNumber|int|float|string $denominator,
|
||||
): BigRational {
|
||||
trigger_error(
|
||||
'The BigRational::nd() method is deprecated, use BigRational::ofFraction() instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return self::ofFraction($numerator, $denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigRational out of a numerator and a denominator.
|
||||
*
|
||||
* If the denominator is negative, the signs of both the numerator and the denominator
|
||||
* will be inverted to ensure that the denominator is always positive.
|
||||
*
|
||||
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @throws MathException If an argument is not valid, or is not convertible to a BigInteger.
|
||||
* @throws DivisionByZeroException If the denominator is zero.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public static function nd(
|
||||
public static function ofFraction(
|
||||
BigNumber|int|float|string $numerator,
|
||||
BigNumber|int|float|string $denominator,
|
||||
): BigRational {
|
||||
@@ -152,35 +190,84 @@ final readonly class BigRational extends BigNumber
|
||||
/**
|
||||
* Returns the quotient of the division of the numerator by the denominator.
|
||||
*
|
||||
* @pure
|
||||
* @deprecated Will be removed in 0.15. Use getIntegralPart() instead.
|
||||
*/
|
||||
public function quotient(): BigInteger
|
||||
{
|
||||
trigger_error(
|
||||
'BigRational::quotient() is deprecated and will be removed in 0.15. Use getIntegralPart() instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return $this->numerator->quotient($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of the numerator by the denominator.
|
||||
*
|
||||
* @pure
|
||||
* @deprecated Will be removed in 0.15. Use `$number->getNumerator()->remainder($number->getDenominator())` instead.
|
||||
*/
|
||||
public function remainder(): BigInteger
|
||||
{
|
||||
trigger_error(
|
||||
'BigRational::remainder() is deprecated and will be removed in 0.15. Use `$number->getNumerator()->remainder($number->getDenominator())` instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return $this->numerator->remainder($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return array{BigInteger, BigInteger}
|
||||
* @deprecated Will be removed in 0.15. Use `$number->getNumerator()->quotientAndRemainder($number->getDenominator())` instead.
|
||||
*
|
||||
* @pure
|
||||
* @return array{BigInteger, BigInteger}
|
||||
*/
|
||||
public function quotientAndRemainder(): array
|
||||
{
|
||||
trigger_error(
|
||||
'BigRational::quotientAndRemainder() is deprecated and will be removed in 0.15. Use `$number->getNumerator()->quotientAndRemainder($number->getDenominator())` instead.',
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
return $this->numerator->quotientAndRemainder($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integral part of this rational number.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7/3` returns `2` (since 7/3 = 2 + 1/3)
|
||||
* - `-7/3` returns `-2` (since -7/3 = -2 + (-1/3))
|
||||
*
|
||||
* The following identity holds: `$r->isEqualTo($r->getFractionalPart()->plus($r->getIntegralPart()))`.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function getIntegralPart(): BigInteger
|
||||
{
|
||||
return $this->numerator->quotient($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fractional part of this rational number.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `7/3` returns `1/3` (since 7/3 = 2 + 1/3)
|
||||
* - `-7/3` returns `-1/3` (since -7/3 = -2 + (-1/3))
|
||||
*
|
||||
* The following identity holds: `$r->isEqualTo($r->getFractionalPart()->plus($r->getIntegralPart()))`.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function getFractionalPart(): BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->remainder($this->denominator), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of this number and the given one.
|
||||
*
|
||||
@@ -226,7 +313,7 @@ final readonly class BigRational extends BigNumber
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number.
|
||||
* @throws MathException If the multiplier is not valid.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -245,7 +332,8 @@ final readonly class BigRational extends BigNumber
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, or is zero.
|
||||
* @throws MathException If the divisor is not valid.
|
||||
* @throws DivisionByZeroException If the divisor is zero.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -253,6 +341,10 @@ final readonly class BigRational extends BigNumber
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->denominator);
|
||||
$denominator = $this->denominator->multipliedBy($that->numerator);
|
||||
|
||||
@@ -269,9 +361,7 @@ final readonly class BigRational extends BigNumber
|
||||
public function power(int $exponent): BigRational
|
||||
{
|
||||
if ($exponent === 0) {
|
||||
$one = BigInteger::one();
|
||||
|
||||
return new BigRational($one, $one, false);
|
||||
return BigRational::one();
|
||||
}
|
||||
|
||||
if ($exponent === 1) {
|
||||
@@ -299,22 +389,8 @@ final readonly class BigRational extends BigNumber
|
||||
return new BigRational($this->denominator, $this->numerator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this BigRational.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function abs(): BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->abs(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this BigRational.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function negated(): BigRational
|
||||
#[Override]
|
||||
public function negated(): static
|
||||
{
|
||||
return new BigRational($this->numerator->negated(), $this->denominator, false);
|
||||
}
|
||||
@@ -337,7 +413,15 @@ final readonly class BigRational extends BigNumber
|
||||
#[Override]
|
||||
public function compareTo(BigNumber|int|float|string $that): int
|
||||
{
|
||||
return $this->minus($that)->getSign();
|
||||
$that = BigRational::of($that);
|
||||
|
||||
if ($this->denominator->isEqualTo($that->denominator)) {
|
||||
return $this->numerator->compareTo($that->numerator);
|
||||
}
|
||||
|
||||
return $this->numerator
|
||||
->multipliedBy($that->denominator)
|
||||
->compareTo($that->numerator->multipliedBy($this->denominator));
|
||||
}
|
||||
|
||||
#[Override]
|
||||
@@ -361,7 +445,7 @@ final readonly class BigRational extends BigNumber
|
||||
#[Override]
|
||||
public function toBigDecimal(): BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
|
||||
return $this->numerator->toBigDecimal()->dividedByExact($this->denominator);
|
||||
}
|
||||
|
||||
#[Override]
|
||||
@@ -371,7 +455,7 @@ final readonly class BigRational extends BigNumber
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::UNNECESSARY): BigDecimal
|
||||
public function toScale(int $scale, RoundingMode $roundingMode = RoundingMode::Unnecessary): BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||
}
|
||||
@@ -386,15 +470,32 @@ final readonly class BigRational extends BigNumber
|
||||
public function toFloat(): float
|
||||
{
|
||||
$simplified = $this->simplified();
|
||||
$numeratorFloat = $simplified->numerator->toFloat();
|
||||
$denominatorFloat = $simplified->denominator->toFloat();
|
||||
|
||||
return $simplified->numerator->toFloat() / $simplified->denominator->toFloat();
|
||||
if (is_finite($numeratorFloat) && is_finite($denominatorFloat)) {
|
||||
return $numeratorFloat / $denominatorFloat;
|
||||
}
|
||||
|
||||
// At least one side overflows to INF; use a decimal approximation instead.
|
||||
// We need ~17 significant digits for double precision (we use 20 for some margin). Since $scale controls
|
||||
// decimal places (not significant digits), we subtract the estimated order of magnitude so that large results
|
||||
// use fewer decimal places and small results use more (to look past leading zeros). Clamped to [0, 350] as
|
||||
// doubles range from e-324 to e308 (350 ≈ 324 + 20 significant digits + margin).
|
||||
$magnitude = strlen($simplified->numerator->abs()->toString()) - strlen($simplified->denominator->toString());
|
||||
$scale = min(350, max(0, 20 - $magnitude));
|
||||
|
||||
return $simplified->numerator
|
||||
->toBigDecimal()
|
||||
->dividedBy($simplified->denominator, $scale, RoundingMode::HalfEven)
|
||||
->toFloat();
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function __toString(): string
|
||||
public function toString(): string
|
||||
{
|
||||
$numerator = (string) $this->numerator;
|
||||
$denominator = (string) $this->denominator;
|
||||
$numerator = $this->numerator->toString();
|
||||
$denominator = $this->denominator->toString();
|
||||
|
||||
if ($denominator === '1') {
|
||||
return $numerator;
|
||||
@@ -403,6 +504,67 @@ final readonly class BigRational extends BigNumber
|
||||
return $numerator . '/' . $denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the decimal representation of this rational number, with repeating decimals in parentheses.
|
||||
*
|
||||
* WARNING: This method is unbounded.
|
||||
* The length of the repeating decimal period can be as large as `denominator - 1`.
|
||||
* For fractions with large denominators, this method can use excessive memory and CPU time.
|
||||
* For example, `1/100019` has a repeating period of 100,018 digits.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - `10/3` returns `3.(3)`
|
||||
* - `171/70` returns `2.4(428571)`
|
||||
* - `1/2` returns `0.5`
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function toRepeatingDecimalString(): string
|
||||
{
|
||||
if ($this->numerator->isZero()) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$sign = $this->numerator->isNegative() ? '-' : '';
|
||||
$numerator = $this->numerator->abs();
|
||||
$denominator = $this->denominator;
|
||||
|
||||
$integral = $numerator->quotient($denominator);
|
||||
$remainder = $numerator->remainder($denominator);
|
||||
|
||||
$integralString = $integral->toString();
|
||||
|
||||
if ($remainder->isZero()) {
|
||||
return $sign . $integralString;
|
||||
}
|
||||
|
||||
$digits = '';
|
||||
$remainderPositions = [];
|
||||
$index = 0;
|
||||
|
||||
while (! $remainder->isZero()) {
|
||||
$remainderString = $remainder->toString();
|
||||
|
||||
if (isset($remainderPositions[$remainderString])) {
|
||||
$repeatIndex = $remainderPositions[$remainderString];
|
||||
$nonRepeating = substr($digits, 0, $repeatIndex);
|
||||
$repeating = substr($digits, $repeatIndex);
|
||||
|
||||
return $sign . $integralString . '.' . $nonRepeating . '(' . $repeating . ')';
|
||||
}
|
||||
|
||||
$remainderPositions[$remainderString] = $index;
|
||||
$remainder = $remainder->multipliedBy(10);
|
||||
|
||||
$digits .= $remainder->quotient($denominator)->toString();
|
||||
$remainder = $remainder->remainder($denominator);
|
||||
$index++;
|
||||
}
|
||||
|
||||
return $sign . $integralString . '.' . $digits;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required for serializing the object and SHOULD NOT be accessed directly.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,6 @@ final class IntegerOverflowException extends MathException
|
||||
{
|
||||
$message = '%s is out of range %d to %d and cannot be represented as an integer.';
|
||||
|
||||
return new self(sprintf($message, (string) $value, PHP_INT_MIN, PHP_INT_MAX));
|
||||
return new self(sprintf($message, $value->toString(), PHP_INT_MIN, PHP_INT_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,19 +31,30 @@ final class NumberFormatException extends MathException
|
||||
* @pure
|
||||
*/
|
||||
public static function charNotInAlphabet(string $char): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Character %s is not valid in the given alphabet.',
|
||||
self::charToString($char),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @pure
|
||||
*/
|
||||
private static function charToString(string $char): string
|
||||
{
|
||||
$ord = ord($char);
|
||||
|
||||
if ($ord < 32 || $ord > 126) {
|
||||
$char = strtoupper(dechex($ord));
|
||||
|
||||
if ($ord < 10) {
|
||||
if ($ord < 16) {
|
||||
$char = '0' . $char;
|
||||
}
|
||||
} else {
|
||||
$char = '"' . $char . '"';
|
||||
|
||||
return '0x' . $char;
|
||||
}
|
||||
|
||||
return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
|
||||
return '"' . $char . '"';
|
||||
}
|
||||
}
|
||||
|
||||
43
vendor/brick/math/src/Internal/Calculator.php
vendored
43
vendor/brick/math/src/Internal/Calculator.php
vendored
@@ -217,7 +217,7 @@ abstract readonly class Calculator
|
||||
/**
|
||||
* Raises a number into power with modulo.
|
||||
*
|
||||
* @param string $base The base number; must be positive or zero.
|
||||
* @param string $base The base number.
|
||||
* @param string $exp The exponent; must be positive or zero.
|
||||
* @param string $mod The modulus; must be strictly positive.
|
||||
*
|
||||
@@ -248,6 +248,25 @@ abstract readonly class Calculator
|
||||
return $this->gcd($b, $this->divR($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the least common multiple of the two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for LCM calculations.
|
||||
*
|
||||
* @return string The LCM, always positive, or zero if at least one argument is zero.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
public function lcm(string $a, string $b): string
|
||||
{
|
||||
if ($a === '0' || $b === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
return $this->divQ($this->abs($this->mul($a, $b)), $this->gcd($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of the given number, rounded down.
|
||||
*
|
||||
@@ -394,7 +413,7 @@ abstract readonly class Calculator
|
||||
* @param string $b The divisor, must not be zero.
|
||||
* @param RoundingMode $roundingMode The rounding mode.
|
||||
*
|
||||
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
||||
* @throws RoundingNecessaryException If RoundingMode::Unnecessary is provided but rounding is necessary.
|
||||
*
|
||||
* @pure
|
||||
*/
|
||||
@@ -415,52 +434,52 @@ abstract readonly class Calculator
|
||||
$increment = false;
|
||||
|
||||
switch ($roundingMode) {
|
||||
case RoundingMode::UNNECESSARY:
|
||||
case RoundingMode::Unnecessary:
|
||||
if ($hasDiscardedFraction) {
|
||||
throw RoundingNecessaryException::roundingNecessary();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::UP:
|
||||
case RoundingMode::Up:
|
||||
$increment = $hasDiscardedFraction;
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::DOWN:
|
||||
case RoundingMode::Down:
|
||||
break;
|
||||
|
||||
case RoundingMode::CEILING:
|
||||
case RoundingMode::Ceiling:
|
||||
$increment = $hasDiscardedFraction && $isPositiveOrZero;
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::FLOOR:
|
||||
case RoundingMode::Floor:
|
||||
$increment = $hasDiscardedFraction && ! $isPositiveOrZero;
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_UP:
|
||||
case RoundingMode::HalfUp:
|
||||
$increment = $discardedFractionSign() >= 0;
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_DOWN:
|
||||
case RoundingMode::HalfDown:
|
||||
$increment = $discardedFractionSign() > 0;
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_CEILING:
|
||||
case RoundingMode::HalfCeiling:
|
||||
$increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_FLOOR:
|
||||
case RoundingMode::HalfFloor:
|
||||
$increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
||||
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_EVEN:
|
||||
case RoundingMode::HalfEven:
|
||||
$lastDigit = (int) $quotient[-1];
|
||||
$lastDigitIsEven = ($lastDigit % 2 === 0);
|
||||
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
||||
|
||||
@@ -71,6 +71,9 @@ final readonly class BcMathCalculator extends Calculator
|
||||
#[Override]
|
||||
public function modPow(string $base, string $exp, string $mod): string
|
||||
{
|
||||
// normalize to Euclidean representative so modPow() stays consistent with mod()
|
||||
$base = $this->mod($base, $mod);
|
||||
|
||||
return bcpowmod($base, $exp, $mod, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ use function gmp_div_r;
|
||||
use function gmp_gcd;
|
||||
use function gmp_init;
|
||||
use function gmp_invert;
|
||||
use function gmp_lcm;
|
||||
use function gmp_mul;
|
||||
use function gmp_or;
|
||||
use function gmp_pow;
|
||||
@@ -107,6 +108,12 @@ final readonly class GmpCalculator extends Calculator
|
||||
return gmp_strval(gmp_gcd($a, $b));
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function lcm(string $a, string $b): string
|
||||
{
|
||||
return gmp_strval(gmp_lcm($a, $b));
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function fromBase(string $number, int $base): string
|
||||
{
|
||||
|
||||
@@ -230,10 +230,8 @@ final readonly class NativeCalculator extends Calculator
|
||||
#[Override]
|
||||
public function modPow(string $base, string $exp, string $mod): string
|
||||
{
|
||||
// special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
|
||||
if ($base === '0' && $exp === '0' && $mod === '1') {
|
||||
return '0';
|
||||
}
|
||||
// normalize to Euclidean representative so modPow() stays consistent with mod()
|
||||
$base = $this->mod($base, $mod);
|
||||
|
||||
// special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0)
|
||||
if ($exp === '0' && $mod === '1') {
|
||||
|
||||
95
vendor/brick/math/src/RoundingMode.php
vendored
95
vendor/brick/math/src/RoundingMode.php
vendored
@@ -5,13 +5,8 @@ declare(strict_types=1);
|
||||
namespace Brick\Math;
|
||||
|
||||
/**
|
||||
* Specifies a rounding behavior for numerical operations capable of discarding precision.
|
||||
*
|
||||
* Each rounding mode indicates how the least significant returned digit of a rounded result
|
||||
* is to be calculated. If fewer digits are returned than the digits needed to represent the
|
||||
* exact numerical result, the discarded digits will be referred to as the discarded fraction
|
||||
* regardless the digits' contribution to the value of the number. In other words, considered
|
||||
* as a numerical value, the discarded fraction could have an absolute value greater than one.
|
||||
* Specifies rounding behavior by defining how discarded digits affect the returned result when an exact value cannot
|
||||
* be represented at the requested scale.
|
||||
*/
|
||||
enum RoundingMode
|
||||
{
|
||||
@@ -21,7 +16,7 @@ enum RoundingMode
|
||||
* If this rounding mode is specified on an operation that yields a result that
|
||||
* cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
|
||||
*/
|
||||
case UNNECESSARY;
|
||||
case Unnecessary;
|
||||
|
||||
/**
|
||||
* Rounds away from zero.
|
||||
@@ -29,7 +24,7 @@ enum RoundingMode
|
||||
* Always increments the digit prior to a nonzero discarded fraction.
|
||||
* Note that this rounding mode never decreases the magnitude of the calculated value.
|
||||
*/
|
||||
case UP;
|
||||
case Up;
|
||||
|
||||
/**
|
||||
* Rounds towards zero.
|
||||
@@ -37,62 +32,112 @@ enum RoundingMode
|
||||
* Never increments the digit prior to a discarded fraction (i.e., truncates).
|
||||
* Note that this rounding mode never increases the magnitude of the calculated value.
|
||||
*/
|
||||
case DOWN;
|
||||
case Down;
|
||||
|
||||
/**
|
||||
* Rounds towards positive infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
|
||||
* If the result is positive, behaves as for Up; if negative, behaves as for Down.
|
||||
* Note that this rounding mode never decreases the calculated value.
|
||||
*/
|
||||
case CEILING;
|
||||
case Ceiling;
|
||||
|
||||
/**
|
||||
* Rounds towards negative infinity.
|
||||
*
|
||||
* If the result is positive, behave as for DOWN; if negative, behave as for UP.
|
||||
* If the result is positive, behaves as for Down; if negative, behaves as for Up.
|
||||
* Note that this rounding mode never increases the calculated value.
|
||||
*/
|
||||
case FLOOR;
|
||||
case Floor;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
|
||||
*
|
||||
* Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN.
|
||||
* Behaves as for Up if the discarded fraction is >= 0.5; otherwise, behaves as for Down.
|
||||
* Note that this is the rounding mode commonly taught at school.
|
||||
*/
|
||||
case HALF_UP;
|
||||
case HalfUp;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
|
||||
*
|
||||
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
|
||||
* Behaves as for Up if the discarded fraction is > 0.5; otherwise, behaves as for Down.
|
||||
*/
|
||||
case HALF_DOWN;
|
||||
case HalfDown;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
|
||||
* If the result is positive, behaves as for HalfUp; if negative, behaves as for HalfDown.
|
||||
*/
|
||||
case HALF_CEILING;
|
||||
case HalfCeiling;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
|
||||
* If the result is positive, behaves as for HalfDown; if negative, behaves as for HalfUp.
|
||||
*/
|
||||
case HALF_FLOOR;
|
||||
case HalfFloor;
|
||||
|
||||
/**
|
||||
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
|
||||
*
|
||||
* Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd;
|
||||
* behaves as for HALF_DOWN if it's even.
|
||||
* Behaves as for HalfUp if the digit to the left of the discarded fraction is odd;
|
||||
* behaves as for HalfDown if it's even.
|
||||
*
|
||||
* Note that this is the rounding mode that statistically minimizes
|
||||
* cumulative error when applied repeatedly over a sequence of calculations.
|
||||
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
|
||||
*/
|
||||
case HALF_EVEN;
|
||||
case HalfEven;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::Unnecessary instead.
|
||||
*/
|
||||
public const UNNECESSARY = self::Unnecessary;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::Up instead.
|
||||
*/
|
||||
public const UP = self::Up;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::Down instead.
|
||||
*/
|
||||
public const DOWN = self::Down;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::Ceiling instead.
|
||||
*/
|
||||
public const CEILING = self::Ceiling;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::Floor instead.
|
||||
*/
|
||||
public const FLOOR = self::Floor;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::HalfUp instead.
|
||||
*/
|
||||
public const HALF_UP = self::HalfUp;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::HalfDown instead.
|
||||
*/
|
||||
public const HALF_DOWN = self::HalfDown;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::HalfCeiling instead.
|
||||
*/
|
||||
public const HALF_CEILING = self::HalfCeiling;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::HalfFloor instead.
|
||||
*/
|
||||
public const HALF_FLOOR = self::HalfFloor;
|
||||
|
||||
/**
|
||||
* @deprecated Use RoundingMode::HalfEven instead.
|
||||
*/
|
||||
public const HALF_EVEN = self::HalfEven;
|
||||
}
|
||||
|
||||
10
vendor/brick/math/tools/ecs/composer.json
vendored
10
vendor/brick/math/tools/ecs/composer.json
vendored
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"require": {
|
||||
"brick/coding-standard": "v2"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": false
|
||||
}
|
||||
}
|
||||
}
|
||||
33
vendor/brick/math/tools/ecs/ecs.php
vendored
33
vendor/brick/math/tools/ecs/ecs.php
vendored
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpCsFixer\Fixer\ClassNotation\OrderedTypesFixer;
|
||||
use PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer;
|
||||
use SlevomatCodingStandard\Sniffs\Whitespaces\DuplicateSpacesSniff;
|
||||
use Symplify\EasyCodingStandard\Config\ECSConfig;
|
||||
|
||||
return static function (ECSConfig $ecsConfig): void {
|
||||
$ecsConfig->import(__DIR__ . '/vendor/brick/coding-standard/ecs.php');
|
||||
|
||||
$libRootPath = realpath(__DIR__ . '/../..');
|
||||
|
||||
$ecsConfig->paths(
|
||||
[
|
||||
$libRootPath . '/src',
|
||||
$libRootPath . '/tests',
|
||||
$libRootPath . '/phpunit.php',
|
||||
$libRootPath . '/random-tests.php',
|
||||
__FILE__,
|
||||
],
|
||||
);
|
||||
|
||||
$ecsConfig->skip([
|
||||
// Allows alignment in test providers
|
||||
DuplicateSpacesSniff::class => [$libRootPath . '/tests'],
|
||||
|
||||
// We want to keep BigNumber|int|float|string order
|
||||
OrderedTypesFixer::class => null,
|
||||
PhpdocTypesOrderFixer::class => null,
|
||||
]);
|
||||
};
|
||||
10
vendor/composer/autoload_classmap.php
vendored
10
vendor/composer/autoload_classmap.php
vendored
@@ -450,6 +450,7 @@ return array(
|
||||
'League\\HTMLToMarkdown\\HtmlConverterInterface' => $vendorDir . '/league/html-to-markdown/src/HtmlConverterInterface.php',
|
||||
'League\\HTMLToMarkdown\\PreConverterInterface' => $vendorDir . '/league/html-to-markdown/src/PreConverterInterface.php',
|
||||
'League\\Uri\\BaseUri' => $vendorDir . '/league/uri/BaseUri.php',
|
||||
'League\\Uri\\Builder' => $vendorDir . '/league/uri/Builder.php',
|
||||
'League\\Uri\\Contracts\\AuthorityInterface' => $vendorDir . '/league/uri-interfaces/Contracts/AuthorityInterface.php',
|
||||
'League\\Uri\\Contracts\\Conditionable' => $vendorDir . '/league/uri-interfaces/Contracts/Conditionable.php',
|
||||
'League\\Uri\\Contracts\\DataPathInterface' => $vendorDir . '/league/uri-interfaces/Contracts/DataPathInterface.php',
|
||||
@@ -462,6 +463,7 @@ return array(
|
||||
'League\\Uri\\Contracts\\PortInterface' => $vendorDir . '/league/uri-interfaces/Contracts/PortInterface.php',
|
||||
'League\\Uri\\Contracts\\QueryInterface' => $vendorDir . '/league/uri-interfaces/Contracts/QueryInterface.php',
|
||||
'League\\Uri\\Contracts\\SegmentedPathInterface' => $vendorDir . '/league/uri-interfaces/Contracts/SegmentedPathInterface.php',
|
||||
'League\\Uri\\Contracts\\Transformable' => $vendorDir . '/league/uri-interfaces/Contracts/Transformable.php',
|
||||
'League\\Uri\\Contracts\\UriAccess' => $vendorDir . '/league/uri-interfaces/Contracts/UriAccess.php',
|
||||
'League\\Uri\\Contracts\\UriComponentInterface' => $vendorDir . '/league/uri-interfaces/Contracts/UriComponentInterface.php',
|
||||
'League\\Uri\\Contracts\\UriException' => $vendorDir . '/league/uri-interfaces/Contracts/UriException.php',
|
||||
@@ -489,8 +491,11 @@ return array(
|
||||
'League\\Uri\\Idna\\Option' => $vendorDir . '/league/uri-interfaces/Idna/Option.php',
|
||||
'League\\Uri\\Idna\\Result' => $vendorDir . '/league/uri-interfaces/Idna/Result.php',
|
||||
'League\\Uri\\KeyValuePair\\Converter' => $vendorDir . '/league/uri-interfaces/KeyValuePair/Converter.php',
|
||||
'League\\Uri\\QueryComposeMode' => $vendorDir . '/league/uri-interfaces/QueryComposeMode.php',
|
||||
'League\\Uri\\QueryExtractMode' => $vendorDir . '/league/uri-interfaces/QueryExtractMode.php',
|
||||
'League\\Uri\\QueryString' => $vendorDir . '/league/uri-interfaces/QueryString.php',
|
||||
'League\\Uri\\SchemeType' => $vendorDir . '/league/uri/SchemeType.php',
|
||||
'League\\Uri\\StringCoercionMode' => $vendorDir . '/league/uri-interfaces/StringCoercionMode.php',
|
||||
'League\\Uri\\Uri' => $vendorDir . '/league/uri/Uri.php',
|
||||
'League\\Uri\\UriComparisonMode' => $vendorDir . '/league/uri-interfaces/UriComparisonMode.php',
|
||||
'League\\Uri\\UriInfo' => $vendorDir . '/league/uri/UriInfo.php',
|
||||
@@ -1913,6 +1918,7 @@ return array(
|
||||
'Zotlabs\\Lib\\Crypto' => $baseDir . '/Zotlabs/Lib/Crypto.php',
|
||||
'Zotlabs\\Lib\\DB_Upgrade' => $baseDir . '/Zotlabs/Lib/DB_Upgrade.php',
|
||||
'Zotlabs\\Lib\\DReport' => $baseDir . '/Zotlabs/Lib/DReport.php',
|
||||
'Zotlabs\\Lib\\DbStats' => $baseDir . '/Zotlabs/Lib/DbStats.php',
|
||||
'Zotlabs\\Lib\\Enotify' => $baseDir . '/Zotlabs/Lib/Enotify.php',
|
||||
'Zotlabs\\Lib\\ExtendedZip' => $baseDir . '/Zotlabs/Lib/ExtendedZip.php',
|
||||
'Zotlabs\\Lib\\Hashpath' => $baseDir . '/Zotlabs/Lib/Hashpath.php',
|
||||
@@ -1930,12 +1936,15 @@ return array(
|
||||
'Zotlabs\\Lib\\MarkdownSoap' => $baseDir . '/Zotlabs/Lib/MarkdownSoap.php',
|
||||
'Zotlabs\\Lib\\MessageFilter' => $baseDir . '/Zotlabs/Lib/MessageFilter.php',
|
||||
'Zotlabs\\Lib\\Multibase' => $baseDir . '/Zotlabs/Lib/Multibase.php',
|
||||
'Zotlabs\\Lib\\MySQLDbStats' => $baseDir . '/Zotlabs/Lib/MySQLDbStats.php',
|
||||
'Zotlabs\\Lib\\ObjCache' => $baseDir . '/Zotlabs/Lib/ObjCache.php',
|
||||
'Zotlabs\\Lib\\PConfig' => $baseDir . '/Zotlabs/Lib/PConfig.php',
|
||||
'Zotlabs\\Lib\\Permcat' => $baseDir . '/Zotlabs/Lib/Permcat.php',
|
||||
'Zotlabs\\Lib\\PermissionDescription' => $baseDir . '/Zotlabs/Lib/PermissionDescription.php',
|
||||
'Zotlabs\\Lib\\PostgresDbStats' => $baseDir . '/Zotlabs/Lib/PostgresDbStats.php',
|
||||
'Zotlabs\\Lib\\Queue' => $baseDir . '/Zotlabs/Lib/Queue.php',
|
||||
'Zotlabs\\Lib\\QueueWorker' => $baseDir . '/Zotlabs/Lib/QueueWorker.php',
|
||||
'Zotlabs\\Lib\\QueueWorkerStats' => $baseDir . '/Zotlabs/Lib/QueueWorkerStats.php',
|
||||
'Zotlabs\\Lib\\SConfig' => $baseDir . '/Zotlabs/Lib/SConfig.php',
|
||||
'Zotlabs\\Lib\\Share' => $baseDir . '/Zotlabs/Lib/Share.php',
|
||||
'Zotlabs\\Lib\\SvgSanitizer' => $baseDir . '/Zotlabs/Lib/SvgSanitizer.php',
|
||||
@@ -2076,6 +2085,7 @@ return array(
|
||||
'Zotlabs\\Module\\Pconfig' => $baseDir . '/Zotlabs/Module/Pconfig.php',
|
||||
'Zotlabs\\Module\\Pdledit' => $baseDir . '/Zotlabs/Module/Pdledit.php',
|
||||
'Zotlabs\\Module\\Pdledit_gui' => $baseDir . '/Zotlabs/Module/Pdledit_gui.php',
|
||||
'Zotlabs\\Module\\Perfstats' => $baseDir . '/Zotlabs/Module/Perfstats.php',
|
||||
'Zotlabs\\Module\\Permcat' => $baseDir . '/Zotlabs/Module/Permcat.php',
|
||||
'Zotlabs\\Module\\Permcats' => $baseDir . '/Zotlabs/Module/Permcats.php',
|
||||
'Zotlabs\\Module\\Photo' => $baseDir . '/Zotlabs/Module/Photo.php',
|
||||
|
||||
2
vendor/composer/autoload_files.php
vendored
2
vendor/composer/autoload_files.php
vendored
@@ -15,9 +15,9 @@ return array(
|
||||
'3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php',
|
||||
'93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'3253b43614197c132b67e5f343def5b7' => $vendorDir . '/paragonie/easy-ecc/autoload-shim.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
|
||||
|
||||
154
vendor/composer/autoload_static.php
vendored
154
vendor/composer/autoload_static.php
vendored
@@ -16,9 +16,9 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php',
|
||||
'93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'3253b43614197c132b67e5f343def5b7' => __DIR__ . '/..' . '/paragonie/easy-ecc/autoload-shim.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
|
||||
@@ -27,25 +27,25 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'v' =>
|
||||
'v' =>
|
||||
array (
|
||||
'voku\\' => 5,
|
||||
),
|
||||
'p' =>
|
||||
'p' =>
|
||||
array (
|
||||
'phpseclib\\' => 10,
|
||||
'phpseclib3\\' => 11,
|
||||
),
|
||||
'c' =>
|
||||
'c' =>
|
||||
array (
|
||||
'chillerlan\\Settings\\' => 20,
|
||||
'chillerlan\\QRCode\\' => 18,
|
||||
),
|
||||
'Z' =>
|
||||
'Z' =>
|
||||
array (
|
||||
'Zotlabs\\' => 8,
|
||||
),
|
||||
'S' =>
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||
'Symfony\\Polyfill\\Ctype\\' => 23,
|
||||
@@ -62,13 +62,13 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'Sabre\\Event\\' => 12,
|
||||
'Sabre\\' => 6,
|
||||
),
|
||||
'R' =>
|
||||
'R' =>
|
||||
array (
|
||||
'Root23\\JsonCanonicalizer\\' => 25,
|
||||
'Ramsey\\Uuid\\' => 12,
|
||||
'Ramsey\\Collection\\' => 18,
|
||||
),
|
||||
'P' =>
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\Http\\Message\\' => 17,
|
||||
@@ -77,47 +77,47 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'ParagonIE\\EasyECC\\' => 18,
|
||||
'ParagonIE\\ConstantTime\\' => 23,
|
||||
),
|
||||
'O' =>
|
||||
'O' =>
|
||||
array (
|
||||
'OTPHP\\' => 6,
|
||||
),
|
||||
'M' =>
|
||||
'M' =>
|
||||
array (
|
||||
'Michelf\\' => 8,
|
||||
'Mdanter\\Ecc\\' => 12,
|
||||
),
|
||||
'L' =>
|
||||
'L' =>
|
||||
array (
|
||||
'League\\Uri\\' => 11,
|
||||
'League\\HTMLToMarkdown\\' => 22,
|
||||
'LanguageDetection\\' => 18,
|
||||
),
|
||||
'I' =>
|
||||
'I' =>
|
||||
array (
|
||||
'ID3Parser\\' => 10,
|
||||
),
|
||||
'H' =>
|
||||
'H' =>
|
||||
array (
|
||||
'Hubzilla\\' => 9,
|
||||
'HttpSignature\\' => 14,
|
||||
),
|
||||
'G' =>
|
||||
'G' =>
|
||||
array (
|
||||
'GuzzleHttp\\Psr7\\' => 16,
|
||||
),
|
||||
'F' =>
|
||||
'F' =>
|
||||
array (
|
||||
'FG\\' => 3,
|
||||
),
|
||||
'D' =>
|
||||
'D' =>
|
||||
array (
|
||||
'Defuse\\Crypto\\' => 14,
|
||||
),
|
||||
'C' =>
|
||||
'C' =>
|
||||
array (
|
||||
'CommerceGuys\\Intl\\' => 18,
|
||||
),
|
||||
'B' =>
|
||||
'B' =>
|
||||
array (
|
||||
'Brick\\Math\\' => 11,
|
||||
'Bakame\\Http\\StructuredFields\\' => 29,
|
||||
@@ -125,219 +125,219 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'voku\\' =>
|
||||
'voku\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/voku/stop-words/src/voku',
|
||||
1 => __DIR__ . '/..' . '/voku/portable-ascii/src/voku',
|
||||
),
|
||||
'phpseclib\\' =>
|
||||
'phpseclib\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpseclib/phpseclib2_compat/src',
|
||||
),
|
||||
'phpseclib3\\' =>
|
||||
'phpseclib3\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
|
||||
),
|
||||
'chillerlan\\Settings\\' =>
|
||||
'chillerlan\\Settings\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/chillerlan/php-settings-container/src',
|
||||
),
|
||||
'chillerlan\\QRCode\\' =>
|
||||
'chillerlan\\QRCode\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/chillerlan/php-qrcode/src',
|
||||
),
|
||||
'Zotlabs\\' =>
|
||||
'Zotlabs\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/Zotlabs',
|
||||
),
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||
),
|
||||
'Symfony\\Polyfill\\Ctype\\' =>
|
||||
'Symfony\\Polyfill\\Ctype\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
||||
),
|
||||
'Symfony\\Component\\Filesystem\\' =>
|
||||
'Symfony\\Component\\Filesystem\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/filesystem',
|
||||
),
|
||||
'StephenHill\\' =>
|
||||
'StephenHill\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/stephenhill/base58/src',
|
||||
),
|
||||
'SourceSpan\\' =>
|
||||
'SourceSpan\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/scssphp/source-span/src',
|
||||
),
|
||||
'Smarty\\' =>
|
||||
'Smarty\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/smarty/smarty/src',
|
||||
),
|
||||
'SimplePie\\' =>
|
||||
'SimplePie\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/simplepie/simplepie/src',
|
||||
),
|
||||
'ScssPhp\\ScssPhp\\' =>
|
||||
'ScssPhp\\ScssPhp\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/scssphp/scssphp/src',
|
||||
),
|
||||
'Sabre\\Xml\\' =>
|
||||
'Sabre\\Xml\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/xml/lib',
|
||||
),
|
||||
'Sabre\\VObject\\' =>
|
||||
'Sabre\\VObject\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/vobject/lib',
|
||||
),
|
||||
'Sabre\\Uri\\' =>
|
||||
'Sabre\\Uri\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/uri/lib',
|
||||
),
|
||||
'Sabre\\HTTP\\' =>
|
||||
'Sabre\\HTTP\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/http/lib',
|
||||
),
|
||||
'Sabre\\Event\\' =>
|
||||
'Sabre\\Event\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/event/lib',
|
||||
),
|
||||
'Sabre\\' =>
|
||||
'Sabre\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/dav/lib',
|
||||
),
|
||||
'Root23\\JsonCanonicalizer\\' =>
|
||||
'Root23\\JsonCanonicalizer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/root23/php-json-canonicalization/src',
|
||||
),
|
||||
'Ramsey\\Uuid\\' =>
|
||||
'Ramsey\\Uuid\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ramsey/uuid/src',
|
||||
),
|
||||
'Ramsey\\Collection\\' =>
|
||||
'Ramsey\\Collection\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ramsey/collection/src',
|
||||
),
|
||||
'Psr\\Log\\' =>
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/src',
|
||||
),
|
||||
'Psr\\Http\\Message\\' =>
|
||||
'Psr\\Http\\Message\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
),
|
||||
'Psr\\Clock\\' =>
|
||||
'Psr\\Clock\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/clock/src',
|
||||
),
|
||||
'ParagonIE\\Sodium\\' =>
|
||||
'ParagonIE\\Sodium\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/paragonie/sodium_compat/namespaced',
|
||||
),
|
||||
'ParagonIE\\EasyECC\\' =>
|
||||
'ParagonIE\\EasyECC\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/paragonie/easy-ecc/src',
|
||||
),
|
||||
'ParagonIE\\ConstantTime\\' =>
|
||||
'ParagonIE\\ConstantTime\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
|
||||
),
|
||||
'OTPHP\\' =>
|
||||
'OTPHP\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/spomky-labs/otphp/src',
|
||||
),
|
||||
'Michelf\\' =>
|
||||
'Michelf\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/michelf/php-markdown/Michelf',
|
||||
),
|
||||
'Mdanter\\Ecc\\' =>
|
||||
'Mdanter\\Ecc\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/paragonie/ecc/src',
|
||||
),
|
||||
'League\\Uri\\' =>
|
||||
'League\\Uri\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/uri',
|
||||
1 => __DIR__ . '/..' . '/league/uri-interfaces',
|
||||
),
|
||||
'League\\HTMLToMarkdown\\' =>
|
||||
'League\\HTMLToMarkdown\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/html-to-markdown/src',
|
||||
),
|
||||
'LanguageDetection\\' =>
|
||||
'LanguageDetection\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/patrickschur/language-detection/src/LanguageDetection',
|
||||
),
|
||||
'ID3Parser\\' =>
|
||||
'ID3Parser\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/lukasreschke/id3parser/src',
|
||||
),
|
||||
'Hubzilla\\' =>
|
||||
'Hubzilla\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/include',
|
||||
),
|
||||
'HttpSignature\\' =>
|
||||
'HttpSignature\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/macgirvin/http-message-signer/src',
|
||||
),
|
||||
'GuzzleHttp\\Psr7\\' =>
|
||||
'GuzzleHttp\\Psr7\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
||||
),
|
||||
'FG\\' =>
|
||||
'FG\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/genkgo/php-asn1/lib',
|
||||
),
|
||||
'Defuse\\Crypto\\' =>
|
||||
'Defuse\\Crypto\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/defuse/php-encryption/src',
|
||||
),
|
||||
'CommerceGuys\\Intl\\' =>
|
||||
'CommerceGuys\\Intl\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/commerceguys/intl/src',
|
||||
),
|
||||
'Brick\\Math\\' =>
|
||||
'Brick\\Math\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/brick/math/src',
|
||||
),
|
||||
'Bakame\\Http\\StructuredFields\\' =>
|
||||
'Bakame\\Http\\StructuredFields\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/bakame/http-structured-fields/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'U' =>
|
||||
'U' =>
|
||||
array (
|
||||
'URLify' =>
|
||||
'URLify' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/jbroadway/urlify',
|
||||
),
|
||||
),
|
||||
'T' =>
|
||||
'T' =>
|
||||
array (
|
||||
'Text' =>
|
||||
'Text' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/pear/text_languagedetect',
|
||||
),
|
||||
),
|
||||
'S' =>
|
||||
'S' =>
|
||||
array (
|
||||
'SimplePie' =>
|
||||
'SimplePie' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/simplepie/simplepie/library',
|
||||
),
|
||||
),
|
||||
'O' =>
|
||||
'O' =>
|
||||
array (
|
||||
'OAuth2' =>
|
||||
'OAuth2' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/bshaffer/oauth2-server-php/src',
|
||||
),
|
||||
),
|
||||
'H' =>
|
||||
'H' =>
|
||||
array (
|
||||
'HTMLPurifier' =>
|
||||
'HTMLPurifier' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
|
||||
),
|
||||
@@ -789,6 +789,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'League\\HTMLToMarkdown\\HtmlConverterInterface' => __DIR__ . '/..' . '/league/html-to-markdown/src/HtmlConverterInterface.php',
|
||||
'League\\HTMLToMarkdown\\PreConverterInterface' => __DIR__ . '/..' . '/league/html-to-markdown/src/PreConverterInterface.php',
|
||||
'League\\Uri\\BaseUri' => __DIR__ . '/..' . '/league/uri/BaseUri.php',
|
||||
'League\\Uri\\Builder' => __DIR__ . '/..' . '/league/uri/Builder.php',
|
||||
'League\\Uri\\Contracts\\AuthorityInterface' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/AuthorityInterface.php',
|
||||
'League\\Uri\\Contracts\\Conditionable' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/Conditionable.php',
|
||||
'League\\Uri\\Contracts\\DataPathInterface' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/DataPathInterface.php',
|
||||
@@ -801,6 +802,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'League\\Uri\\Contracts\\PortInterface' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/PortInterface.php',
|
||||
'League\\Uri\\Contracts\\QueryInterface' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/QueryInterface.php',
|
||||
'League\\Uri\\Contracts\\SegmentedPathInterface' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/SegmentedPathInterface.php',
|
||||
'League\\Uri\\Contracts\\Transformable' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/Transformable.php',
|
||||
'League\\Uri\\Contracts\\UriAccess' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/UriAccess.php',
|
||||
'League\\Uri\\Contracts\\UriComponentInterface' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/UriComponentInterface.php',
|
||||
'League\\Uri\\Contracts\\UriException' => __DIR__ . '/..' . '/league/uri-interfaces/Contracts/UriException.php',
|
||||
@@ -828,8 +830,11 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'League\\Uri\\Idna\\Option' => __DIR__ . '/..' . '/league/uri-interfaces/Idna/Option.php',
|
||||
'League\\Uri\\Idna\\Result' => __DIR__ . '/..' . '/league/uri-interfaces/Idna/Result.php',
|
||||
'League\\Uri\\KeyValuePair\\Converter' => __DIR__ . '/..' . '/league/uri-interfaces/KeyValuePair/Converter.php',
|
||||
'League\\Uri\\QueryComposeMode' => __DIR__ . '/..' . '/league/uri-interfaces/QueryComposeMode.php',
|
||||
'League\\Uri\\QueryExtractMode' => __DIR__ . '/..' . '/league/uri-interfaces/QueryExtractMode.php',
|
||||
'League\\Uri\\QueryString' => __DIR__ . '/..' . '/league/uri-interfaces/QueryString.php',
|
||||
'League\\Uri\\SchemeType' => __DIR__ . '/..' . '/league/uri/SchemeType.php',
|
||||
'League\\Uri\\StringCoercionMode' => __DIR__ . '/..' . '/league/uri-interfaces/StringCoercionMode.php',
|
||||
'League\\Uri\\Uri' => __DIR__ . '/..' . '/league/uri/Uri.php',
|
||||
'League\\Uri\\UriComparisonMode' => __DIR__ . '/..' . '/league/uri-interfaces/UriComparisonMode.php',
|
||||
'League\\Uri\\UriInfo' => __DIR__ . '/..' . '/league/uri/UriInfo.php',
|
||||
@@ -2252,6 +2257,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'Zotlabs\\Lib\\Crypto' => __DIR__ . '/../..' . '/Zotlabs/Lib/Crypto.php',
|
||||
'Zotlabs\\Lib\\DB_Upgrade' => __DIR__ . '/../..' . '/Zotlabs/Lib/DB_Upgrade.php',
|
||||
'Zotlabs\\Lib\\DReport' => __DIR__ . '/../..' . '/Zotlabs/Lib/DReport.php',
|
||||
'Zotlabs\\Lib\\DbStats' => __DIR__ . '/../..' . '/Zotlabs/Lib/DbStats.php',
|
||||
'Zotlabs\\Lib\\Enotify' => __DIR__ . '/../..' . '/Zotlabs/Lib/Enotify.php',
|
||||
'Zotlabs\\Lib\\ExtendedZip' => __DIR__ . '/../..' . '/Zotlabs/Lib/ExtendedZip.php',
|
||||
'Zotlabs\\Lib\\Hashpath' => __DIR__ . '/../..' . '/Zotlabs/Lib/Hashpath.php',
|
||||
@@ -2269,12 +2275,15 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'Zotlabs\\Lib\\MarkdownSoap' => __DIR__ . '/../..' . '/Zotlabs/Lib/MarkdownSoap.php',
|
||||
'Zotlabs\\Lib\\MessageFilter' => __DIR__ . '/../..' . '/Zotlabs/Lib/MessageFilter.php',
|
||||
'Zotlabs\\Lib\\Multibase' => __DIR__ . '/../..' . '/Zotlabs/Lib/Multibase.php',
|
||||
'Zotlabs\\Lib\\MySQLDbStats' => __DIR__ . '/../..' . '/Zotlabs/Lib/MySQLDbStats.php',
|
||||
'Zotlabs\\Lib\\ObjCache' => __DIR__ . '/../..' . '/Zotlabs/Lib/ObjCache.php',
|
||||
'Zotlabs\\Lib\\PConfig' => __DIR__ . '/../..' . '/Zotlabs/Lib/PConfig.php',
|
||||
'Zotlabs\\Lib\\Permcat' => __DIR__ . '/../..' . '/Zotlabs/Lib/Permcat.php',
|
||||
'Zotlabs\\Lib\\PermissionDescription' => __DIR__ . '/../..' . '/Zotlabs/Lib/PermissionDescription.php',
|
||||
'Zotlabs\\Lib\\PostgresDbStats' => __DIR__ . '/../..' . '/Zotlabs/Lib/PostgresDbStats.php',
|
||||
'Zotlabs\\Lib\\Queue' => __DIR__ . '/../..' . '/Zotlabs/Lib/Queue.php',
|
||||
'Zotlabs\\Lib\\QueueWorker' => __DIR__ . '/../..' . '/Zotlabs/Lib/QueueWorker.php',
|
||||
'Zotlabs\\Lib\\QueueWorkerStats' => __DIR__ . '/../..' . '/Zotlabs/Lib/QueueWorkerStats.php',
|
||||
'Zotlabs\\Lib\\SConfig' => __DIR__ . '/../..' . '/Zotlabs/Lib/SConfig.php',
|
||||
'Zotlabs\\Lib\\Share' => __DIR__ . '/../..' . '/Zotlabs/Lib/Share.php',
|
||||
'Zotlabs\\Lib\\SvgSanitizer' => __DIR__ . '/../..' . '/Zotlabs/Lib/SvgSanitizer.php',
|
||||
@@ -2415,6 +2424,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
|
||||
'Zotlabs\\Module\\Pconfig' => __DIR__ . '/../..' . '/Zotlabs/Module/Pconfig.php',
|
||||
'Zotlabs\\Module\\Pdledit' => __DIR__ . '/../..' . '/Zotlabs/Module/Pdledit.php',
|
||||
'Zotlabs\\Module\\Pdledit_gui' => __DIR__ . '/../..' . '/Zotlabs/Module/Pdledit_gui.php',
|
||||
'Zotlabs\\Module\\Perfstats' => __DIR__ . '/../..' . '/Zotlabs/Module/Perfstats.php',
|
||||
'Zotlabs\\Module\\Permcat' => __DIR__ . '/../..' . '/Zotlabs/Module/Permcat.php',
|
||||
'Zotlabs\\Module\\Permcats' => __DIR__ . '/../..' . '/Zotlabs/Module/Permcats.php',
|
||||
'Zotlabs\\Module\\Photo' => __DIR__ . '/../..' . '/Zotlabs/Module/Photo.php',
|
||||
|
||||
127
vendor/composer/installed.json
vendored
127
vendor/composer/installed.json
vendored
@@ -155,17 +155,17 @@
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.14.1",
|
||||
"version_normalized": "0.14.1.0",
|
||||
"version": "0.14.8",
|
||||
"version_normalized": "0.14.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/brick/math.git",
|
||||
"reference": "f05858549e5f9d7bb45875a75583240a38a281d0"
|
||||
"reference": "63422359a44b7f06cae63c3b429b59e8efcc0629"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0",
|
||||
"reference": "f05858549e5f9d7bb45875a75583240a38a281d0",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629",
|
||||
"reference": "63422359a44b7f06cae63c3b429b59e8efcc0629",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -176,7 +176,7 @@
|
||||
"phpstan/phpstan": "2.1.22",
|
||||
"phpunit/phpunit": "^11.5"
|
||||
},
|
||||
"time": "2025-11-24T14:40:29+00:00",
|
||||
"time": "2026-02-10T14:33:43+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@@ -206,7 +206,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/brick/math/issues",
|
||||
"source": "https://github.com/brick/math/tree/0.14.1"
|
||||
"source": "https://github.com/brick/math/tree/0.14.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1046,21 +1046,21 @@
|
||||
},
|
||||
{
|
||||
"name": "league/uri",
|
||||
"version": "7.7.0",
|
||||
"version_normalized": "7.7.0.0",
|
||||
"version": "7.8.0",
|
||||
"version_normalized": "7.8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri.git",
|
||||
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807"
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
|
||||
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"league/uri-interfaces": "^7.7",
|
||||
"league/uri-interfaces": "^7.8",
|
||||
"php": "^8.1",
|
||||
"psr/http-factory": "^1"
|
||||
},
|
||||
@@ -1074,14 +1074,14 @@
|
||||
"ext-gmp": "to improve IPV4 host parsing",
|
||||
"ext-intl": "to handle IDN host with the best performance",
|
||||
"ext-uri": "to use the PHP native URI class",
|
||||
"jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain",
|
||||
"league/uri-components": "Needed to easily manipulate URI objects components",
|
||||
"league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP",
|
||||
"jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
|
||||
"league/uri-components": "to provide additional tools to manipulate URI objects components",
|
||||
"league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
|
||||
"php-64bit": "to improve IPV4 host parsing",
|
||||
"rowbot/url": "to handle WHATWG URL",
|
||||
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
|
||||
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
|
||||
},
|
||||
"time": "2025-12-07T16:02:06+00:00",
|
||||
"time": "2026-01-14T17:24:56+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
@@ -1135,7 +1135,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.7.0"
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1147,17 +1147,17 @@
|
||||
},
|
||||
{
|
||||
"name": "league/uri-interfaces",
|
||||
"version": "7.7.0",
|
||||
"version_normalized": "7.7.0.0",
|
||||
"version": "7.8.0",
|
||||
"version_normalized": "7.8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri-interfaces.git",
|
||||
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c"
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
|
||||
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1170,10 +1170,10 @@
|
||||
"ext-gmp": "to improve IPV4 host parsing",
|
||||
"ext-intl": "to handle IDN host with the best performance",
|
||||
"php-64bit": "to improve IPV4 host parsing",
|
||||
"rowbot/url": "to handle WHATWG URL",
|
||||
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
|
||||
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
|
||||
},
|
||||
"time": "2025-12-07T16:03:21+00:00",
|
||||
"time": "2026-01-15T06:54:53+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
@@ -1222,7 +1222,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.7.0"
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1273,23 +1273,22 @@
|
||||
},
|
||||
{
|
||||
"name": "macgirvin/http-message-signer",
|
||||
"version": "v0.2.12",
|
||||
"version_normalized": "0.2.12.0",
|
||||
"version": "v0.2.13",
|
||||
"version_normalized": "0.2.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/macgirvin/HTTP-Message-Signer.git",
|
||||
"reference": "6e5b25a5536576e5046f5b0a7db620b5eb451453"
|
||||
"reference": "b231228c630bf88ac3415b2ba28c057654c9fbea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/macgirvin/HTTP-Message-Signer/zipball/6e5b25a5536576e5046f5b0a7db620b5eb451453",
|
||||
"reference": "6e5b25a5536576e5046f5b0a7db620b5eb451453",
|
||||
"url": "https://api.github.com/repos/macgirvin/HTTP-Message-Signer/zipball/b231228c630bf88ac3415b2ba28c057654c9fbea",
|
||||
"reference": "b231228c630bf88ac3415b2ba28c057654c9fbea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"bakame/http-structured-fields": "^2.0",
|
||||
"ext-openssl": "*",
|
||||
"guzzlehttp/psr7": "^2.0",
|
||||
"paragonie/easy-ecc": "^1.3",
|
||||
"php": "^8.1",
|
||||
"phpseclib/phpseclib": "~3.0",
|
||||
@@ -1297,9 +1296,10 @@
|
||||
"psr/http-message": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/psr7": "^2.8",
|
||||
"phpunit/phpunit": "^10.0"
|
||||
},
|
||||
"time": "2025-12-02T18:48:05+00:00",
|
||||
"time": "2026-02-01T19:54:05+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@@ -1314,7 +1314,7 @@
|
||||
"description": "RFC 9421 HTTP Message Signer and Verifier for PSR-7 requests",
|
||||
"support": {
|
||||
"issues": "https://github.com/macgirvin/HTTP-Message-Signer/issues",
|
||||
"source": "https://github.com/macgirvin/HTTP-Message-Signer/tree/v0.2.12"
|
||||
"source": "https://github.com/macgirvin/HTTP-Message-Signer/tree/v0.2.13"
|
||||
},
|
||||
"install-path": "../macgirvin/http-message-signer"
|
||||
},
|
||||
@@ -1855,21 +1855,22 @@
|
||||
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Text_LanguageDetect",
|
||||
"source": "https://github.com/pear/Text_LanguageDetect"
|
||||
},
|
||||
"abandoned": true,
|
||||
"install-path": "../pear/text_languagedetect"
|
||||
},
|
||||
{
|
||||
"name": "phpseclib/phpseclib",
|
||||
"version": "3.0.48",
|
||||
"version_normalized": "3.0.48.0",
|
||||
"version": "3.0.49",
|
||||
"version_normalized": "3.0.49.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||
"reference": "64065a5679c50acb886e82c07aa139b0f757bb89"
|
||||
"reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/64065a5679c50acb886e82c07aa139b0f757bb89",
|
||||
"reference": "64065a5679c50acb886e82c07aa139b0f757bb89",
|
||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/6233a1e12584754e6b5daa69fe1289b47775c1b9",
|
||||
"reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1887,7 +1888,7 @@
|
||||
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
||||
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
||||
},
|
||||
"time": "2025-12-15T11:51:42+00:00",
|
||||
"time": "2026-01-27T09:17:28+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@@ -1952,7 +1953,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.48"
|
||||
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.49"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3176,17 +3177,17 @@
|
||||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v5.7.0",
|
||||
"version_normalized": "5.7.0.0",
|
||||
"version": "v5.8.0",
|
||||
"version_normalized": "5.8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/smarty-php/smarty.git",
|
||||
"reference": "73da7e90f302175a570662fcb0ba41f57b7a92ab"
|
||||
"reference": "78d259d3b971c59a0cd719c270cc5cbb740c36a7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/73da7e90f302175a570662fcb0ba41f57b7a92ab",
|
||||
"reference": "73da7e90f302175a570662fcb0ba41f57b7a92ab",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/78d259d3b971c59a0cd719c270cc5cbb740c36a7",
|
||||
"reference": "78d259d3b971c59a0cd719c270cc5cbb740c36a7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3197,7 +3198,7 @@
|
||||
"phpunit/phpunit": "^8.5 || ^7.5",
|
||||
"smarty/smarty-lexer": "^4.0.2"
|
||||
},
|
||||
"time": "2025-11-19T21:36:38+00:00",
|
||||
"time": "2026-02-15T14:27:15+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
@@ -3243,7 +3244,7 @@
|
||||
"support": {
|
||||
"forum": "https://github.com/smarty-php/smarty/discussions",
|
||||
"issues": "https://github.com/smarty-php/smarty/issues",
|
||||
"source": "https://github.com/smarty-php/smarty/tree/v5.7.0"
|
||||
"source": "https://github.com/smarty-php/smarty/tree/v5.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3255,17 +3256,17 @@
|
||||
},
|
||||
{
|
||||
"name": "spomky-labs/otphp",
|
||||
"version": "11.4.1",
|
||||
"version_normalized": "11.4.1.0",
|
||||
"version": "11.4.2",
|
||||
"version_normalized": "11.4.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Spomky-Labs/otphp.git",
|
||||
"reference": "126c99b6cbbc18992cf3fba3b87931ba4e312482"
|
||||
"reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/126c99b6cbbc18992cf3fba3b87931ba4e312482",
|
||||
"reference": "126c99b6cbbc18992cf3fba3b87931ba4e312482",
|
||||
"url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad",
|
||||
"reference": "2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3277,7 +3278,7 @@
|
||||
"require-dev": {
|
||||
"symfony/error-handler": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"time": "2026-01-05T13:20:36+00:00",
|
||||
"time": "2026-01-23T10:53:01+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@@ -3312,7 +3313,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Spomky-Labs/otphp/issues",
|
||||
"source": "https://github.com/Spomky-Labs/otphp/tree/11.4.1"
|
||||
"source": "https://github.com/Spomky-Labs/otphp/tree/11.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3454,17 +3455,17 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v7.4.0",
|
||||
"version_normalized": "7.4.0.0",
|
||||
"version": "v7.4.6",
|
||||
"version_normalized": "7.4.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "d551b38811096d0be9c4691d406991b47c0c630a"
|
||||
"reference": "3ebc794fa5315e59fd122561623c2e2e4280538e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d551b38811096d0be9c4691d406991b47c0c630a",
|
||||
"reference": "d551b38811096d0be9c4691d406991b47c0c630a",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e",
|
||||
"reference": "3ebc794fa5315e59fd122561623c2e2e4280538e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3475,7 +3476,7 @@
|
||||
"require-dev": {
|
||||
"symfony/process": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"time": "2025-11-27T13:27:24+00:00",
|
||||
"time": "2026-02-25T16:50:00+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@@ -3503,7 +3504,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.4.0"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.4.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
||||
60
vendor/composer/installed.php
vendored
60
vendor/composer/installed.php
vendored
@@ -1,9 +1,9 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'zotlabs/hubzilla',
|
||||
'pretty_version' => 'dev-10.6RC',
|
||||
'version' => 'dev-10.6RC',
|
||||
'reference' => '38f040f9b528378aa796fc0d72e971cb30bc9bd4',
|
||||
'pretty_version' => 'dev-11.2RC',
|
||||
'version' => 'dev-11.2RC',
|
||||
'reference' => '955ee217e30e12dec86bdcd936ce10abc3ed366a',
|
||||
'type' => 'application',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -29,9 +29,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'brick/math' => array(
|
||||
'pretty_version' => '0.14.1',
|
||||
'version' => '0.14.1.0',
|
||||
'reference' => 'f05858549e5f9d7bb45875a75583240a38a281d0',
|
||||
'pretty_version' => '0.14.8',
|
||||
'version' => '0.14.8.0',
|
||||
'reference' => '63422359a44b7f06cae63c3b429b59e8efcc0629',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../brick/math',
|
||||
'aliases' => array(),
|
||||
@@ -137,18 +137,18 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/uri' => array(
|
||||
'pretty_version' => '7.7.0',
|
||||
'version' => '7.7.0.0',
|
||||
'reference' => '8d587cddee53490f9b82bf203d3a9aa7ea4f9807',
|
||||
'pretty_version' => '7.8.0',
|
||||
'version' => '7.8.0.0',
|
||||
'reference' => '4436c6ec8d458e4244448b069cc572d088230b76',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/uri',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/uri-interfaces' => array(
|
||||
'pretty_version' => '7.7.0',
|
||||
'version' => '7.7.0.0',
|
||||
'reference' => '62ccc1a0435e1c54e10ee6022df28d6c04c2946c',
|
||||
'pretty_version' => '7.8.0',
|
||||
'version' => '7.8.0.0',
|
||||
'reference' => 'c5c5cd056110fc8afaba29fa6b72a43ced42acd4',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/uri-interfaces',
|
||||
'aliases' => array(),
|
||||
@@ -164,9 +164,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'macgirvin/http-message-signer' => array(
|
||||
'pretty_version' => 'v0.2.12',
|
||||
'version' => '0.2.12.0',
|
||||
'reference' => '6e5b25a5536576e5046f5b0a7db620b5eb451453',
|
||||
'pretty_version' => 'v0.2.13',
|
||||
'version' => '0.2.13.0',
|
||||
'reference' => 'b231228c630bf88ac3415b2ba28c057654c9fbea',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../macgirvin/http-message-signer',
|
||||
'aliases' => array(),
|
||||
@@ -245,9 +245,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'phpseclib/phpseclib' => array(
|
||||
'pretty_version' => '3.0.48',
|
||||
'version' => '3.0.48.0',
|
||||
'reference' => '64065a5679c50acb886e82c07aa139b0f757bb89',
|
||||
'pretty_version' => '3.0.49',
|
||||
'version' => '3.0.49.0',
|
||||
'reference' => '6233a1e12584754e6b5daa69fe1289b47775c1b9',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
|
||||
'aliases' => array(),
|
||||
@@ -437,18 +437,18 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'smarty/smarty' => array(
|
||||
'pretty_version' => 'v5.7.0',
|
||||
'version' => '5.7.0.0',
|
||||
'reference' => '73da7e90f302175a570662fcb0ba41f57b7a92ab',
|
||||
'pretty_version' => 'v5.8.0',
|
||||
'version' => '5.8.0.0',
|
||||
'reference' => '78d259d3b971c59a0cd719c270cc5cbb740c36a7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../smarty/smarty',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'spomky-labs/otphp' => array(
|
||||
'pretty_version' => '11.4.1',
|
||||
'version' => '11.4.1.0',
|
||||
'reference' => '126c99b6cbbc18992cf3fba3b87931ba4e312482',
|
||||
'pretty_version' => '11.4.2',
|
||||
'version' => '11.4.2.0',
|
||||
'reference' => '2a1b503fd1c1a5c751ab3c5cd37f2d2d26ab74ad',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../spomky-labs/otphp',
|
||||
'aliases' => array(),
|
||||
@@ -473,9 +473,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/filesystem' => array(
|
||||
'pretty_version' => 'v7.4.0',
|
||||
'version' => '7.4.0.0',
|
||||
'reference' => 'd551b38811096d0be9c4691d406991b47c0c630a',
|
||||
'pretty_version' => 'v7.4.6',
|
||||
'version' => '7.4.6.0',
|
||||
'reference' => '3ebc794fa5315e59fd122561623c2e2e4280538e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/filesystem',
|
||||
'aliases' => array(),
|
||||
@@ -542,9 +542,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'zotlabs/hubzilla' => array(
|
||||
'pretty_version' => 'dev-10.6RC',
|
||||
'version' => 'dev-10.6RC',
|
||||
'reference' => '38f040f9b528378aa796fc0d72e971cb30bc9bd4',
|
||||
'pretty_version' => 'dev-11.2RC',
|
||||
'version' => 'dev-11.2RC',
|
||||
'reference' => '955ee217e30e12dec86bdcd936ce10abc3ed366a',
|
||||
'type' => 'application',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
||||
@@ -13,6 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace League\Uri\Contracts;
|
||||
|
||||
use BackedEnum;
|
||||
use Countable;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
@@ -20,7 +21,14 @@ use League\Uri\Exceptions\SyntaxError;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* @extends IteratorAggregate<string>
|
||||
* @extends IteratorAggregate<int, string>
|
||||
*
|
||||
* @method bool isSubdomainOf(BackedEnum|Stringable|string|null $parentHost) Tells whether the current domain instance is a subdomain of the parent host.
|
||||
* @method bool hasSubdomain(BackedEnum|Stringable|string|null $childHost) Tells whether the submitted host is a subdomain of the current instance.
|
||||
* @method bool isSiblingOf(BackedEnum|Stringable|string|null $siblingHost) Tells whether the submitted host share the same parent domain as the current instance.
|
||||
* @method static commonAncestorWith(BackedEnum|Stringable|string|null $other) Returns the common longest ancestor between 2 domain. The returned domain is empty if no ancestor is found
|
||||
* @method static parentHost() Returns the current parent domain for the current instance. The returned domain is empty if no ancestor is found
|
||||
* @method bool isEmpty() Tells whether the domain contains any label.
|
||||
*/
|
||||
interface DomainHostInterface extends Countable, HostInterface, IteratorAggregate
|
||||
{
|
||||
|
||||
@@ -17,6 +17,8 @@ use Stringable;
|
||||
|
||||
/**
|
||||
* @see https://wicg.github.io/scroll-to-text-fragment/#the-fragment-directive
|
||||
*
|
||||
* @method string toFragmentValue() returns the encoded string representation of the directive as a fragment string
|
||||
*/
|
||||
interface FragmentDirective extends Stringable
|
||||
{
|
||||
@@ -33,7 +35,7 @@ interface FragmentDirective extends Stringable
|
||||
public function value(): ?string;
|
||||
|
||||
/**
|
||||
* The encoded string representation of the fragment.
|
||||
* The encoded string representation of the directive.
|
||||
*/
|
||||
public function toString(): string;
|
||||
|
||||
|
||||
@@ -13,22 +13,40 @@ declare(strict_types=1);
|
||||
|
||||
namespace League\Uri\Contracts;
|
||||
|
||||
use BackedEnum;
|
||||
use Countable;
|
||||
use Deprecated;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
use League\Uri\QueryComposeMode;
|
||||
use League\Uri\StringCoercionMode;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* @extends IteratorAggregate<array{0:string, 1:string|null}>
|
||||
*
|
||||
* @method self withoutPairByKey(string ...$keys) Returns an instance without pairs with the specified keys.
|
||||
* @method self withoutPairByValue(Stringable|string|int|bool|null ...$values) Returns an instance without pairs with the specified values.
|
||||
* @method self withoutPairByKeyValue(string $key, Stringable|string|int|bool|null $value) Returns an instance without pairs with the specified key/value pair
|
||||
* @method bool hasPair(string $key, ?string $value) Tells whether the pair exists in the query.
|
||||
* @method ?string toFormData() Returns the string representation using the applicat/www-form-urlencoded rules
|
||||
* @method ?string toRFC3986() Returns the string representation using RFC3986 rules
|
||||
* @method string|null toFormData() Returns the string representation using the application/www-form-urlencoded rules
|
||||
* @method string|null toRFC3986() Returns the string representation using RFC3986 rules
|
||||
* @method string|null first(string $key) Returns the first value associated with the given name
|
||||
* @method string|null last(string $key) Returns the first value associated with the given name
|
||||
* @method int|null indexOf(string $key, int $nth = 0) Returns the offset of the pair based on its key and its nth occurrence; negative occurrences are supported
|
||||
* @method int|null indexOfValue(?string $value, int $nth = 0) Returns the offset of the pair based on its value and its nth occurrence; negative occurrences are supported
|
||||
* @method array pair(int $offset) Returns the key/value pair at the given numeric offset; negative occurrences are supported
|
||||
* @method int countDistinctKeys() Returns the total number of distinct keys
|
||||
* @method string|null valueAt(int $offset): Returns the value at the given numeric offset; negative occurrences are supported
|
||||
* @method string keyAt(int $offset): Returns the key at the given numeric offset; negative occurrences are supported
|
||||
* @method self normalize() returns the normalized string representation of the component
|
||||
* @method self withoutPairByKey(string ...$keys) Returns an instance without pairs with the specified keys.
|
||||
* @method self withoutPairByValue(array|BackedEnum|Stringable|string|int|bool|null $values, StringCoercionMode $coercionMode = StringCoercionMode::Native) Returns an instance without pairs with the specified values.
|
||||
* @method self withoutPairByKeyValue(string $key, BackedEnum|Stringable|string|int|bool|null $value, StringCoercionMode $coercionMode = StringCoercionMode::Native) Returns an instance without pairs with the specified key/value pair
|
||||
* @method bool hasPair(string $key, ?string $value) Tells whether the pair exists in the query.
|
||||
* @method array getList(string $name) Returns the list associated with the given name or an empty array if it does not exist.
|
||||
* @method bool hasList(string ...$names) Tells whether the parameter list exists in the query.
|
||||
* @method self appendList(string $name, array $values, QueryComposeMode $composeMode = QueryComposeMode::Native) Appends a parameter to the query string
|
||||
* @method self withList(string $name, array $values, QueryComposeMode $composeMode = QueryComposeMode::Native) Adds a new parameter to the query string and remove any previously set values
|
||||
* @method self withoutList(string ...$names) Removes any given list associated with the given names
|
||||
* @method self withoutLists() Removes all lists from the query string
|
||||
* @method self onlyLists() Removes all pairs without a valid PHP's bracket notation
|
||||
*/
|
||||
interface QueryInterface extends Countable, IteratorAggregate, UriComponentInterface
|
||||
{
|
||||
|
||||
27
vendor/league/uri-interfaces/Contracts/Transformable.php
vendored
Normal file
27
vendor/league/uri-interfaces/Contracts/Transformable.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* League.Uri (https://uri.thephpleague.com)
|
||||
*
|
||||
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\Uri\Contracts;
|
||||
|
||||
interface Transformable
|
||||
{
|
||||
/**
|
||||
* Apply a transformation to this instance and return a new instance.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* a new instance of the same type.
|
||||
*
|
||||
* @param callable(static): static $callback
|
||||
*/
|
||||
public function transform(callable $callback): static;
|
||||
}
|
||||
118
vendor/league/uri-interfaces/Encoder.php
vendored
118
vendor/league/uri-interfaces/Encoder.php
vendored
@@ -13,19 +13,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace League\Uri;
|
||||
|
||||
use BackedEnum;
|
||||
use Closure;
|
||||
use Deprecated;
|
||||
use League\Uri\Contracts\UriComponentInterface;
|
||||
use League\Uri\Exceptions\SyntaxError;
|
||||
use League\Uri\IPv6\Converter as IPv6Converter;
|
||||
use SensitiveParameter;
|
||||
use Stringable;
|
||||
use Throwable;
|
||||
|
||||
use function explode;
|
||||
use function filter_var;
|
||||
use function gettype;
|
||||
use function in_array;
|
||||
use function is_scalar;
|
||||
use function preg_match;
|
||||
use function preg_replace_callback;
|
||||
use function rawurldecode;
|
||||
@@ -59,15 +59,19 @@ final class Encoder
|
||||
*
|
||||
* @see https://www.rfc-editor.org/rfc/rfc3986.html#section-2.3
|
||||
*/
|
||||
private const REGEXP_UNRESERVED_CHARACTERS = ',%(2[1-9A-Fa-f]|[3-7][0-9A-Fa-f]|61|62|64|65|66|7[AB]|5F),';
|
||||
private const REGEXP_UNRESERVED_CHARACTERS = ',%(2[DdEe]|3[0-9]|4[1-9A-Fa-f]|5[AaFf]|6[1-9A-Fa-f]|7[0-9A-Ea-e]),';
|
||||
|
||||
/**
|
||||
* Tell whether the user component is correctly encoded.
|
||||
*/
|
||||
public static function isUserEncoded(Stringable|string|null $encoded): bool
|
||||
public static function isUserEncoded(BackedEnum|Stringable|string|null $encoded): bool
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.']+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
if ($encoded instanceof BackedEnum) {
|
||||
$encoded = $encoded->value;
|
||||
}
|
||||
|
||||
return null === $encoded || 1 !== preg_match($pattern, (string) $encoded);
|
||||
}
|
||||
|
||||
@@ -76,11 +80,11 @@ final class Encoder
|
||||
*
|
||||
* All generic delimiters MUST be encoded
|
||||
*/
|
||||
public static function encodeUser(Stringable|string|null $component): ?string
|
||||
public static function encodeUser(BackedEnum|Stringable|string|null $user): ?string
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.']+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
return self::encode($component, $pattern);
|
||||
return self::encode($user, $pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +94,7 @@ final class Encoder
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986.
|
||||
*/
|
||||
public static function normalizeUser(Stringable|string|null $user): ?string
|
||||
public static function normalizeUser(BackedEnum|Stringable|string|null $user): ?string
|
||||
{
|
||||
return self::normalize(self::encodeUser(self::decodeUnreservedCharacters($user)));
|
||||
}
|
||||
@@ -111,10 +115,14 @@ final class Encoder
|
||||
/**
|
||||
* Tell whether the password component is correctly encoded.
|
||||
*/
|
||||
public static function isPasswordEncoded(#[SensitiveParameter] Stringable|string|null $encoded): bool
|
||||
public static function isPasswordEncoded(#[SensitiveParameter] BackedEnum|Stringable|string|null $encoded): bool
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.':]+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
if ($encoded instanceof BackedEnum) {
|
||||
$encoded = $encoded->value;
|
||||
}
|
||||
|
||||
return null === $encoded || 1 !== preg_match($pattern, (string) $encoded);
|
||||
}
|
||||
|
||||
@@ -123,7 +131,7 @@ final class Encoder
|
||||
*
|
||||
* Generic delimiters ":" MUST NOT be encoded
|
||||
*/
|
||||
public static function encodePassword(#[SensitiveParameter] Stringable|string|null $component): ?string
|
||||
public static function encodePassword(#[SensitiveParameter] BackedEnum|Stringable|string|null $component): ?string
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.':]+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
@@ -137,7 +145,7 @@ final class Encoder
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986.
|
||||
*/
|
||||
public static function normalizePassword(#[SensitiveParameter] Stringable|string|null $password): ?string
|
||||
public static function normalizePassword(#[SensitiveParameter] BackedEnum|Stringable|string|null $password): ?string
|
||||
{
|
||||
return self::normalize(self::encodePassword(self::decodeUnreservedCharacters($password)));
|
||||
}
|
||||
@@ -145,24 +153,32 @@ final class Encoder
|
||||
/**
|
||||
* Tell whether the userInfo component is correctly encoded.
|
||||
*/
|
||||
public static function isUserInfoEncoded(#[SensitiveParameter] Stringable|string|null $userInfo): bool
|
||||
public static function isUserInfoEncoded(#[SensitiveParameter] BackedEnum|Stringable|string|null $userInfo): bool
|
||||
{
|
||||
if (null === $userInfo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($userInfo instanceof BackedEnum) {
|
||||
$userInfo = $userInfo->value;
|
||||
}
|
||||
|
||||
[$user, $password] = explode(':', (string) $userInfo, 2) + [1 => null];
|
||||
|
||||
return self::isUserEncoded($user)
|
||||
&& self::isPasswordEncoded($password);
|
||||
}
|
||||
|
||||
public static function encodeUserInfo(#[SensitiveParameter] Stringable|string|null $userInfo): ?string
|
||||
public static function encodeUserInfo(#[SensitiveParameter] BackedEnum|Stringable|string|null $userInfo): ?string
|
||||
{
|
||||
if (null === $userInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($userInfo instanceof BackedEnum) {
|
||||
$userInfo = $userInfo->value;
|
||||
}
|
||||
|
||||
[$user, $password] = explode(':', (string) $userInfo, 2) + [1 => null];
|
||||
$userInfo = self::encodeUser($user);
|
||||
if (null === $password) {
|
||||
@@ -172,12 +188,16 @@ final class Encoder
|
||||
return $userInfo.':'.self::encodePassword($password);
|
||||
}
|
||||
|
||||
public static function normalizeUserInfo(#[SensitiveParameter] Stringable|string|null $userInfo): ?string
|
||||
public static function normalizeUserInfo(#[SensitiveParameter] BackedEnum|Stringable|string|null $userInfo): ?string
|
||||
{
|
||||
if (null === $userInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($userInfo instanceof BackedEnum) {
|
||||
$userInfo = $userInfo->value;
|
||||
}
|
||||
|
||||
[$user, $password] = explode(':', (string) $userInfo, 2) + [1 => null];
|
||||
$userInfo = self::normalizeUser($user);
|
||||
if (null === $password) {
|
||||
@@ -190,7 +210,7 @@ final class Encoder
|
||||
/**
|
||||
* Decodes all the URI component characters.
|
||||
*/
|
||||
public static function decodeAll(Stringable|string|null $component): ?string
|
||||
public static function decodeAll(BackedEnum|Stringable|string|null $component): ?string
|
||||
{
|
||||
return self::decode($component, static fn (array $matches): string => rawurldecode($matches[0]));
|
||||
}
|
||||
@@ -198,7 +218,7 @@ final class Encoder
|
||||
/**
|
||||
* Decodes the URI component without decoding the unreserved characters which are already encoded.
|
||||
*/
|
||||
public static function decodeNecessary(Stringable|string|int|null $component): ?string
|
||||
public static function decodeNecessary(BackedEnum|Stringable|string|int|null $component): ?string
|
||||
{
|
||||
$decoder = static function (array $matches): string {
|
||||
if (1 === preg_match(self::REGEXP_CHARS_PREVENTS_DECODING, $matches[0])) {
|
||||
@@ -214,8 +234,12 @@ final class Encoder
|
||||
/**
|
||||
* Decodes the component unreserved characters.
|
||||
*/
|
||||
public static function decodeUnreservedCharacters(Stringable|string|null $str): ?string
|
||||
public static function decodeUnreservedCharacters(BackedEnum|Stringable|string|null $str): ?string
|
||||
{
|
||||
if ($str instanceof BackedEnum) {
|
||||
$str = $str->value;
|
||||
}
|
||||
|
||||
if (null === $str) {
|
||||
return null;
|
||||
}
|
||||
@@ -230,10 +254,14 @@ final class Encoder
|
||||
/**
|
||||
* Tell whether the path component is correctly encoded.
|
||||
*/
|
||||
public static function isPathEncoded(Stringable|string|null $encoded): bool
|
||||
public static function isPathEncoded(BackedEnum|Stringable|string|null $encoded): bool
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.':@\/]+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
if ($encoded instanceof BackedEnum) {
|
||||
$encoded = $encoded->value;
|
||||
}
|
||||
|
||||
return null === $encoded || 1 !== preg_match($pattern, (string) $encoded);
|
||||
}
|
||||
|
||||
@@ -242,7 +270,7 @@ final class Encoder
|
||||
*
|
||||
* Generic delimiters ":", "@", and "/" MUST NOT be encoded
|
||||
*/
|
||||
public static function encodePath(Stringable|string|null $component): string
|
||||
public static function encodePath(BackedEnum|Stringable|string|null $component): string
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.':@\/]+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
@@ -252,7 +280,7 @@ final class Encoder
|
||||
/**
|
||||
* Decodes the path component while preserving characters that should not be decoded in the context of a full valid URI.
|
||||
*/
|
||||
public static function decodePath(Stringable|string|null $path): ?string
|
||||
public static function decodePath(BackedEnum|Stringable|string|null $path): ?string
|
||||
{
|
||||
$decoder = static function (array $matches): string {
|
||||
$encodedChar = strtoupper($matches[0]);
|
||||
@@ -270,7 +298,7 @@ final class Encoder
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986.
|
||||
*/
|
||||
public static function normalizePath(Stringable|string|null $component): ?string
|
||||
public static function normalizePath(BackedEnum|Stringable|string|null $component): ?string
|
||||
{
|
||||
return self::normalize(self::encodePath(self::decodePath($component)));
|
||||
}
|
||||
@@ -278,9 +306,12 @@ final class Encoder
|
||||
/**
|
||||
* Tell whether the query component is correctly encoded.
|
||||
*/
|
||||
public static function isQueryEncoded(Stringable|string|null $encoded): bool
|
||||
public static function isQueryEncoded(BackedEnum|Stringable|string|null $encoded): bool
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.'\/?%]+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
if ($encoded instanceof BackedEnum) {
|
||||
$encoded = $encoded->value;
|
||||
}
|
||||
|
||||
return null === $encoded || 1 !== preg_match($pattern, (string) $encoded);
|
||||
}
|
||||
@@ -288,7 +319,7 @@ final class Encoder
|
||||
/**
|
||||
* Decodes the query component while preserving characters that should not be decoded in the context of a full valid URI.
|
||||
*/
|
||||
public static function decodeQuery(Stringable|string|null $path): ?string
|
||||
public static function decodeQuery(BackedEnum|Stringable|string|null $path): ?string
|
||||
{
|
||||
$decoder = static function (array $matches): string {
|
||||
$encodedChar = strtoupper($matches[0]);
|
||||
@@ -306,7 +337,7 @@ final class Encoder
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986.
|
||||
*/
|
||||
public static function normalizeQuery(Stringable|string|null $query): ?string
|
||||
public static function normalizeQuery(BackedEnum|Stringable|string|null $query): ?string
|
||||
{
|
||||
return self::normalize(self::encodeQueryOrFragment(self::decodeQuery($query)));
|
||||
}
|
||||
@@ -314,17 +345,21 @@ final class Encoder
|
||||
/**
|
||||
* Tell whether the query component is correctly encoded.
|
||||
*/
|
||||
public static function isFragmentEncoded(Stringable|string|null $encoded): bool
|
||||
public static function isFragmentEncoded(BackedEnum|Stringable|string|null $encoded): bool
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.':@\/?%]|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
if ($encoded instanceof BackedEnum) {
|
||||
$encoded = $encoded->value;
|
||||
}
|
||||
|
||||
return null === $encoded || 1 !== preg_match($pattern, (string) $encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the fragment component while preserving characters that should not be decoded in the context of a full valid URI.
|
||||
*/
|
||||
public static function decodeFragment(Stringable|string|null $path): ?string
|
||||
public static function decodeFragment(BackedEnum|Stringable|string|null $path): ?string
|
||||
{
|
||||
return self::decode($path, static fn (array $matches): string => '%20' === $matches[0] ? $matches[0] : rawurldecode($matches[0]));
|
||||
}
|
||||
@@ -336,7 +371,7 @@ final class Encoder
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986.
|
||||
*/
|
||||
public static function normalizeFragment(Stringable|string|null $fragment): ?string
|
||||
public static function normalizeFragment(BackedEnum|Stringable|string|null $fragment): ?string
|
||||
{
|
||||
return self::normalize(self::encodeQueryOrFragment(self::decodeFragment($fragment)));
|
||||
}
|
||||
@@ -350,8 +385,12 @@ final class Encoder
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986.
|
||||
*/
|
||||
public static function normalizeHost(Stringable|string|null $host): ?string
|
||||
public static function normalizeHost(BackedEnum|Stringable|string|null $host): ?string
|
||||
{
|
||||
if ($host instanceof BackedEnum) {
|
||||
$host = (string) $host->value;
|
||||
}
|
||||
|
||||
if ($host instanceof Stringable) {
|
||||
$host = (string) $host;
|
||||
}
|
||||
@@ -378,7 +417,7 @@ final class Encoder
|
||||
*
|
||||
* Generic delimiters ":", "@", "?", and "/" MUST NOT be encoded
|
||||
*/
|
||||
public static function encodeQueryOrFragment(Stringable|string|null $component): ?string
|
||||
public static function encodeQueryOrFragment(BackedEnum|Stringable|string|null $component): ?string
|
||||
{
|
||||
static $pattern = '/[^'.self::REGEXP_PART_UNRESERVED.self::REGEXP_PART_SUBDELIM.':@\/?]+|'.self::REGEXP_PART_ENCODED.'/';
|
||||
|
||||
@@ -400,21 +439,20 @@ final class Encoder
|
||||
|
||||
private static function filterComponent(mixed $component): ?string
|
||||
{
|
||||
return match (true) {
|
||||
true === $component => '1',
|
||||
false === $component => '0',
|
||||
$component instanceof UriComponentInterface => $component->value(),
|
||||
$component instanceof Stringable,
|
||||
is_scalar($component) => (string) $component,
|
||||
null === $component => null,
|
||||
default => throw new SyntaxError(sprintf('The component must be a scalar value `%s` given.', gettype($component))),
|
||||
};
|
||||
try {
|
||||
return StringCoercionMode::Native->coerce($component);
|
||||
} catch (Throwable $exception) {
|
||||
throw new SyntaxError(
|
||||
sprintf('The component must be a scalar value `%s` given.', gettype($component)),
|
||||
previous: $exception
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the URI component characters using a regular expression to find which characters need encoding.
|
||||
*/
|
||||
private static function encode(Stringable|string|int|bool|null $component, string $pattern): ?string
|
||||
private static function encode(BackedEnum|Stringable|string|int|bool|null $component, string $pattern): ?string
|
||||
{
|
||||
$component = self::filterComponent($component);
|
||||
if (null === $component || '' === $component) {
|
||||
@@ -431,7 +469,7 @@ final class Encoder
|
||||
/**
|
||||
* Decodes the URI component characters using a closure.
|
||||
*/
|
||||
private static function decode(Stringable|string|int|null $component, Closure $decoder): ?string
|
||||
private static function decode(BackedEnum|Stringable|string|int|null $component, Closure $decoder): ?string
|
||||
{
|
||||
$component = self::filterComponent($component);
|
||||
if (null === $component || '' === $component) {
|
||||
@@ -461,7 +499,7 @@ final class Encoder
|
||||
* Create a new instance from the environment.
|
||||
*/
|
||||
#[Deprecated(message:'use League\Uri\Encoder::decodeNecessary() instead', since:'league/uri:7.6.0')]
|
||||
public static function decodePartial(Stringable|string|int|null $component): ?string
|
||||
public static function decodePartial(BackedEnum|Stringable|string|int|null $component): ?string
|
||||
{
|
||||
return self::decodeNecessary($component);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace League\Uri\Exceptions;
|
||||
|
||||
use BackedEnum;
|
||||
use League\Uri\Idna\Error;
|
||||
use League\Uri\Idna\Result;
|
||||
use Stringable;
|
||||
@@ -27,10 +28,14 @@ final class ConversionFailed extends SyntaxError
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
public static function dueToIdnError(Stringable|string $host, Result $result): self
|
||||
public static function dueToIdnError(BackedEnum|Stringable|string $host, Result $result): self
|
||||
{
|
||||
$reasons = array_map(fn (Error $error): string => $error->description(), $result->errors());
|
||||
|
||||
if ($host instanceof BackedEnum) {
|
||||
$host = (string) $host->value;
|
||||
}
|
||||
|
||||
return new self('Host `'.$host.'` is invalid: '.implode('; ', $reasons).'.', (string) $host, $result);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ final class FeatureDetection
|
||||
$isSupported = $isSupported ?? (function_exists('\idn_to_ascii') && defined('\INTL_IDNA_VARIANT_UTS46'));
|
||||
|
||||
$isSupported || throw new MissingFeature('Support for IDN host requires the `intl` extension for best performance or run "composer require symfony/polyfill-intl-idn" to install a polyfill.');
|
||||
|
||||
}
|
||||
|
||||
public static function supportsIPv4Conversion(): void
|
||||
|
||||
11
vendor/league/uri-interfaces/HostRecord.php
vendored
11
vendor/league/uri-interfaces/HostRecord.php
vendored
@@ -13,6 +13,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace League\Uri;
|
||||
|
||||
use BackedEnum;
|
||||
use Exception;
|
||||
use JsonSerializable;
|
||||
use League\Uri\Contracts\UriComponentInterface;
|
||||
@@ -223,7 +224,7 @@ final class HostRecord implements JsonSerializable
|
||||
return $this->ipValue;
|
||||
}
|
||||
|
||||
public static function isValid(Stringable|string|null $host): bool
|
||||
public static function isValid(BackedEnum|Stringable|string|null $host): bool
|
||||
{
|
||||
try {
|
||||
HostRecord::from($host);
|
||||
@@ -287,8 +288,12 @@ final class HostRecord implements JsonSerializable
|
||||
/**
|
||||
* @throws SyntaxError
|
||||
*/
|
||||
public static function from(Stringable|string|null $host): self
|
||||
public static function from(BackedEnum|Stringable|string|null $host): self
|
||||
{
|
||||
if ($host instanceof BackedEnum) {
|
||||
$host = $host->value;
|
||||
}
|
||||
|
||||
if ($host instanceof UriComponentInterface) {
|
||||
$host = $host->value();
|
||||
}
|
||||
@@ -434,7 +439,7 @@ final class HostRecord implements JsonSerializable
|
||||
$record = self::from($properties['host'] ?? throw new Exception('The `host` property is missing from the serialized object.'));
|
||||
//if the Host computed value are already cache this avoid recomputing them
|
||||
foreach (get_object_vars($record) as $prop => $value) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
/* @phpstan-ignore-next-line */
|
||||
$this->{$prop} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user