Merge remote-tracking branch 'upstream/develop' into baseurl
commit
24d2d0481a
45
database.sql
45
database.sql
|
@ -1,6 +1,6 @@
|
|||
-- ------------------------------------------
|
||||
-- Friendica 2023.09-dev (Giant Rhubarb)
|
||||
-- DB_UPDATE_VERSION 1524
|
||||
-- DB_UPDATE_VERSION 1529
|
||||
-- ------------------------------------------
|
||||
|
||||
|
||||
|
@ -101,6 +101,19 @@ CREATE TABLE IF NOT EXISTS `user` (
|
|||
FOREIGN KEY (`parent-uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
|
||||
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='The local users';
|
||||
|
||||
--
|
||||
-- TABLE user-gserver
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS `user-gserver` (
|
||||
`uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Owner User id',
|
||||
`gsid` int unsigned NOT NULL DEFAULT 0 COMMENT 'Gserver id',
|
||||
`ignored` boolean NOT NULL DEFAULT '0' COMMENT 'server accounts are ignored for the user',
|
||||
PRIMARY KEY(`uid`,`gsid`),
|
||||
INDEX `gsid` (`gsid`),
|
||||
FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE,
|
||||
FOREIGN KEY (`gsid`) REFERENCES `gserver` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
|
||||
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='User settings about remote servers';
|
||||
|
||||
--
|
||||
-- TABLE item-uri
|
||||
--
|
||||
|
@ -160,8 +173,8 @@ CREATE TABLE IF NOT EXISTS `contact` (
|
|||
`archive` boolean NOT NULL DEFAULT '0' COMMENT '',
|
||||
`unsearchable` boolean NOT NULL DEFAULT '0' COMMENT 'Contact prefers to not be searchable',
|
||||
`sensitive` boolean NOT NULL DEFAULT '0' COMMENT 'Contact posts sensitive content',
|
||||
`baseurl` varbinary(383) DEFAULT '' COMMENT 'baseurl of the contact',
|
||||
`gsid` int unsigned COMMENT 'Global Server ID',
|
||||
`baseurl` varbinary(383) DEFAULT '' COMMENT 'baseurl of the contact from the gserver record, can be missing',
|
||||
`gsid` int unsigned COMMENT 'Global Server ID, can be missing',
|
||||
`bd` date NOT NULL DEFAULT '0001-01-01' COMMENT '',
|
||||
`reason` text COMMENT '',
|
||||
`self` boolean NOT NULL DEFAULT '0' COMMENT '1 if the contact is the user him/her self',
|
||||
|
@ -1586,7 +1599,7 @@ CREATE TABLE IF NOT EXISTS `profile` (
|
|||
`profile-name` varchar(255) COMMENT 'Deprecated',
|
||||
`is-default` boolean COMMENT 'Deprecated',
|
||||
`hide-friends` boolean NOT NULL DEFAULT '0' COMMENT 'Hide friend list from viewers of this profile',
|
||||
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`name` varchar(255) NOT NULL DEFAULT '' COMMENT 'Unused in favor of user.username',
|
||||
`pdesc` varchar(255) COMMENT 'Deprecated',
|
||||
`dob` varchar(32) NOT NULL DEFAULT '0000-00-00' COMMENT 'Day of birth',
|
||||
`address` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
|
@ -2032,6 +2045,7 @@ CREATE VIEW `post-user-view` AS SELECT
|
|||
`author`.`hidden` AS `author-hidden`,
|
||||
`author`.`updated` AS `author-updated`,
|
||||
`author`.`gsid` AS `author-gsid`,
|
||||
`author`.`baseurl` AS `author-baseurl`,
|
||||
`post-user`.`owner-id` AS `owner-id`,
|
||||
`owner`.`uri-id` AS `owner-uri-id`,
|
||||
`owner`.`url` AS `owner-link`,
|
||||
|
@ -2044,6 +2058,7 @@ CREATE VIEW `post-user-view` AS SELECT
|
|||
`owner`.`blocked` AS `owner-blocked`,
|
||||
`owner`.`hidden` AS `owner-hidden`,
|
||||
`owner`.`updated` AS `owner-updated`,
|
||||
`owner`.`gsid` AS `owner-gsid`,
|
||||
`owner`.`contact-type` AS `owner-contact-type`,
|
||||
`post-user`.`causer-id` AS `causer-id`,
|
||||
`causer`.`uri-id` AS `causer-uri-id`,
|
||||
|
@ -2056,6 +2071,7 @@ CREATE VIEW `post-user-view` AS SELECT
|
|||
`causer`.`network` AS `causer-network`,
|
||||
`causer`.`blocked` AS `causer-blocked`,
|
||||
`causer`.`hidden` AS `causer-hidden`,
|
||||
`causer`.`gsid` AS `causer-gsid`,
|
||||
`causer`.`contact-type` AS `causer-contact-type`,
|
||||
`post-delivery-data`.`postopts` AS `postopts`,
|
||||
`post-delivery-data`.`inform` AS `inform`,
|
||||
|
@ -2189,6 +2205,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT
|
|||
`contact`.`pending` AS `contact-pending`,
|
||||
`contact`.`rel` AS `contact-rel`,
|
||||
`contact`.`uid` AS `contact-uid`,
|
||||
`contact`.`gsid` AS `contact-gsid`,
|
||||
`contact`.`contact-type` AS `contact-contact-type`,
|
||||
IF (`post-user`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`) AS `writable`,
|
||||
`contact`.`self` AS `self`,
|
||||
|
@ -2224,6 +2241,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT
|
|||
`owner`.`blocked` AS `owner-blocked`,
|
||||
`owner`.`hidden` AS `owner-hidden`,
|
||||
`owner`.`updated` AS `owner-updated`,
|
||||
`owner`.`gsid` AS `owner-gsid`,
|
||||
`owner`.`contact-type` AS `owner-contact-type`,
|
||||
`post-thread-user`.`causer-id` AS `causer-id`,
|
||||
`causer`.`uri-id` AS `causer-uri-id`,
|
||||
|
@ -2236,6 +2254,7 @@ CREATE VIEW `post-thread-user-view` AS SELECT
|
|||
`causer`.`network` AS `causer-network`,
|
||||
`causer`.`blocked` AS `causer-blocked`,
|
||||
`causer`.`hidden` AS `causer-hidden`,
|
||||
`causer`.`gsid` AS `causer-gsid`,
|
||||
`causer`.`contact-type` AS `causer-contact-type`,
|
||||
`post-delivery-data`.`postopts` AS `postopts`,
|
||||
`post-delivery-data`.`inform` AS `inform`,
|
||||
|
@ -2391,6 +2410,7 @@ CREATE VIEW `post-view` AS SELECT
|
|||
`owner`.`hidden` AS `owner-hidden`,
|
||||
`owner`.`updated` AS `owner-updated`,
|
||||
`owner`.`contact-type` AS `owner-contact-type`,
|
||||
`owner`.`gsid` AS `owner-gsid`,
|
||||
`post`.`causer-id` AS `causer-id`,
|
||||
`causer`.`uri-id` AS `causer-uri-id`,
|
||||
`causer`.`url` AS `causer-link`,
|
||||
|
@ -2403,6 +2423,7 @@ CREATE VIEW `post-view` AS SELECT
|
|||
`causer`.`blocked` AS `causer-blocked`,
|
||||
`causer`.`hidden` AS `causer-hidden`,
|
||||
`causer`.`contact-type` AS `causer-contact-type`,
|
||||
`causer`.`gsid` AS `causer-gsid`,
|
||||
`post-question`.`id` AS `question-id`,
|
||||
`post-question`.`multiple` AS `question-multiple`,
|
||||
`post-question`.`voters` AS `question-voters`,
|
||||
|
@ -2533,6 +2554,7 @@ CREATE VIEW `post-thread-view` AS SELECT
|
|||
`owner`.`blocked` AS `owner-blocked`,
|
||||
`owner`.`hidden` AS `owner-hidden`,
|
||||
`owner`.`updated` AS `owner-updated`,
|
||||
`owner`.`gsid` AS `owner-gsid`,
|
||||
`owner`.`contact-type` AS `owner-contact-type`,
|
||||
`post-thread`.`causer-id` AS `causer-id`,
|
||||
`causer`.`uri-id` AS `causer-uri-id`,
|
||||
|
@ -2545,6 +2567,7 @@ CREATE VIEW `post-thread-view` AS SELECT
|
|||
`causer`.`network` AS `causer-network`,
|
||||
`causer`.`blocked` AS `causer-blocked`,
|
||||
`causer`.`hidden` AS `causer-hidden`,
|
||||
`causer`.`gsid` AS `causer-gsid`,
|
||||
`causer`.`contact-type` AS `causer-contact-type`,
|
||||
`post-question`.`id` AS `question-id`,
|
||||
`post-question`.`multiple` AS `question-multiple`,
|
||||
|
@ -2666,18 +2689,16 @@ CREATE VIEW `network-item-view` AS SELECT
|
|||
`post-user`.`contact-id` AS `contact-id`,
|
||||
`ownercontact`.`contact-type` AS `contact-type`
|
||||
FROM `post-user`
|
||||
INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid`
|
||||
INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid`
|
||||
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id`
|
||||
STRAIGHT_JOIN `contact` AS `authorcontact` ON `authorcontact`.`id` = `post-thread-user`.`author-id`
|
||||
STRAIGHT_JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread-user`.`owner-id`
|
||||
LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-thread-user`.`uid` AND `author`.`cid` = `post-thread-user`.`author-id`
|
||||
LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-thread-user`.`uid` AND `owner`.`cid` = `post-thread-user`.`owner-id`
|
||||
WHERE `post-user`.`visible` AND NOT `post-user`.`deleted`
|
||||
AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
|
||||
AND (`post-user`.`hidden` IS NULL OR NOT `post-user`.`hidden`)
|
||||
AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked`
|
||||
AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
|
||||
AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`);
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`);
|
||||
|
||||
--
|
||||
-- VIEW network-thread-view
|
||||
|
@ -2700,14 +2721,12 @@ CREATE VIEW `network-thread-view` AS SELECT
|
|||
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id`
|
||||
STRAIGHT_JOIN `contact` AS `authorcontact` ON `authorcontact`.`id` = `post-thread-user`.`author-id`
|
||||
STRAIGHT_JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread-user`.`owner-id`
|
||||
LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-thread-user`.`uid` AND `author`.`cid` = `post-thread-user`.`author-id`
|
||||
LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-thread-user`.`uid` AND `owner`.`cid` = `post-thread-user`.`owner-id`
|
||||
WHERE `post-user`.`visible` AND NOT `post-user`.`deleted`
|
||||
AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
|
||||
AND (`post-thread-user`.`hidden` IS NULL OR NOT `post-thread-user`.`hidden`)
|
||||
AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked`
|
||||
AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
|
||||
AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`);
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`);
|
||||
|
||||
--
|
||||
-- VIEW owner-view
|
||||
|
|
|
@ -10,8 +10,10 @@ If you installed Friendica in the ``path/to/friendica`` folder:
|
|||
1. Unpack the new Friendica archive in ``path/to/friendica_new``.
|
||||
2. Copy the following items from ``path/to/friendica`` to ``path/to/friendica_new``:
|
||||
* ``config/local.config.php``
|
||||
* ``proxy/``
|
||||
The following items only need to be copied if they are located inside your friendica path:
|
||||
* ``proxy/``
|
||||
* ``.htaccess`` if using Apache web server
|
||||
|
||||
The following items only need to be copied if they are located inside your friendica path:
|
||||
* your storage folder as set in **Admin -> Site -> File Upload -> Storage base path**
|
||||
* your item cache as set in **Admin -> Site -> Performance -> Path to item cache**
|
||||
* your temp folder as set in **Admin -> Site -> Advanced -> Temp path**
|
||||
|
|
|
@ -86,6 +86,7 @@ Database Tables
|
|||
| [tag](help/database/db_tag) | tags and mentions |
|
||||
| [user](help/database/db_user) | The local users |
|
||||
| [user-contact](help/database/db_user-contact) | User specific public contact data |
|
||||
| [user-gserver](help/database/db_user-gserver) | User settings about remote servers |
|
||||
| [userd](help/database/db_userd) | Deleted usernames |
|
||||
| [verb](help/database/db_verb) | Activity Verbs |
|
||||
| [worker-ipc](help/database/db_worker-ipc) | Inter process communication between the frontend and the worker |
|
||||
|
|
|
@ -51,8 +51,8 @@ Fields
|
|||
| archive | | boolean | NO | | 0 | |
|
||||
| unsearchable | Contact prefers to not be searchable | boolean | NO | | 0 | |
|
||||
| sensitive | Contact posts sensitive content | boolean | NO | | 0 | |
|
||||
| baseurl | baseurl of the contact | varbinary(383) | YES | | | |
|
||||
| gsid | Global Server ID | int unsigned | YES | | NULL | |
|
||||
| baseurl | baseurl of the contact from the gserver record, can be missing | varbinary(383) | YES | | | |
|
||||
| gsid | Global Server ID, can be missing | int unsigned | YES | | NULL | |
|
||||
| bd | | date | NO | | 0001-01-01 | |
|
||||
| reason | | text | YES | | NULL | |
|
||||
| self | 1 if the contact is the user him/her self | boolean | NO | | 0 | |
|
||||
|
|
|
@ -13,7 +13,7 @@ Fields
|
|||
| profile-name | Deprecated | varchar(255) | YES | | NULL | |
|
||||
| is-default | Deprecated | boolean | YES | | NULL | |
|
||||
| hide-friends | Hide friend list from viewers of this profile | boolean | NO | | 0 | |
|
||||
| name | | varchar(255) | NO | | | |
|
||||
| name | Unused in favor of user.username | varchar(255) | NO | | | |
|
||||
| pdesc | Deprecated | varchar(255) | YES | | NULL | |
|
||||
| dob | Day of birth | varchar(32) | NO | | 0000-00-00 | |
|
||||
| address | | varchar(255) | NO | | | |
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
Table user-gserver
|
||||
===========
|
||||
|
||||
User settings about remote servers
|
||||
|
||||
Fields
|
||||
------
|
||||
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ------- | ---------------------------------------- | ------------------ | ---- | --- | ------- | ----- |
|
||||
| uid | Owner User id | mediumint unsigned | NO | | 0 | |
|
||||
| gsid | Gserver id | int unsigned | NO | | 0 | |
|
||||
| ignored | server accounts are ignored for the user | boolean | NO | | 0 | |
|
||||
|
||||
Indexes
|
||||
------------
|
||||
|
||||
| Name | Fields |
|
||||
| ------- | --------- |
|
||||
| PRIMARY | uid, gsid |
|
||||
| gsid | gsid |
|
||||
|
||||
Foreign Keys
|
||||
------------
|
||||
|
||||
| Field | Target Table | Target Field |
|
||||
|-------|--------------|--------------|
|
||||
| uid | [user](help/database/db_user) | uid |
|
||||
| gsid | [gserver](help/database/db_gserver) | id |
|
||||
|
||||
Return to [database documentation](help/database)
|
|
@ -245,10 +245,12 @@ class Page implements ArrayAccess
|
|||
*/
|
||||
$this->page['htmlhead'] = Renderer::replaceMacros($tpl, [
|
||||
'$l10n' => [
|
||||
'delitem' => $l10n->t('Delete this item?'),
|
||||
'blockAuthor' => $l10n->t('Block this author? They won\'t be able to follow you nor see your public posts, and you won\'t be able to see their posts and their notifications.'),
|
||||
'ignoreAuthor' => $l10n->t('Ignore this author? You won\'t be able to see their posts and their notifications.'),
|
||||
'collapseAuthor' => $l10n->t('Collapse this author\'s posts?'),
|
||||
'delitem' => $l10n->t('Delete this item?'),
|
||||
'blockAuthor' => $l10n->t("Block this author? They won't be able to follow you nor see your public posts, and you won't be able to see their posts and their notifications."),
|
||||
'ignoreAuthor' => $l10n->t("Ignore this author? You won't be able to see their posts and their notifications."),
|
||||
'collapseAuthor' => $l10n->t("Collapse this author's posts?"),
|
||||
'ignoreServer' => $l10n->t("Ignore this author's server?"),
|
||||
'ignoreServerDesc' => $l10n->t("You won't see any content from this server including reshares in your Network page, the community pages and individual conversations."),
|
||||
|
||||
'likeError' => $l10n->t('Like not successful'),
|
||||
'dislikeError' => $l10n->t('Dislike not successful'),
|
||||
|
|
|
@ -38,6 +38,7 @@ use Friendica\Database\DBA;
|
|||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Item as ItemModel;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Model\Post\Category;
|
||||
use Friendica\Model\Tag;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Model\Verb;
|
||||
|
@ -45,6 +46,8 @@ use Friendica\Network\HTTPException\InternalServerErrorException;
|
|||
use Friendica\Object\Post as PostObject;
|
||||
use Friendica\Object\Thread;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\User\Settings\Entity\UserGServer;
|
||||
use Friendica\User\Settings\Repository;
|
||||
use Friendica\Util\Crypto;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Profiler;
|
||||
|
@ -90,22 +93,25 @@ class Conversation
|
|||
private $mode;
|
||||
/** @var IHandleUserSessions */
|
||||
private $session;
|
||||
/** @var Repository\UserGServer */
|
||||
private $userGServer;
|
||||
|
||||
public function __construct(LoggerInterface $logger, Profiler $profiler, Activity $activity, L10n $l10n, Item $item, Arguments $args, BaseURL $baseURL, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, App\Page $page, App\Mode $mode, App $app, IHandleUserSessions $session)
|
||||
public function __construct(Repository\UserGServer $userGServer, LoggerInterface $logger, Profiler $profiler, Activity $activity, L10n $l10n, Item $item, Arguments $args, BaseURL $baseURL, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, App\Page $page, App\Mode $mode, App $app, IHandleUserSessions $session)
|
||||
{
|
||||
$this->activity = $activity;
|
||||
$this->item = $item;
|
||||
$this->config = $config;
|
||||
$this->mode = $mode;
|
||||
$this->baseURL = $baseURL;
|
||||
$this->profiler = $profiler;
|
||||
$this->logger = $logger;
|
||||
$this->l10n = $l10n;
|
||||
$this->args = $args;
|
||||
$this->pConfig = $pConfig;
|
||||
$this->page = $page;
|
||||
$this->app = $app;
|
||||
$this->session = $session;
|
||||
$this->activity = $activity;
|
||||
$this->item = $item;
|
||||
$this->config = $config;
|
||||
$this->mode = $mode;
|
||||
$this->baseURL = $baseURL;
|
||||
$this->profiler = $profiler;
|
||||
$this->logger = $logger;
|
||||
$this->l10n = $l10n;
|
||||
$this->args = $args;
|
||||
$this->pConfig = $pConfig;
|
||||
$this->page = $page;
|
||||
$this->app = $app;
|
||||
$this->session = $session;
|
||||
$this->userGServer = $userGServer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -459,8 +465,14 @@ class Conversation
|
|||
|
||||
$live_update_div = '';
|
||||
|
||||
$userGservers = $this->userGServer->listIgnoredByUser($this->session->getLocalUserId());
|
||||
|
||||
$ignoredGsids = array_map(function (UserGServer $userGServer) {
|
||||
return $userGServer->gsid;
|
||||
}, $userGservers->getArrayCopy());
|
||||
|
||||
if ($mode === self::MODE_NETWORK) {
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode);
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids);
|
||||
if (!$update) {
|
||||
/*
|
||||
* The special div is needed for liveUpdate to kick in for this page.
|
||||
|
@ -486,7 +498,7 @@ class Conversation
|
|||
. "'; </script>\r\n";
|
||||
}
|
||||
} elseif ($mode === self::MODE_PROFILE) {
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode);
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids);
|
||||
|
||||
if (!$update) {
|
||||
$tab = !empty($_GET['tab']) ? trim($_GET['tab']) : 'posts';
|
||||
|
@ -511,7 +523,7 @@ class Conversation
|
|||
. "; var netargs = '?f='; </script>\r\n";
|
||||
}
|
||||
} elseif ($mode === self::MODE_DISPLAY) {
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode);
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids);
|
||||
|
||||
if (!$update) {
|
||||
$live_update_div = '<div id="live-display"></div>' . "\r\n"
|
||||
|
@ -519,7 +531,7 @@ class Conversation
|
|||
. "</script>";
|
||||
}
|
||||
} elseif ($mode === self::MODE_COMMUNITY) {
|
||||
$items = $this->addChildren($items, true, $order, $uid, $mode);
|
||||
$items = $this->addChildren($items, true, $order, $uid, $mode, $ignoredGsids);
|
||||
|
||||
if (!$update) {
|
||||
$live_update_div = '<div id="live-community"></div>' . "\r\n"
|
||||
|
@ -530,7 +542,7 @@ class Conversation
|
|||
. "'; </script>\r\n";
|
||||
}
|
||||
} elseif ($mode === self::MODE_CONTACTS) {
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode);
|
||||
$items = $this->addChildren($items, false, $order, $uid, $mode, $ignoredGsids);
|
||||
|
||||
if (!$update) {
|
||||
$live_update_div = '<div id="live-contact"></div>' . "\r\n"
|
||||
|
@ -743,7 +755,12 @@ class Conversation
|
|||
$row['direction'] = ['direction' => 6, 'title' => $this->l10n->t('You are following %s.', $row['causer-name'] ?: $row['author-name'])];
|
||||
break;
|
||||
case ItemModel::PR_TAG:
|
||||
$row['direction'] = ['direction' => 4, 'title' => $this->l10n->t('You subscribed to one or more tags in this post.')];
|
||||
$tags = Category::getArrayByURIId($row['uri-id'], $row['uid'], Category::SUBCRIPTION);
|
||||
if (!empty($tags)) {
|
||||
$row['direction'] = ['direction' => 4, 'title' => $this->l10n->t('You subscribed to %s.', implode(', ', $tags))];
|
||||
} else {
|
||||
$row['direction'] = ['direction' => 4, 'title' => $this->l10n->t('You subscribed to one or more tags in this post.')];
|
||||
}
|
||||
break;
|
||||
case ItemModel::PR_ANNOUNCEMENT:
|
||||
if (!empty($row['causer-id']) && $this->pConfig->get($this->session->getLocalUserId(), 'system', 'display_resharer')) {
|
||||
|
@ -812,13 +829,14 @@ class Conversation
|
|||
*
|
||||
* @param array $parents Parent items
|
||||
* @param bool $block_authors
|
||||
* @param bool $order
|
||||
* @param string $order Either "received" or "commented"
|
||||
* @param int $uid
|
||||
* @param string $mode
|
||||
* @param string $mode One of self::MODE_*
|
||||
* @param array $ignoredGsids List of ids of servers ignored by the user
|
||||
* @return array items with parents and comments
|
||||
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
|
||||
* @throws InternalServerErrorException
|
||||
*/
|
||||
private function addChildren(array $parents, bool $block_authors, string $order, int $uid, string $mode): array
|
||||
private function addChildren(array $parents, bool $block_authors, string $order, int $uid, string $mode, array $ignoredGsids = []): array
|
||||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
if (count($parents) > 1) {
|
||||
|
@ -900,6 +918,13 @@ class Conversation
|
|||
continue;
|
||||
}
|
||||
|
||||
if (in_array($row['author-gsid'], $ignoredGsids)
|
||||
|| in_array($row['owner-gsid'], $ignoredGsids)
|
||||
|| in_array($row['causer-gsid'], $ignoredGsids)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (($mode != self::MODE_CONTACTS) && !$row['origin']) {
|
||||
$row['featured'] = false;
|
||||
}
|
||||
|
@ -1462,6 +1487,7 @@ class Conversation
|
|||
'received' => $item['received'],
|
||||
'created_date' => $item['created'],
|
||||
'uriid' => $item['uri-id'],
|
||||
'author_gsid' => $item['author-gsid'],
|
||||
'network' => $item['network'],
|
||||
'network_name' => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network'], $item['author-gsid']),
|
||||
'network_icon' => ContactSelector::networkToIcon($item['network'], $item['author-link'], $item['author-gsid']),
|
||||
|
|
|
@ -34,15 +34,16 @@ use Friendica\Core\Protocol;
|
|||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Attach;
|
||||
use Friendica\Model\Circle;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Conversation;
|
||||
use Friendica\Model\FileTag;
|
||||
use Friendica\Model\Circle;
|
||||
use Friendica\Model\Item as ItemModel;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Model\Tag;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Model\Tag;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Object\EMail\ItemCCEMail;
|
||||
|
@ -54,6 +55,7 @@ use Friendica\Util\ParseUrl;
|
|||
use Friendica\Util\Profiler;
|
||||
use Friendica\Util\Proxy;
|
||||
use Friendica\Util\XML;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
||||
/**
|
||||
* A content helper class for displaying items
|
||||
|
@ -367,7 +369,7 @@ class Item
|
|||
{
|
||||
$this->profiler->startRecording('rendering');
|
||||
$sub_link = $contact_url = $pm_url = $status_link = '';
|
||||
$photos_link = $posts_link = $block_link = $ignore_link = '';
|
||||
$photos_link = $posts_link = $block_link = $ignore_link = $collapse_link = $ignoreserver_link = '';
|
||||
|
||||
if ($this->userSession->getLocalUserId() && $this->userSession->getLocalUserId() == $item['uid'] && $item['gravity'] == ItemModel::GRAVITY_PARENT && !$item['self'] && !$item['mention']) {
|
||||
$sub_link = 'javascript:doFollowThread(' . $item['id'] . '); return false;';
|
||||
|
@ -407,6 +409,11 @@ class Item
|
|||
$collapse_link = $item['self'] ? '' : $contact_url . '/collapse?t=' . $formSecurityToken;
|
||||
}
|
||||
|
||||
$authorBaseUri = new Uri($item['author-baseurl'] ?? '');
|
||||
if (!empty($item['author-gsid']) && $authorBaseUri->getHost() && !DI::baseUrl()->isLocalUrl($authorBaseUri)) {
|
||||
$ignoreserver_link = 'settings/server/' . $item['author-gsid'] . '/ignore';
|
||||
}
|
||||
|
||||
if ($cid && !$item['self']) {
|
||||
$contact_url = 'contact/' . $cid;
|
||||
$posts_link = $contact_url . '/posts';
|
||||
|
@ -427,7 +434,8 @@ class Item
|
|||
$this->l10n->t('Send PM') => $pm_url,
|
||||
$this->l10n->t('Block') => $block_link,
|
||||
$this->l10n->t('Ignore') => $ignore_link,
|
||||
$this->l10n->t('Collapse') => $collapse_link
|
||||
$this->l10n->t('Collapse') => $collapse_link,
|
||||
$this->l10n->t("Ignore %s server", $authorBaseUri->getHost()) => $ignoreserver_link,
|
||||
];
|
||||
|
||||
if (!empty($item['language'])) {
|
||||
|
|
|
@ -671,6 +671,15 @@ abstract class DI
|
|||
return self::$dice->create(Security\Authentication::class);
|
||||
}
|
||||
|
||||
//
|
||||
// "User" namespace instances
|
||||
//
|
||||
|
||||
public static function userGServer(): User\Settings\Repository\UserGServer
|
||||
{
|
||||
return self::$dice->create(User\Settings\Repository\UserGServer::class);
|
||||
}
|
||||
|
||||
//
|
||||
// "Util" namespace instances
|
||||
//
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Federation\Entity;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* @property-read int $id
|
||||
* @property-read string $url
|
||||
* @property-read string $nurl
|
||||
* @property-read string $version
|
||||
* @property-read string $siteName
|
||||
* @property-read string $info
|
||||
* @property-read int $registerPolicy
|
||||
* @property-read int $registeredUsers
|
||||
* @property-read string $poco
|
||||
* @property-read string $noscrape
|
||||
* @property-read string $network
|
||||
* @property-read string $platform
|
||||
* @property-read int $relaySubscribe
|
||||
* @property-read string $relayScope
|
||||
* @property-read DateTimeImmutable $created
|
||||
* @property-read ?DateTimeImmutable $lastPocoQuery
|
||||
* @property-read ?DateTimeImmutable $lastContact
|
||||
* @property-read ?DateTimeImmutable $lastFailure
|
||||
* @property-read int $directoryType
|
||||
* @property-read int $detectionMethod
|
||||
* @property-read bool $failed
|
||||
* @property-read DateTimeImmutable $nextContact
|
||||
* @property-read int $protocol
|
||||
* @property-read int $activeWeekUsers
|
||||
* @property-read int $activeMonthUsers
|
||||
* @property-read int $activeHalfyearUsers
|
||||
* @property-read int $localPosts
|
||||
* @property-read int $localComments
|
||||
* @property-read bool $blocked
|
||||
*/
|
||||
class GServer extends \Friendica\BaseEntity
|
||||
{
|
||||
/** @var ?int */
|
||||
protected $id;
|
||||
/** @var UriInterface */
|
||||
protected $url;
|
||||
/** @var UriInterface */
|
||||
protected $nurl;
|
||||
/** @var string */
|
||||
protected $version;
|
||||
/** @var string */
|
||||
protected $siteName;
|
||||
/** @var string */
|
||||
protected $info;
|
||||
/** @var int One of Module\Register::* constant values */
|
||||
protected $registerPolicy;
|
||||
/** @var int */
|
||||
protected $registeredUsers;
|
||||
/** @var ?UriInterface */
|
||||
protected $poco;
|
||||
/** @var ?UriInterface */
|
||||
protected $noscrape;
|
||||
/** @var string One of the Protocol::* constant values */
|
||||
protected $network;
|
||||
/** @var string */
|
||||
protected $platform;
|
||||
/** @var bool */
|
||||
protected $relaySubscribe;
|
||||
/** @var string */
|
||||
protected $relayScope;
|
||||
/** @var DateTimeImmutable */
|
||||
protected $created;
|
||||
/** @var DateTimeImmutable */
|
||||
protected $lastPocoQuery;
|
||||
/** @var DateTimeImmutable */
|
||||
protected $lastContact;
|
||||
/** @var DateTimeImmutable */
|
||||
protected $lastFailure;
|
||||
/** @var int One of Model\Gserver::DT_* constant values */
|
||||
protected $directoryType;
|
||||
/** @var ?int One of Model\Gserver::DETECT_* constant values */
|
||||
protected $detectionMethod;
|
||||
/** @var bool */
|
||||
protected $failed;
|
||||
/** @var DateTimeImmutable */
|
||||
protected $nextContact;
|
||||
/** @var ?int One of Model\Post\DeliveryData::* constant values */
|
||||
protected $protocol;
|
||||
/** @var ?int */
|
||||
protected $activeWeekUsers;
|
||||
/** @var ?int */
|
||||
protected $activeMonthUsers;
|
||||
/** @var ?int */
|
||||
protected $activeHalfyearUsers;
|
||||
/** @var ?int */
|
||||
protected $localPosts;
|
||||
/** @var ?int */
|
||||
protected $localComments;
|
||||
/** @var bool */
|
||||
protected $blocked;
|
||||
|
||||
public function __construct(UriInterface $url, UriInterface $nurl, string $version, string $siteName, string $info, int $registerPolicy, int $registeredUsers, ?UriInterface $poco, ?UriInterface $noscrape, string $network, string $platform, bool $relaySubscribe, string $relayScope, DateTimeImmutable $created, ?DateTimeImmutable $lastPocoQuery, ?DateTimeImmutable $lastContact, ?DateTimeImmutable $lastFailure, int $directoryType, ?int $detectionMethod, bool $failed, ?DateTimeImmutable $nextContact, ?int $protocol, ?int $activeWeekUsers, ?int $activeMonthUsers, ?int $activeHalfyearUsers, ?int $localPosts, ?int $localComments, bool $blocked, ?int $id = null)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->nurl = $nurl;
|
||||
$this->version = $version;
|
||||
$this->siteName = $siteName;
|
||||
$this->info = $info;
|
||||
$this->registerPolicy = $registerPolicy;
|
||||
$this->registeredUsers = $registeredUsers;
|
||||
$this->poco = $poco;
|
||||
$this->noscrape = $noscrape;
|
||||
$this->network = $network;
|
||||
$this->platform = $platform;
|
||||
$this->relaySubscribe = $relaySubscribe;
|
||||
$this->relayScope = $relayScope;
|
||||
$this->created = $created;
|
||||
$this->lastPocoQuery = $lastPocoQuery;
|
||||
$this->lastContact = $lastContact;
|
||||
$this->lastFailure = $lastFailure;
|
||||
$this->directoryType = $directoryType;
|
||||
$this->detectionMethod = $detectionMethod;
|
||||
$this->failed = $failed;
|
||||
$this->nextContact = $nextContact;
|
||||
$this->protocol = $protocol;
|
||||
$this->activeWeekUsers = $activeWeekUsers;
|
||||
$this->activeMonthUsers = $activeMonthUsers;
|
||||
$this->activeHalfyearUsers = $activeHalfyearUsers;
|
||||
$this->localPosts = $localPosts;
|
||||
$this->localComments = $localComments;
|
||||
$this->blocked = $blocked;
|
||||
$this->id = $id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Federation\Factory;
|
||||
|
||||
use Friendica\Capabilities\ICanCreateFromTableRow;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\Federation\Entity;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
|
||||
class GServer extends \Friendica\BaseFactory implements ICanCreateFromTableRow
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function createFromTableRow(array $row): Entity\GServer
|
||||
{
|
||||
return new Entity\GServer(
|
||||
new Uri($row['url']),
|
||||
new Uri($row['nurl']),
|
||||
$row['version'],
|
||||
$row['site_name'],
|
||||
$row['info'] ?? '',
|
||||
$row['register_policy'],
|
||||
$row['registered-users'],
|
||||
$row['poco'] ? new Uri($row['poco']) : null,
|
||||
$row['noscrape'] ? new Uri($row['noscrape']) : null,
|
||||
$row['network'],
|
||||
$row['platform'],
|
||||
$row['relay-subscribe'],
|
||||
$row['relay-scope'],
|
||||
new \DateTimeImmutable($row['created']),
|
||||
$row['last_poco_query'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['last_poco_query']) : null,
|
||||
$row['last_contact'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['last_contact']) : null,
|
||||
$row['last_failure'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['last_failure']) : null,
|
||||
$row['directory-type'],
|
||||
$row['detection-method'],
|
||||
$row['failed'],
|
||||
$row['next_contact'] !== DBA::NULL_DATETIME ? new \DateTimeImmutable($row['next_contact']) : null,
|
||||
$row['protocol'],
|
||||
$row['active-week-users'],
|
||||
$row['active-month-users'],
|
||||
$row['active-halfyear-users'],
|
||||
$row['local-posts'],
|
||||
$row['local-comments'],
|
||||
$row['blocked'],
|
||||
$row['id'],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Federation\Repository;
|
||||
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Federation\Factory;
|
||||
use Friendica\Federation\Entity;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class GServer extends \Friendica\BaseRepository
|
||||
{
|
||||
protected static $table_name = 'gserver';
|
||||
|
||||
public function __construct(Database $database, LoggerInterface $logger, Factory\GServer $factory)
|
||||
{
|
||||
parent::__construct($database, $logger, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $gsid
|
||||
* @return Entity\GServer
|
||||
* @throws \Friendica\Network\HTTPException\NotFoundException
|
||||
*/
|
||||
public function selectOneById(int $gsid): Entity\GServer
|
||||
{
|
||||
return $this->_selectOne(['id' => $gsid]);
|
||||
}
|
||||
}
|
|
@ -793,10 +793,10 @@ class Contact
|
|||
/**
|
||||
* Updates the self-contact for the provided user id
|
||||
*
|
||||
* @param int $uid
|
||||
* @param bool $update_avatar Force the avatar update
|
||||
* @param int $uid
|
||||
* @param bool $update_avatar Force the avatar update
|
||||
* @return bool "true" if updated
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function updateSelfFromUserID(int $uid, bool $update_avatar = false): bool
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ use Friendica\Core\System;
|
|||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Post\Category;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Protocol\ActivityPub;
|
||||
|
@ -95,9 +96,9 @@ class Item
|
|||
'wall', 'private', 'starred', 'origin', 'parent-origin', 'title', 'body', 'language',
|
||||
'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object',
|
||||
'quote-uri', 'quote-uri-id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'mention', 'global',
|
||||
'author-id', 'author-link', 'author-alias', 'author-name', 'author-avatar', 'author-network', 'author-updated', 'author-gsid', 'author-addr', 'author-uri-id',
|
||||
'owner-id', 'owner-link', 'owner-alias', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type', 'owner-updated',
|
||||
'causer-id', 'causer-link', 'causer-alias', 'causer-name', 'causer-avatar', 'causer-contact-type', 'causer-network',
|
||||
'author-id', 'author-link', 'author-alias', 'author-name', 'author-avatar', 'author-network', 'author-updated', 'author-gsid', 'author-baseurl', 'author-addr', 'author-uri-id',
|
||||
'owner-id', 'owner-link', 'owner-alias', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type', 'owner-updated', 'owner-gsid',
|
||||
'causer-id', 'causer-link', 'causer-alias', 'causer-name', 'causer-avatar', 'causer-contact-type', 'causer-network', 'causer-gsid',
|
||||
'contact-id', 'contact-uid', 'contact-link', 'contact-name', 'contact-avatar',
|
||||
'writable', 'self', 'cid', 'alias',
|
||||
'event-created', 'event-edited', 'event-start', 'event-finish',
|
||||
|
@ -1509,10 +1510,13 @@ class Item
|
|||
return;
|
||||
}
|
||||
|
||||
$uids = Tag::getUIDListByURIId($item['uri-id']);
|
||||
foreach ($uids as $uid) {
|
||||
foreach (Tag::getUIDListByURIId($item['uri-id']) as $uid => $tags) {
|
||||
$stored = self::storeForUserByUriId($item['uri-id'], $uid, ['post-reason' => self::PR_TAG]);
|
||||
Logger::info('Stored item for users', ['uri-id' => $item['uri-id'], 'uid' => $uid, 'stored' => $stored]);
|
||||
foreach ($tags as $tag) {
|
||||
$stored = Category::storeFileByURIId($item['uri-id'], $uid, Category::SUBCRIPTION, $tag);
|
||||
Logger::debug('Stored tag subscription for user', ['uri-id' => $item['uri-id'], 'uid' => $uid, $tag, 'stored' => $stored]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -453,12 +453,10 @@ class Post
|
|||
AND (NOT `causer-blocked` OR `causer-id` = ? OR `causer-id` IS NULL) AND NOT `contact-blocked`
|
||||
AND ((NOT `contact-readonly` AND NOT `contact-pending` AND (`contact-rel` IN (?, ?)))
|
||||
OR `self` OR `contact-uid` = ?)
|
||||
AND NOT `" . $view . "`.`uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `uid` = ? AND `hidden`)
|
||||
AND NOT `author-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `blocked` AND `cid` = `author-id`)
|
||||
AND NOT `owner-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `blocked` AND `cid` = `owner-id`)
|
||||
AND NOT `author-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `ignored` AND `cid` = `author-id`)
|
||||
AND NOT `owner-id` IN (SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `ignored` AND `cid` = `owner-id`)",
|
||||
0, Contact::SHARING, Contact::FRIEND, 0, $uid, $uid, $uid, $uid, $uid]);
|
||||
AND NOT EXISTS(SELECT `uri-id` FROM `post-user` WHERE `uid` = ? AND `uri-id` = " . DBA::quoteIdentifier($view) . ".`uri-id` AND `hidden`)
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = ? AND `cid` IN (`author-id`, `owner-id`) AND (`blocked` OR `ignored`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = ? AND `gsid` IN (`author-gsid`, `owner-gsid`, `causer-gsid`) AND `ignored`)",
|
||||
0, Contact::SHARING, Contact::FRIEND, 0, $uid, $uid, $uid]);
|
||||
|
||||
$select_string = implode(', ', array_map([DBA::class, 'quoteIdentifier'], $selected));
|
||||
|
||||
|
|
|
@ -33,9 +33,10 @@ use Friendica\Model\Tag;
|
|||
*/
|
||||
class Category
|
||||
{
|
||||
const UNKNOWN = 0;
|
||||
const CATEGORY = 3;
|
||||
const FILE = 5;
|
||||
const UNKNOWN = 0;
|
||||
const CATEGORY = 3;
|
||||
const FILE = 5;
|
||||
const SUBCRIPTION = 10;
|
||||
|
||||
/**
|
||||
* Delete all categories and files from a given uri-id and user
|
||||
|
@ -80,7 +81,7 @@ class Category
|
|||
{
|
||||
$file_text = '';
|
||||
|
||||
$tags = DBA::selectToArray('category-view', ['type', 'name'], ['uri-id' => $uri_id, 'uid' => $uid]);
|
||||
$tags = DBA::selectToArray('category-view', ['type', 'name'], ['uri-id' => $uri_id, 'uid' => $uid, 'type' => [Category::FILE, Category::CATEGORY]]);
|
||||
foreach ($tags as $tag) {
|
||||
if ($tag['type'] == self::CATEGORY) {
|
||||
$file_text .= '<' . $tag['name'] . '>';
|
||||
|
@ -177,12 +178,7 @@ class Category
|
|||
continue;
|
||||
}
|
||||
|
||||
DBA::replace('post-category', [
|
||||
'uri-id' => $uri_id,
|
||||
'uid' => $uid,
|
||||
'type' => self::FILE,
|
||||
'tid' => $tagid
|
||||
]);
|
||||
self::storeByURIId($uri_id, $uid, self::FILE, $tagid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,13 +189,18 @@ class Category
|
|||
}
|
||||
}
|
||||
|
||||
public static function storeFileByURIId(int $uri_id, int $uid, int $type, string $file)
|
||||
public static function storeFileByURIId(int $uri_id, int $uid, int $type, string $file, string $url = ''): bool
|
||||
{
|
||||
$tagid = Tag::getID($file);
|
||||
$tagid = Tag::getID($file, $url);
|
||||
if (empty($tagid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::storeByURIId($uri_id, $uid, $type, $tagid);
|
||||
}
|
||||
|
||||
private static function storeByURIId(int $uri_id, int $uid, int $type, int $tagid): bool
|
||||
{
|
||||
return DBA::replace('post-category', [
|
||||
'uri-id' => $uri_id,
|
||||
'uid' => $uid,
|
||||
|
|
|
@ -133,14 +133,14 @@ class UserNotification
|
|||
public static function setNotification(int $uri_id, int $uid)
|
||||
{
|
||||
$fields = ['id', 'uri-id', 'parent-uri-id', 'uid', 'body', 'parent', 'gravity', 'vid', 'gravity',
|
||||
'contact-id', 'author-id', 'owner-id', 'causer-id',
|
||||
'contact-id', 'author-id', 'author-gsid', 'owner-id', 'owner-gsid', 'causer-id', 'causer-gsid',
|
||||
'private', 'thr-parent', 'thr-parent-id', 'parent-uri-id', 'parent-uri', 'verb'];
|
||||
$item = Post::selectFirst($fields, ['uri-id' => $uri_id, 'uid' => $uid, 'origin' => false]);
|
||||
if (!DBA::isResult($item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$parent = Post::selectFirstPost(['author-id', 'owner-id', 'causer-id'], ['uri-id' => $item['parent-uri-id']]);
|
||||
$parent = Post::selectFirstPost(['author-id', 'author-gsid', 'owner-id', 'owner-gsid', 'causer-id', 'causer-gsid',], ['uri-id' => $item['parent-uri-id']]);
|
||||
if (!DBA::isResult($parent)) {
|
||||
return;
|
||||
}
|
||||
|
@ -195,6 +195,13 @@ class UserNotification
|
|||
}
|
||||
}
|
||||
|
||||
foreach (array_unique([$parent['author-gsid'], $parent['owner-gsid'], $parent['causer-gsid'], $item['author-gsid'], $item['owner-gsid'], $item['causer-gsid']]) as $gsid) {
|
||||
if ($gsid && DI::userGServer()->isIgnoredByUser($uid, $gsid)) {
|
||||
Logger::debug('Server is ignored by user', ['uid' => $uid, 'gsid' => $gsid, 'uri-id' => $item['uri-id']]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$user = User::getById($uid, ['account-type', 'account_removed', 'account_expired']);
|
||||
if (in_array($user['account-type'], [User::ACCOUNT_TYPE_COMMUNITY, User::ACCOUNT_TYPE_RELAY])) {
|
||||
return;
|
||||
|
|
|
@ -37,6 +37,7 @@ use Friendica\DI;
|
|||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Protocol\Diaspora;
|
||||
use Friendica\Security\PermissionSet\Entity\PermissionSet;
|
||||
|
@ -93,10 +94,11 @@ class Profile
|
|||
/**
|
||||
* Update a profile entry and distribute the changes if needed
|
||||
*
|
||||
* @param array $fields Profile fields to update
|
||||
* @param integer $uid User id
|
||||
* @param array $fields Profile fields to update
|
||||
* @param integer $uid User id
|
||||
*
|
||||
* @return boolean Whether update was successful
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function update(array $fields, int $uid): bool
|
||||
{
|
||||
|
@ -116,10 +118,6 @@ class Profile
|
|||
return false;
|
||||
}
|
||||
|
||||
if ($old_owner['name'] != $owner['name']) {
|
||||
User::update(['username' => $owner['name']], $uid);
|
||||
}
|
||||
|
||||
$profile_fields = ['postal-code', 'dob', 'prv_keywords', 'homepage'];
|
||||
foreach ($profile_fields as $field) {
|
||||
if ($old_owner[$field] != $owner[$field]) {
|
||||
|
|
|
@ -828,12 +828,13 @@ class Tag
|
|||
public static function getUIDListByURIId(int $uriId): array
|
||||
{
|
||||
$uids = [];
|
||||
$tags = self::getByURIId($uriId, [self::HASHTAG]);
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$uids = array_merge($uids, self::getUIDListByTag(self::TAG_CHARACTER[self::HASHTAG] . $tag['name']));
|
||||
foreach (self::getByURIId($uriId, [self::HASHTAG]) as $tag) {
|
||||
foreach (self::getUIDListByTag(self::TAG_CHARACTER[self::HASHTAG] . $tag['name']) as $uid) {
|
||||
$uids[$uid][] = $tag['name'];
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($uids);
|
||||
return $uids;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ use Friendica\Database\DBA;
|
|||
use Friendica\DI;
|
||||
use Friendica\Module;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Security\TwoFactor\Model\AppSpecificPassword;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Object\Image;
|
||||
|
@ -1328,33 +1329,18 @@ class User
|
|||
/**
|
||||
* Update a user entry and distribute the changes if needed
|
||||
*
|
||||
* @param array $fields
|
||||
* @param array $fields
|
||||
* @param integer $uid
|
||||
* @return boolean
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function update(array $fields, int $uid): bool
|
||||
{
|
||||
$old_owner = self::getOwnerDataById($uid);
|
||||
if (empty($old_owner)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DBA::update('user', $fields, ['uid' => $uid])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$update = Contact::updateSelfFromUserID($uid);
|
||||
|
||||
$owner = self::getOwnerDataById($uid);
|
||||
if (empty($owner)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($old_owner['name'] != $owner['name']) {
|
||||
Profile::update(['name' => $owner['name']], $uid);
|
||||
}
|
||||
|
||||
if ($update) {
|
||||
if (Contact::updateSelfFromUserID($uid)) {
|
||||
Profile::publishUpdate($uid);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ final class Report extends \Friendica\BaseRepository
|
|||
|
||||
$this->factory = $factory;
|
||||
$this->postFactory = $postFactory;
|
||||
$this->ruleFactory = $postFactory;
|
||||
$this->ruleFactory = $ruleFactory;
|
||||
}
|
||||
|
||||
public function selectOneById(int $lastInsertId): \Friendica\Moderation\Entity\Report
|
||||
|
|
|
@ -151,6 +151,13 @@ class BaseSettings extends BaseModule
|
|||
'accesskey' => 'b',
|
||||
];
|
||||
|
||||
$tabs[] = [
|
||||
'label' => $this->t('Remote servers'),
|
||||
'url' => 'settings/server',
|
||||
'selected' => static::class == Settings\Server\Index::class ? 'active' : '',
|
||||
'accesskey' => 's',
|
||||
];
|
||||
|
||||
$tabs[] = [
|
||||
'label' => $this->t('Export personal data'),
|
||||
'url' => 'settings/userexport',
|
||||
|
|
|
@ -23,8 +23,7 @@ namespace Friendica\Module\Contact;
|
|||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseModule;
|
||||
use Friendica\Contact\LocalRelationship\Entity;
|
||||
use Friendica\Contact\LocalRelationship\Repository;
|
||||
use Friendica\Contact\LocalRelationship;
|
||||
use Friendica\Content\ContactSelector;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
|
@ -34,13 +33,16 @@ use Friendica\Core\Hook;
|
|||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Circle;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Module;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Navigation\SystemMessages;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\User\Settings;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -50,31 +52,37 @@ use Psr\Log\LoggerInterface;
|
|||
*/
|
||||
class Profile extends BaseModule
|
||||
{
|
||||
/**
|
||||
* @var Repository\LocalRelationship
|
||||
*/
|
||||
/** @var LocalRelationship\Repository\LocalRelationship */
|
||||
private $localRelationship;
|
||||
/**
|
||||
* @var App\Page
|
||||
*/
|
||||
/** @var App\Page */
|
||||
private $page;
|
||||
/**
|
||||
* @var IManageConfigValues
|
||||
*/
|
||||
/** @var IManageConfigValues */
|
||||
private $config;
|
||||
/** @var IHandleUserSessions */
|
||||
private $session;
|
||||
/** @var SystemMessages */
|
||||
private $systemMessages;
|
||||
/** @var Database */
|
||||
private $db;
|
||||
/** @var Settings\Repository\UserGServer */
|
||||
private $userGServer;
|
||||
|
||||
public function __construct(L10n $l10n, Repository\LocalRelationship $localRelationship, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, App\Page $page, IManageConfigValues $config, array $server, array $parameters = [])
|
||||
public function __construct(Settings\Repository\UserGServer $userGServer, Database $db, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, LocalRelationship\Repository\LocalRelationship $localRelationship, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, App\Page $page, IManageConfigValues $config, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->localRelationship = $localRelationship;
|
||||
$this->page = $page;
|
||||
$this->config = $config;
|
||||
$this->session = $session;
|
||||
$this->systemMessages = $systemMessages;
|
||||
$this->db = $db;
|
||||
$this->userGServer = $userGServer;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
if (!DI::userSession()->getLocalUserId()) {
|
||||
if (!$this->session->getLocalUserId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -82,8 +90,8 @@ class Profile extends BaseModule
|
|||
|
||||
// Backward compatibility: The update still needs a user-specific contact ID
|
||||
// Change to user-contact table check by version 2022.03
|
||||
$cdata = Contact::getPublicAndUserContactID($contact_id, DI::userSession()->getLocalUserId());
|
||||
if (empty($cdata['user']) || !DBA::exists('contact', ['id' => $cdata['user'], 'deleted' => false])) {
|
||||
$cdata = Contact::getPublicAndUserContactID($contact_id, $this->session->getLocalUserId());
|
||||
if (empty($cdata['user']) || !$this->db->exists('contact', ['id' => $cdata['user'], 'deleted' => false])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -124,35 +132,35 @@ class Profile extends BaseModule
|
|||
$fields['info'] = $_POST['info'];
|
||||
}
|
||||
|
||||
if (!Contact::update($fields, ['id' => $cdata['user'], 'uid' => DI::userSession()->getLocalUserId()])) {
|
||||
DI::sysmsg()->addNotice($this->t('Failed to update contact record.'));
|
||||
if (!Contact::update($fields, ['id' => $cdata['user'], 'uid' => $this->session->getLocalUserId()])) {
|
||||
$this->systemMessages->addNotice($this->t('Failed to update contact record.'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
if (!DI::userSession()->getLocalUserId()) {
|
||||
if (!$this->session->getLocalUserId()) {
|
||||
return Module\Security\Login::form($_SERVER['REQUEST_URI']);
|
||||
}
|
||||
|
||||
// Backward compatibility: Ensure to use the public contact when the user contact is provided
|
||||
// Remove by version 2022.03
|
||||
$data = Contact::getPublicAndUserContactID(intval($this->parameters['id']), DI::userSession()->getLocalUserId());
|
||||
$data = Contact::getPublicAndUserContactID(intval($this->parameters['id']), $this->session->getLocalUserId());
|
||||
if (empty($data)) {
|
||||
throw new HTTPException\NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
$contact = Contact::getById($data['public']);
|
||||
if (!DBA::isResult($contact)) {
|
||||
if (!$this->db->isResult($contact)) {
|
||||
throw new HTTPException\NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
// Don't display contacts that are about to be deleted
|
||||
if (DBA::isResult($contact) && (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM)) {
|
||||
if ($this->db->isResult($contact) && (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM)) {
|
||||
throw new HTTPException\NotFoundException($this->t('Contact not found.'));
|
||||
}
|
||||
|
||||
$localRelationship = $this->localRelationship->getForUserContact(DI::userSession()->getLocalUserId(), $contact['id']);
|
||||
$localRelationship = $this->localRelationship->getForUserContact($this->session->getLocalUserId(), $contact['id']);
|
||||
|
||||
if ($localRelationship->rel === Contact::SELF) {
|
||||
$this->baseUrl->redirect('profile/' . $contact['nick'] . '/profile');
|
||||
|
@ -167,55 +175,55 @@ class Profile extends BaseModule
|
|||
}
|
||||
|
||||
if ($cmd === 'updateprofile') {
|
||||
self::updateContactFromProbe($contact['id']);
|
||||
$this->updateContactFromProbe($contact['id']);
|
||||
}
|
||||
|
||||
if ($cmd === 'block') {
|
||||
if ($localRelationship->blocked) {
|
||||
// @TODO Backward compatibility, replace with $localRelationship->unblock()
|
||||
Contact\User::setBlocked($contact['id'], DI::userSession()->getLocalUserId(), false);
|
||||
Contact\User::setBlocked($contact['id'], $this->session->getLocalUserId(), false);
|
||||
|
||||
$message = $this->t('Contact has been unblocked');
|
||||
} else {
|
||||
// @TODO Backward compatibility, replace with $localRelationship->block()
|
||||
Contact\User::setBlocked($contact['id'], DI::userSession()->getLocalUserId(), true);
|
||||
Contact\User::setBlocked($contact['id'], $this->session->getLocalUserId(), true);
|
||||
$message = $this->t('Contact has been blocked');
|
||||
}
|
||||
|
||||
// @TODO: add $this->localRelationship->save($localRelationship);
|
||||
DI::sysmsg()->addInfo($message);
|
||||
$this->systemMessages->addInfo($message);
|
||||
}
|
||||
|
||||
if ($cmd === 'ignore') {
|
||||
if ($localRelationship->ignored) {
|
||||
// @TODO Backward compatibility, replace with $localRelationship->unblock()
|
||||
Contact\User::setIgnored($contact['id'], DI::userSession()->getLocalUserId(), false);
|
||||
Contact\User::setIgnored($contact['id'], $this->session->getLocalUserId(), false);
|
||||
|
||||
$message = $this->t('Contact has been unignored');
|
||||
} else {
|
||||
// @TODO Backward compatibility, replace with $localRelationship->block()
|
||||
Contact\User::setIgnored($contact['id'], DI::userSession()->getLocalUserId(), true);
|
||||
Contact\User::setIgnored($contact['id'], $this->session->getLocalUserId(), true);
|
||||
$message = $this->t('Contact has been ignored');
|
||||
}
|
||||
|
||||
// @TODO: add $this->localRelationship->save($localRelationship);
|
||||
DI::sysmsg()->addInfo($message);
|
||||
$this->systemMessages->addInfo($message);
|
||||
}
|
||||
|
||||
if ($cmd === 'collapse') {
|
||||
if ($localRelationship->collapsed) {
|
||||
// @TODO Backward compatibility, replace with $localRelationship->unblock()
|
||||
Contact\User::setCollapsed($contact['id'], DI::userSession()->getLocalUserId(), false);
|
||||
Contact\User::setCollapsed($contact['id'], $this->session->getLocalUserId(), false);
|
||||
|
||||
$message = $this->t('Contact has been uncollapsed');
|
||||
} else {
|
||||
// @TODO Backward compatibility, replace with $localRelationship->block()
|
||||
Contact\User::setCollapsed($contact['id'], DI::userSession()->getLocalUserId(), true);
|
||||
Contact\User::setCollapsed($contact['id'], $this->session->getLocalUserId(), true);
|
||||
$message = $this->t('Contact has been collapsed');
|
||||
}
|
||||
|
||||
// @TODO: add $this->localRelationship->save($localRelationship);
|
||||
DI::sysmsg()->addInfo($message);
|
||||
$this->systemMessages->addInfo($message);
|
||||
}
|
||||
|
||||
$this->baseUrl->redirect('contact/' . $contact['id']);
|
||||
|
@ -259,6 +267,17 @@ class Profile extends BaseModule
|
|||
|
||||
$insecure = $this->t('Private communications are not available for this contact.');
|
||||
|
||||
// @TODO: Figure out why gsid can be empty
|
||||
if (empty($contact['gsid'])) {
|
||||
$this->logger->notice('Empty gsid for contact', ['contact' => $contact]);
|
||||
}
|
||||
|
||||
$serverIgnored =
|
||||
$contact['gsid'] &&
|
||||
$this->userGServer->isIgnoredByUser($this->session->getLocalUserId(), $contact['gsid']) ?
|
||||
$this->t('This contact is on a server you ignored.')
|
||||
: '';
|
||||
|
||||
$last_update = (($contact['last-update'] <= DBA::NULL_DATETIME) ? $this->t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A'));
|
||||
|
||||
if ($contact['last-update'] > DBA::NULL_DATETIME) {
|
||||
|
@ -363,6 +382,8 @@ class Profile extends BaseModule
|
|||
'$collapsed' => $localRelationship->collapsed ? $this->t('Currently collapsed') : '',
|
||||
'$archived' => ($contact['archive'] ? $this->t('Currently archived') : ''),
|
||||
'$insecure' => (in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::MAIL, Protocol::DIASPORA]) ? '' : $insecure),
|
||||
'$serverIgnored' => $serverIgnored,
|
||||
'$manageServers' => $this->t('Manage remote servers'),
|
||||
'$cinfo' => ['info', '', $localRelationship->info, ''],
|
||||
'$hidden' => ['hidden', $this->t('Hide this contact from others'), $localRelationship->hidden, $this->t('Replies/likes to your public posts <strong>may</strong> still be visible')],
|
||||
'$notify_new_posts' => ['notify_new_posts', $this->t('Notification for new posts'), ($localRelationship->notifyNewPosts), $this->t('Send a notification of every new post of this contact')],
|
||||
|
@ -413,11 +434,11 @@ class Profile extends BaseModule
|
|||
* This includes actions like e.g. 'block', 'hide', 'delete' and others
|
||||
*
|
||||
* @param array $contact Public contact row
|
||||
* @param Entity\LocalRelationship $localRelationship
|
||||
* @param LocalRelationship\Entity\LocalRelationship $localRelationship
|
||||
* @return array with contact related actions
|
||||
* @throws HTTPException\InternalServerErrorException
|
||||
*/
|
||||
private function getContactActions(array $contact, Entity\LocalRelationship $localRelationship): array
|
||||
private function getContactActions(array $contact, LocalRelationship\Entity\LocalRelationship $localRelationship): array
|
||||
{
|
||||
$poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]);
|
||||
$contact_actions = [];
|
||||
|
@ -518,10 +539,9 @@ class Profile extends BaseModule
|
|||
* @throws HTTPException\InternalServerErrorException
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
private static function updateContactFromProbe(int $contact_id)
|
||||
private function updateContactFromProbe(int $contact_id)
|
||||
{
|
||||
$contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => [0, DI::userSession()->getLocalUserId()], 'deleted' => false]);
|
||||
if (!DBA::isResult($contact)) {
|
||||
if (!$this->db->exists('contact', ['id' => $contact_id, 'uid' => [0, $this->session->getLocalUserId()], 'deleted' => false])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -356,7 +356,7 @@ class Community extends BaseModule
|
|||
}
|
||||
}
|
||||
|
||||
$r = Post::selectThreadForUser(0, ['uri-id', 'commented', 'author-link'], $condition, $params);
|
||||
$r = Post::selectThreadForUser(DI::userSession()->getLocalUserId() ?: 0, ['uri-id', 'commented', 'author-link'], $condition, $params);
|
||||
|
||||
$items = Post::toArray($r);
|
||||
if (empty($items)) {
|
||||
|
|
|
@ -133,7 +133,9 @@ class Display extends BaseModule
|
|||
}
|
||||
|
||||
if (empty($item)) {
|
||||
throw new HTTPException\NotFoundException($this->t('The requested item doesn\'t exist or has been deleted.'));
|
||||
$this->page['aside'] = '';
|
||||
$displayNotFound = new DisplayNotFound($this->l10n, $this->baseUrl, $this->args, $this->logger, $this->profiler, $this->response, $this->server, $this->parameters);
|
||||
return $displayNotFound->content();
|
||||
}
|
||||
|
||||
if ($item['gravity'] != Item::GRAVITY_PARENT) {
|
||||
|
|
|
@ -38,6 +38,8 @@ class RobotsTxt extends BaseModule
|
|||
'/search',
|
||||
'/help',
|
||||
'/proxy',
|
||||
'/photo',
|
||||
'/avatar',
|
||||
];
|
||||
|
||||
header('Content-Type: text/plain');
|
||||
|
@ -50,6 +52,10 @@ class RobotsTxt extends BaseModule
|
|||
echo 'User-agent: ChatGPT-User' . PHP_EOL;
|
||||
echo 'Disallow: /' . PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
echo 'User-agent: GPTBot' . PHP_EOL;
|
||||
echo 'Disallow: /' . PHP_EOL;
|
||||
|
||||
System::exit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -573,7 +573,7 @@ class Account extends BaseSettings
|
|||
'$delete_openid' => ['delete_openid', DI::l10n()->t('Delete OpenID URL'), false, ''],
|
||||
|
||||
'$h_basic' => DI::l10n()->t('Basic Settings'),
|
||||
'$username' => ['username', DI::l10n()->t('Full Name:'), $username, '', false, 'autocomplete="off"'],
|
||||
'$username' => ['username', DI::l10n()->t('Display name:'), $username, '', false, 'autocomplete="off"'],
|
||||
'$email' => ['email', DI::l10n()->t('Email Address:'), $email, '', '', 'autocomplete="off"', 'email'],
|
||||
'$timezone' => ['timezone_select', DI::l10n()->t('Your Timezone:'), Temporal::getTimezoneSelect($timezone), ''],
|
||||
'$language' => ['language', DI::l10n()->t('Your Language:'), $language, DI::l10n()->t('Set the language we use to show you friendica interface and to send you emails'), $lang_choices],
|
||||
|
|
|
@ -21,43 +21,75 @@
|
|||
|
||||
namespace Friendica\Module\Settings\Profile;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\Theme;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Profile;
|
||||
use Friendica\Profile\ProfileField\Collection\ProfileFields;
|
||||
use Friendica\Profile\ProfileField\Entity\ProfileField;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Navigation\SystemMessages;
|
||||
use Friendica\Profile\ProfileField;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\BaseSettings;
|
||||
use Friendica\Module\Security\Login;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Security\PermissionSet;
|
||||
use Friendica\Util\ACLFormatter;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Profiler;
|
||||
use Friendica\Util\Temporal;
|
||||
use Friendica\Core\Worker;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Index extends BaseSettings
|
||||
{
|
||||
/** @var ProfileField\Repository\ProfileField */
|
||||
private $profileFieldRepo;
|
||||
/** @var ProfileField\Factory\ProfileField */
|
||||
private $profileFieldFactory;
|
||||
/** @var SystemMessages */
|
||||
private $systemMessages;
|
||||
/** @var PermissionSet\Repository\PermissionSet */
|
||||
private $permissionSetRepo;
|
||||
/** @var PermissionSet\Factory\PermissionSet */
|
||||
private $permissionSetFactory;
|
||||
/** @var ACLFormatter */
|
||||
private $aclFormatter;
|
||||
|
||||
public function __construct(ACLFormatter $aclFormatter, PermissionSet\Factory\PermissionSet $permissionSetFactory, PermissionSet\Repository\PermissionSet $permissionSetRepo, SystemMessages $systemMessages, ProfileField\Factory\ProfileField $profileFieldFactory, ProfileField\Repository\ProfileField $profileFieldRepo, IHandleUserSessions $session, App\Page $page, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($session, $page, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->profileFieldRepo = $profileFieldRepo;
|
||||
$this->profileFieldFactory = $profileFieldFactory;
|
||||
$this->systemMessages = $systemMessages;
|
||||
$this->permissionSetRepo = $permissionSetRepo;
|
||||
$this->permissionSetFactory = $permissionSetFactory;
|
||||
$this->aclFormatter = $aclFormatter;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
if (!DI::userSession()->getLocalUserId()) {
|
||||
if (!$this->session->getLocalUserId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$profile = Profile::getByUID(DI::userSession()->getLocalUserId());
|
||||
if (!DBA::isResult($profile)) {
|
||||
$profile = Profile::getByUID($this->session->getLocalUserId());
|
||||
if (!$profile) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::checkFormSecurityTokenRedirectOnError('/settings/profile', 'settings_profile');
|
||||
|
||||
Hook::callAll('profile_post', $_POST);
|
||||
Hook::callAll('profile_post', $request);
|
||||
|
||||
$dob = trim($_POST['dob'] ?? '');
|
||||
$dob = trim($request['dob'] ?? '');
|
||||
|
||||
if ($dob && !in_array($dob, ['0000-00-00', DBA::NULL_DATE])) {
|
||||
$y = substr($dob, 0, 4);
|
||||
|
@ -79,39 +111,40 @@ class Index extends BaseSettings
|
|||
}
|
||||
}
|
||||
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
if (!strlen($name)) {
|
||||
DI::sysmsg()->addNotice(DI::l10n()->t('Profile Name is required.'));
|
||||
$username = trim($request['username'] ?? '');
|
||||
if (!$username) {
|
||||
$this->systemMessages->addNotice($this->t('Display Name is required.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$about = trim($_POST['about']);
|
||||
$address = trim($_POST['address']);
|
||||
$locality = trim($_POST['locality']);
|
||||
$region = trim($_POST['region']);
|
||||
$postal_code = trim($_POST['postal_code']);
|
||||
$country_name = trim($_POST['country_name']);
|
||||
$pub_keywords = self::cleanKeywords(trim($_POST['pub_keywords']));
|
||||
$prv_keywords = self::cleanKeywords(trim($_POST['prv_keywords']));
|
||||
$xmpp = trim($_POST['xmpp']);
|
||||
$matrix = trim($_POST['matrix']);
|
||||
$homepage = trim($_POST['homepage']);
|
||||
$about = trim($request['about']);
|
||||
$address = trim($request['address']);
|
||||
$locality = trim($request['locality']);
|
||||
$region = trim($request['region']);
|
||||
$postal_code = trim($request['postal_code']);
|
||||
$country_name = trim($request['country_name']);
|
||||
$pub_keywords = self::cleanKeywords(trim($request['pub_keywords']));
|
||||
$prv_keywords = self::cleanKeywords(trim($request['prv_keywords']));
|
||||
$xmpp = trim($request['xmpp']);
|
||||
$matrix = trim($request['matrix']);
|
||||
$homepage = trim($request['homepage']);
|
||||
if ((strpos($homepage, 'http') !== 0) && (strlen($homepage))) {
|
||||
// neither http nor https in URL, add them
|
||||
$homepage = 'http://' . $homepage;
|
||||
}
|
||||
|
||||
$profileFieldsNew = self::getProfileFieldsFromInput(
|
||||
DI::userSession()->getLocalUserId(),
|
||||
$_REQUEST['profile_field'],
|
||||
$_REQUEST['profile_field_order']
|
||||
$profileFieldsNew = $this->getProfileFieldsFromInput(
|
||||
$this->session->getLocalUserId(),
|
||||
$request['profile_field'],
|
||||
$request['profile_field_order']
|
||||
);
|
||||
|
||||
DI::profileField()->saveCollectionForUser(DI::userSession()->getLocalUserId(), $profileFieldsNew);
|
||||
$this->profileFieldRepo->saveCollectionForUser($this->session->getLocalUserId(), $profileFieldsNew);
|
||||
|
||||
User::update(['username' => $username], $this->session->getLocalUserId());
|
||||
|
||||
$result = Profile::update(
|
||||
[
|
||||
'name' => $name,
|
||||
'about' => $about,
|
||||
'dob' => $dob,
|
||||
'address' => $address,
|
||||
|
@ -125,23 +158,23 @@ class Index extends BaseSettings
|
|||
'pub_keywords' => $pub_keywords,
|
||||
'prv_keywords' => $prv_keywords,
|
||||
],
|
||||
DI::userSession()->getLocalUserId()
|
||||
$this->session->getLocalUserId()
|
||||
);
|
||||
|
||||
Worker::add(Worker::PRIORITY_MEDIUM, 'CheckRelMeProfileLink', DI::userSession()->getLocalUserId());
|
||||
Worker::add(Worker::PRIORITY_MEDIUM, 'CheckRelMeProfileLink', $this->session->getLocalUserId());
|
||||
|
||||
if (!$result) {
|
||||
DI::sysmsg()->addNotice(DI::l10n()->t('Profile couldn\'t be updated.'));
|
||||
$this->systemMessages->addNotice($this->t("Profile couldn't be updated."));
|
||||
return;
|
||||
}
|
||||
|
||||
DI::baseUrl()->redirect('settings/profile');
|
||||
$this->baseUrl->redirect('settings/profile');
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
if (!DI::userSession()->getLocalUserId()) {
|
||||
DI::sysmsg()->addNotice(DI::l10n()->t('You must be logged in to use this module'));
|
||||
if (!$this->session->getLocalUserId()) {
|
||||
$this->systemMessages->addNotice($this->t('You must be logged in to use this module'));
|
||||
return Login::form();
|
||||
}
|
||||
|
||||
|
@ -149,147 +182,145 @@ class Index extends BaseSettings
|
|||
|
||||
$o = '';
|
||||
|
||||
$profile = User::getOwnerDataById(DI::userSession()->getLocalUserId());
|
||||
if (!DBA::isResult($profile)) {
|
||||
$owner = User::getOwnerDataById($this->session->getLocalUserId());
|
||||
if (!$owner) {
|
||||
throw new HTTPException\NotFoundException();
|
||||
}
|
||||
|
||||
$a = DI::app();
|
||||
|
||||
DI::page()->registerFooterScript('view/asset/es-jquery-sortable/source/js/jquery-sortable-min.js');
|
||||
DI::page()->registerFooterScript(Theme::getPathForFile('js/module/settings/profile/index.js'));
|
||||
$this->page->registerFooterScript('view/asset/es-jquery-sortable/source/js/jquery-sortable-min.js');
|
||||
$this->page->registerFooterScript(Theme::getPathForFile('js/module/settings/profile/index.js'));
|
||||
|
||||
$custom_fields = [];
|
||||
|
||||
$profileFields = DI::profileField()->selectByUserId(DI::userSession()->getLocalUserId());
|
||||
$profileFields = $this->profileFieldRepo->selectByUserId($this->session->getLocalUserId());
|
||||
foreach ($profileFields as $profileField) {
|
||||
/** @var ProfileField $profileField */
|
||||
$defaultPermissions = $profileField->permissionSet->withAllowedContacts(
|
||||
Contact::pruneUnavailable($profileField->permissionSet->allow_cid)
|
||||
);
|
||||
|
||||
$custom_fields[] = [
|
||||
'id' => $profileField->id,
|
||||
'id' => $profileField->id,
|
||||
'legend' => $profileField->label,
|
||||
'fields' => [
|
||||
'label' => ['profile_field[' . $profileField->id . '][label]', DI::l10n()->t('Label:'), $profileField->label],
|
||||
'value' => ['profile_field[' . $profileField->id . '][value]', DI::l10n()->t('Value:'), $profileField->value],
|
||||
'acl' => ACL::getFullSelectorHTML(
|
||||
DI::page(),
|
||||
$a->getLoggedInUserId(),
|
||||
'label' => ['profile_field[' . $profileField->id . '][label]', $this->t('Label:'), $profileField->label],
|
||||
'value' => ['profile_field[' . $profileField->id . '][value]', $this->t('Value:'), $profileField->value],
|
||||
'acl' => ACL::getFullSelectorHTML(
|
||||
$this->page,
|
||||
$this->session->getLocalUserId(),
|
||||
false,
|
||||
$defaultPermissions->toArray(),
|
||||
['network' => Protocol::DFRN],
|
||||
'profile_field[' . $profileField->id . ']'
|
||||
),
|
||||
],
|
||||
'permissions' => DI::l10n()->t('Field Permissions'),
|
||||
'permdesc' => DI::l10n()->t("(click to open/close)"),
|
||||
|
||||
'permissions' => $this->t('Field Permissions'),
|
||||
'permdesc' => $this->t("(click to open/close)"),
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
$custom_fields[] = [
|
||||
'id' => 'new',
|
||||
'legend' => DI::l10n()->t('Add a new profile field'),
|
||||
'id' => 'new',
|
||||
'legend' => $this->t('Add a new profile field'),
|
||||
'fields' => [
|
||||
'label' => ['profile_field[new][label]', DI::l10n()->t('Label:')],
|
||||
'value' => ['profile_field[new][value]', DI::l10n()->t('Value:')],
|
||||
'acl' => ACL::getFullSelectorHTML(
|
||||
DI::page(),
|
||||
$a->getLoggedInUserId(),
|
||||
'label' => ['profile_field[new][label]', $this->t('Label:')],
|
||||
'value' => ['profile_field[new][value]', $this->t('Value:')],
|
||||
'acl' => ACL::getFullSelectorHTML(
|
||||
$this->page,
|
||||
$this->session->getLocalUserId(),
|
||||
false,
|
||||
['allow_cid' => []],
|
||||
['network' => Protocol::DFRN],
|
||||
'profile_field[new]'
|
||||
),
|
||||
],
|
||||
'permissions' => DI::l10n()->t('Field Permissions'),
|
||||
'permdesc' => DI::l10n()->t("(click to open/close)"),
|
||||
|
||||
'permissions' => $this->t('Field Permissions'),
|
||||
'permdesc' => $this->t("(click to open/close)"),
|
||||
];
|
||||
|
||||
DI::page()['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('settings/profile/index_head.tpl'), [
|
||||
]);
|
||||
$this->page['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('settings/profile/index_head.tpl'));
|
||||
|
||||
$personal_account = ($profile['account-type'] != User::ACCOUNT_TYPE_COMMUNITY);
|
||||
$personal_account = ($owner['account-type'] != User::ACCOUNT_TYPE_COMMUNITY);
|
||||
|
||||
if ($profile['homepage_verified']) {
|
||||
$homepage_help_text = DI::l10n()->t('The homepage is verified. A rel="me" link back to your Friendica profile page was found on the homepage.');
|
||||
if ($owner['homepage_verified']) {
|
||||
$homepage_help_text = $this->t('The homepage is verified. A rel="me" link back to your Friendica profile page was found on the homepage.');
|
||||
} else {
|
||||
$homepage_help_text = DI::l10n()->t('To verify your homepage, add a rel="me" link to it, pointing to your profile URL (%s).', $profile['url']);
|
||||
$homepage_help_text = $this->t('To verify your homepage, add a rel="me" link to it, pointing to your profile URL (%s).', $owner['url']);
|
||||
}
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate('settings/profile/index.tpl');
|
||||
$o .= Renderer::replaceMacros($tpl, [
|
||||
'$personal_account' => $personal_account,
|
||||
|
||||
'$form_security_token' => self::getFormSecurityToken('settings_profile'),
|
||||
'$form_security_token_photo' => self::getFormSecurityToken('settings_profile_photo'),
|
||||
|
||||
'$profile_action' => DI::l10n()->t('Profile Actions'),
|
||||
'$banner' => DI::l10n()->t('Edit Profile Details'),
|
||||
'$submit' => DI::l10n()->t('Submit'),
|
||||
'$profpic' => DI::l10n()->t('Change Profile Photo'),
|
||||
'$profpiclink' => '/profile/' . $profile['nickname'] . '/photos',
|
||||
'$viewprof' => DI::l10n()->t('View Profile'),
|
||||
|
||||
'$lbl_personal_section' => DI::l10n()->t('Personal'),
|
||||
'$lbl_picture_section' => DI::l10n()->t('Profile picture'),
|
||||
'$lbl_location_section' => DI::l10n()->t('Location'),
|
||||
'$lbl_miscellaneous_section' => DI::l10n()->t('Miscellaneous'),
|
||||
'$lbl_custom_fields_section' => DI::l10n()->t('Custom Profile Fields'),
|
||||
|
||||
'$lbl_profile_photo' => DI::l10n()->t('Upload Profile Photo'),
|
||||
|
||||
'$baseurl' => DI::baseUrl(),
|
||||
'$nickname' => $profile['nickname'],
|
||||
'$name' => ['name', DI::l10n()->t('Display name:'), $profile['name']],
|
||||
'$about' => ['about', DI::l10n()->t('Description:'), $profile['about']],
|
||||
'$dob' => Temporal::getDateofBirthField($profile['dob'], $profile['timezone']),
|
||||
'$address' => ['address', DI::l10n()->t('Street Address:'), $profile['address']],
|
||||
'$locality' => ['locality', DI::l10n()->t('Locality/City:'), $profile['locality']],
|
||||
'$region' => ['region', DI::l10n()->t('Region/State:'), $profile['region']],
|
||||
'$postal_code' => ['postal_code', DI::l10n()->t('Postal/Zip Code:'), $profile['postal-code']],
|
||||
'$country_name' => ['country_name', DI::l10n()->t('Country:'), $profile['country-name']],
|
||||
'$age' => ((intval($profile['dob'])) ? '(' . DI::l10n()->t('Age: ') . DI::l10n()->tt('%d year old', '%d years old', Temporal::getAgeByTimezone($profile['dob'], $profile['timezone'])) . ')' : ''),
|
||||
'$xmpp' => ['xmpp', DI::l10n()->t('XMPP (Jabber) address:'), $profile['xmpp'], DI::l10n()->t('The XMPP address will be published so that people can follow you there.')],
|
||||
'$matrix' => ['matrix', DI::l10n()->t('Matrix (Element) address:'), $profile['matrix'], DI::l10n()->t('The Matrix address will be published so that people can follow you there.')],
|
||||
'$homepage' => ['homepage', DI::l10n()->t('Homepage URL:'), $profile['homepage'], $homepage_help_text],
|
||||
'$pub_keywords' => ['pub_keywords', DI::l10n()->t('Public Keywords:'), $profile['pub_keywords'], DI::l10n()->t('(Used for suggesting potential friends, can be seen by others)')],
|
||||
'$prv_keywords' => ['prv_keywords', DI::l10n()->t('Private Keywords:'), $profile['prv_keywords'], DI::l10n()->t('(Used for searching profiles, never shown to others)')],
|
||||
'$custom_fields_description' => DI::l10n()->t("<p>Custom fields appear on <a href=\"%s\">your profile page</a>.</p>
|
||||
'$l10n' => [
|
||||
'profile_action' => $this->t('Profile Actions'),
|
||||
'banner' => $this->t('Edit Profile Details'),
|
||||
'submit' => $this->t('Submit'),
|
||||
'profpic' => $this->t('Change Profile Photo'),
|
||||
'viewprof' => $this->t('View Profile'),
|
||||
'personal_section' => $this->t('Personal'),
|
||||
'picture_section' => $this->t('Profile picture'),
|
||||
'location_section' => $this->t('Location'),
|
||||
'miscellaneous_section' => $this->t('Miscellaneous'),
|
||||
'custom_fields_section' => $this->t('Custom Profile Fields'),
|
||||
'profile_photo' => $this->t('Upload Profile Photo'),
|
||||
'custom_fields_description' => $this->t('<p>Custom fields appear on <a href="%s">your profile page</a>.</p>
|
||||
<p>You can use BBCodes in the field values.</p>
|
||||
<p>Reorder by dragging the field title.</p>
|
||||
<p>Empty the label field to remove a custom field.</p>
|
||||
<p>Non-public fields can only be seen by the selected Friendica contacts or the Friendica contacts in the selected circles.</p>",
|
||||
'profile/' . $profile['nickname'] . '/profile'
|
||||
),
|
||||
<p>Non-public fields can only be seen by the selected Friendica contacts or the Friendica contacts in the selected circles.</p>',
|
||||
'profile/' . $owner['nickname'] . '/profile'
|
||||
),
|
||||
],
|
||||
|
||||
'$personal_account' => $personal_account,
|
||||
|
||||
'$form_security_token' => self::getFormSecurityToken('settings_profile'),
|
||||
'$form_security_token_photo' => self::getFormSecurityToken('settings_profile_photo'),
|
||||
|
||||
'$profpiclink' => '/profile/' . $owner['nickname'] . '/photos',
|
||||
|
||||
'$nickname' => $owner['nickname'],
|
||||
'$username' => ['username', $this->t('Display name:'), $owner['name']],
|
||||
'$about' => ['about', $this->t('Description:'), $owner['about']],
|
||||
'$dob' => Temporal::getDateofBirthField($owner['dob'], $owner['timezone']),
|
||||
'$address' => ['address', $this->t('Street Address:'), $owner['address']],
|
||||
'$locality' => ['locality', $this->t('Locality/City:'), $owner['locality']],
|
||||
'$region' => ['region', $this->t('Region/State:'), $owner['region']],
|
||||
'$postal_code' => ['postal_code', $this->t('Postal/Zip Code:'), $owner['postal-code']],
|
||||
'$country_name' => ['country_name', $this->t('Country:'), $owner['country-name']],
|
||||
'$age' => ((intval($owner['dob'])) ? '(' . $this->t('Age: ') . $this->tt('%d year old', '%d years old', Temporal::getAgeByTimezone($owner['dob'], $owner['timezone'])) . ')' : ''),
|
||||
'$xmpp' => ['xmpp', $this->t('XMPP (Jabber) address:'), $owner['xmpp'], $this->t('The XMPP address will be published so that people can follow you there.')],
|
||||
'$matrix' => ['matrix', $this->t('Matrix (Element) address:'), $owner['matrix'], $this->t('The Matrix address will be published so that people can follow you there.')],
|
||||
'$homepage' => ['homepage', $this->t('Homepage URL:'), $owner['homepage'], $homepage_help_text],
|
||||
'$pub_keywords' => ['pub_keywords', $this->t('Public Keywords:'), $owner['pub_keywords'], $this->t('(Used for suggesting potential friends, can be seen by others)')],
|
||||
'$prv_keywords' => ['prv_keywords', $this->t('Private Keywords:'), $owner['prv_keywords'], $this->t('(Used for searching profiles, never shown to others)')],
|
||||
'$custom_fields' => $custom_fields,
|
||||
]);
|
||||
|
||||
$arr = ['profile' => $profile, 'entry' => $o];
|
||||
$arr = ['profile' => $owner, 'entry' => $o];
|
||||
Hook::callAll('profile_edit', $arr);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
private static function getProfileFieldsFromInput(int $uid, array $profileFieldInputs, array $profileFieldOrder): ProfileFields
|
||||
private function getProfileFieldsFromInput(int $uid, array $profileFieldInputs, array $profileFieldOrder): ProfileField\Collection\ProfileFields
|
||||
{
|
||||
$profileFields = new ProfileFields();
|
||||
$profileFields = new ProfileField\Collection\ProfileFields();
|
||||
|
||||
// Returns an associative array of id => order values
|
||||
$profileFieldOrder = array_flip($profileFieldOrder);
|
||||
|
||||
// Creation of the new field
|
||||
if (!empty($profileFieldInputs['new']['label'])) {
|
||||
$permissionSet = DI::permissionSet()->selectOrCreate(DI::permissionSetFactory()->createFromString(
|
||||
$permissionSet = $this->permissionSetRepo->selectOrCreate($this->permissionSetFactory->createFromString(
|
||||
$uid,
|
||||
DI::aclFormatter()->toString($profileFieldInputs['new']['contact_allow'] ?? ''),
|
||||
DI::aclFormatter()->toString($profileFieldInputs['new']['circle_allow'] ?? ''),
|
||||
DI::aclFormatter()->toString($profileFieldInputs['new']['contact_deny'] ?? ''),
|
||||
DI::aclFormatter()->toString($profileFieldInputs['new']['circle_deny'] ?? '')
|
||||
$this->aclFormatter->toString($profileFieldInputs['new']['contact_allow'] ?? ''),
|
||||
$this->aclFormatter->toString($profileFieldInputs['new']['circle_allow'] ?? ''),
|
||||
$this->aclFormatter->toString($profileFieldInputs['new']['contact_deny'] ?? ''),
|
||||
$this->aclFormatter->toString($profileFieldInputs['new']['circle_deny'] ?? '')
|
||||
));
|
||||
|
||||
$profileFields->append(DI::profileFieldFactory()->createFromValues(
|
||||
$profileFields->append($this->profileFieldFactory->createFromValues(
|
||||
$uid,
|
||||
$profileFieldOrder['new'],
|
||||
$profileFieldInputs['new']['label'],
|
||||
|
@ -302,15 +333,15 @@ class Index extends BaseSettings
|
|||
unset($profileFieldOrder['new']);
|
||||
|
||||
foreach ($profileFieldInputs as $id => $profileFieldInput) {
|
||||
$permissionSet = DI::permissionSet()->selectOrCreate(DI::permissionSetFactory()->createFromString(
|
||||
$permissionSet = $this->permissionSetRepo->selectOrCreate($this->permissionSetFactory->createFromString(
|
||||
$uid,
|
||||
DI::aclFormatter()->toString($profileFieldInput['contact_allow'] ?? ''),
|
||||
DI::aclFormatter()->toString($profileFieldInput['circle_allow'] ?? ''),
|
||||
DI::aclFormatter()->toString($profileFieldInput['contact_deny'] ?? ''),
|
||||
DI::aclFormatter()->toString($profileFieldInput['circle_deny'] ?? '')
|
||||
$this->aclFormatter->toString($profileFieldInput['contact_allow'] ?? ''),
|
||||
$this->aclFormatter->toString($profileFieldInput['circle_allow'] ?? ''),
|
||||
$this->aclFormatter->toString($profileFieldInput['contact_deny'] ?? ''),
|
||||
$this->aclFormatter->toString($profileFieldInput['circle_deny'] ?? '')
|
||||
));
|
||||
|
||||
$profileFields->append(DI::profileFieldFactory()->createFromValues(
|
||||
$profileFields->append($this->profileFieldFactory->createFromValues(
|
||||
$uid,
|
||||
$profileFieldOrder[$id],
|
||||
$profileFieldInput['label'],
|
||||
|
@ -322,22 +353,20 @@ class Index extends BaseSettings
|
|||
return $profileFields;
|
||||
}
|
||||
|
||||
private static function cleanKeywords($keywords)
|
||||
private static function cleanKeywords($keywords): string
|
||||
{
|
||||
$keywords = str_replace(',', ' ', $keywords);
|
||||
$keywords = explode(' ', $keywords);
|
||||
|
||||
$cleaned = [];
|
||||
foreach ($keywords as $keyword) {
|
||||
$keyword = trim(strtolower($keyword));
|
||||
$keyword = trim($keyword);
|
||||
$keyword = trim($keyword, '#');
|
||||
if ($keyword != '') {
|
||||
$cleaned[] = $keyword;
|
||||
}
|
||||
}
|
||||
|
||||
$keywords = implode(', ', $cleaned);
|
||||
|
||||
return $keywords;
|
||||
return implode(', ', $cleaned);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Module\Settings\Server;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Federation\Repository\GServer;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Network\HTTPException\BadRequestException;
|
||||
use Friendica\User\Settings\Repository\UserGServer;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Action extends \Friendica\BaseModule
|
||||
{
|
||||
/** @var IHandleUserSessions */
|
||||
private $session;
|
||||
/** @var UserGServer */
|
||||
private $repository;
|
||||
/** @var GServer */
|
||||
private $gserverRepo;
|
||||
|
||||
public function __construct(GServer $gserverRepo, UserGServer $repository, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->session = $session;
|
||||
$this->repository = $repository;
|
||||
$this->gserverRepo = $gserverRepo;
|
||||
}
|
||||
|
||||
public function content(array $request = []): string
|
||||
{
|
||||
$GServer = $this->gserverRepo->selectOneById($this->parameters['gsid']);
|
||||
|
||||
switch ($this->parameters['action']) {
|
||||
case 'ignore':
|
||||
$action = $this->t('Do you want to ignore this server?');
|
||||
$desc = $this->t("You won't see any content from this server including reshares in your Network page, the community pages and individual conversations.");
|
||||
break;
|
||||
case 'unignore':
|
||||
$action = $this->t('Do you want to unignore this server?');
|
||||
$desc = '';
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestException('Unknown user server action ' . $this->parameters['action']);
|
||||
}
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate('settings/server/action.tpl');
|
||||
return Renderer::replaceMacros($tpl, [
|
||||
'$l10n' => [
|
||||
'title' => $this->t('Remote server settings'),
|
||||
'action' => $action,
|
||||
'siteName' => $this->t('Server Name'),
|
||||
'siteUrl' => $this->t('Server URL'),
|
||||
'desc' => $desc,
|
||||
'submit' => $this->t('Submit'),
|
||||
],
|
||||
|
||||
'$action' => $this->args->getQueryString(),
|
||||
|
||||
'$GServer' => $GServer,
|
||||
|
||||
'$form_security_token' => self::getFormSecurityToken('settings-server'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function post(array $request = [])
|
||||
{
|
||||
if (!empty($request['redirect_url'])) {
|
||||
self::checkFormSecurityTokenRedirectOnError($this->args->getQueryString(), 'settings-server');
|
||||
}
|
||||
|
||||
$userGServer = $this->repository->getOneByUserAndServer($this->session->getLocalUserId(), $this->parameters['gsid']);
|
||||
|
||||
switch ($this->parameters['action']) {
|
||||
case 'ignore':
|
||||
$userGServer->ignore();
|
||||
break;
|
||||
case 'unignore':
|
||||
$userGServer->unignore();
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestException('Unknown user server action ' . $this->parameters['action']);
|
||||
}
|
||||
|
||||
$this->repository->save($userGServer);
|
||||
|
||||
if (!empty($request['redirect_url'])) {
|
||||
$this->baseUrl->redirect($request['redirect_url']);
|
||||
}
|
||||
|
||||
System::exit();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\Module\Settings\Server;
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Pager;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Module\BaseSettings;
|
||||
use Friendica\Module\Response;
|
||||
use Friendica\Navigation\SystemMessages;
|
||||
use Friendica\Network\HTTPException\NotFoundException;
|
||||
use Friendica\User\Settings\Entity\UserGServer;
|
||||
use Friendica\User\Settings\Repository;
|
||||
use Friendica\Util\Profiler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Index extends BaseSettings
|
||||
{
|
||||
/** @var Repository\UserGServer */
|
||||
private $repository;
|
||||
/** @var SystemMessages */
|
||||
private $systemMessages;
|
||||
|
||||
public function __construct(SystemMessages $systemMessages, Repository\UserGServer $repository, IHandleUserSessions $session, App\Page $page, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
|
||||
{
|
||||
parent::__construct($session, $page, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
|
||||
|
||||
$this->repository = $repository;
|
||||
$this->systemMessages = $systemMessages;
|
||||
}
|
||||
|
||||
protected function post(array $request = [])
|
||||
{
|
||||
self::checkFormSecurityTokenRedirectOnError($this->args->getQueryString(), 'settings-server');
|
||||
|
||||
foreach ($request['delete'] ?? [] as $gsid => $delete) {
|
||||
if ($delete) {
|
||||
unset($request['ignored'][$gsid]);
|
||||
|
||||
try {
|
||||
$userGServer = $this->repository->selectOneByUserAndServer($this->session->getLocalUserId(), $gsid, false);
|
||||
$this->repository->delete($userGServer);
|
||||
} catch (NotFoundException $e) {
|
||||
// Nothing to delete
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($request['ignored'] ?? [] as $gsid => $ignored) {
|
||||
$userGServer = $this->repository->getOneByUserAndServer($this->session->getLocalUserId(), $gsid, false);
|
||||
if ($userGServer->ignored != $ignored) {
|
||||
$userGServer->toggleIgnored();
|
||||
$this->repository->save($userGServer);
|
||||
}
|
||||
}
|
||||
|
||||
$this->systemMessages->addInfo($this->t('Settings saved'));
|
||||
|
||||
$this->baseUrl->redirect($this->args->getQueryString());
|
||||
}
|
||||
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
parent::content();
|
||||
|
||||
$pager = new Pager($this->l10n, $this->args->getQueryString(), 30);
|
||||
|
||||
$total = $this->repository->countByUser($this->session->getLocalUserId());
|
||||
|
||||
$servers = $this->repository->selectByUserWithPagination($this->session->getLocalUserId(), $pager);
|
||||
|
||||
$ignoredCheckboxes = array_map(function (UserGServer $server) {
|
||||
return ['ignored[' . $server->gsid . ']', '', $server->ignored];
|
||||
}, $servers->getArrayCopy());
|
||||
|
||||
$deleteCheckboxes = array_map(function (UserGServer $server) {
|
||||
return ['delete[' . $server->gsid . ']'];
|
||||
}, $servers->getArrayCopy());
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate('settings/server/index.tpl');
|
||||
return Renderer::replaceMacros($tpl, [
|
||||
'$l10n' => [
|
||||
'title' => $this->t('Remote server settings'),
|
||||
'desc' => $this->t('Here you can find all the remote servers you have taken individual moderation actions against. For a list of servers your node has blocked, please check out the <a href="friendica">Information</a> page.'),
|
||||
'siteName' => $this->t('Server Name'),
|
||||
'ignored' => $this->t('Ignored'),
|
||||
'ignored_title' => $this->t("You won't see any content from this server including reshares in your Network page, the community pages and individual conversations."),
|
||||
'delete' => $this->t('Delete'),
|
||||
'delete_title' => $this->t('Delete all your settings for the remote server'),
|
||||
'submit' => $this->t('Save changes'),
|
||||
],
|
||||
|
||||
'$count' => $total,
|
||||
|
||||
'$servers' => $servers,
|
||||
|
||||
'$form_security_token' => self::getFormSecurityToken('settings-server'),
|
||||
|
||||
'$ignoredCheckboxes' => $ignoredCheckboxes,
|
||||
'$deleteCheckboxes' => $deleteCheckboxes,
|
||||
|
||||
'$paginate' => $pager->renderFull($total),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -31,18 +31,21 @@ class DisplayNotFound extends \Friendica\BaseModule
|
|||
{
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
$reasons = [
|
||||
$this->t("The top-level post isn't visible."),
|
||||
$this->t('The top-level post was deleted.'),
|
||||
$this->t('This node has blocked the top-level author or the author of the shared post.'),
|
||||
$this->t('You have ignored or blocked the top-level author or the author of the shared post.'),
|
||||
$this->t("You have ignored the top-level author's server or the shared post author's server."),
|
||||
];
|
||||
|
||||
$tpl = Renderer::getMarkupTemplate('special/displaynotfound.tpl');
|
||||
return Renderer::replaceMacros($tpl, [
|
||||
'$l10n' => [
|
||||
'title' => $this->t('Not Found'),
|
||||
'message' => $this->t("<p>Unfortunately, the requested conversation isn't available to you.</p>
|
||||
<p>Possible reasons include:</p>
|
||||
<ul>
|
||||
<li>The top-level post isn't visible.</li>
|
||||
<li>The top-level post was deleted.</li>
|
||||
<li>The node has blocked the top-level author or the author of the shared post.</li>
|
||||
<li>You have ignored or blocked the top-level author or the author of the shared post.</li>
|
||||
</ul>"),
|
||||
'title' => $this->t('Conversation Not Found'),
|
||||
'desc1' => $this->t("Unfortunately, the requested conversation isn't available to you."),
|
||||
'desc2' => $this->t('Possible reasons include:'),
|
||||
'reasons' => $reasons,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -31,16 +31,15 @@ use Friendica\Core\Renderer;
|
|||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Model\Post as PostModel;
|
||||
use Friendica\Model\Tag;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Util\Crypto;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Proxy;
|
||||
use Friendica\Util\Strings;
|
||||
use Friendica\Util\Temporal;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
|
@ -248,11 +247,12 @@ class Post
|
|||
$pinned = DI::l10n()->t('Pinned item');
|
||||
}
|
||||
|
||||
$drop = false;
|
||||
$block = false;
|
||||
$ignore = false;
|
||||
$collapse = false;
|
||||
$report = false;
|
||||
$drop = false;
|
||||
$block = false;
|
||||
$ignore = false;
|
||||
$collapse = false;
|
||||
$report = false;
|
||||
$ignoreServer = false;
|
||||
if (DI::userSession()->getLocalUserId()) {
|
||||
$drop = [
|
||||
'dropping' => $dropping,
|
||||
|
@ -282,6 +282,12 @@ class Post
|
|||
'label' => DI::l10n()->t('Report post'),
|
||||
'href' => 'moderation/report/create?' . http_build_query(['cid' => $item['author-id'], 'uri-ids' => [$item['uri-id']]]),
|
||||
];
|
||||
$authorBaseUri = new Uri($item['author-baseurl'] ?? '');
|
||||
if ($authorBaseUri->getHost() && !DI::baseUrl()->isLocalUrl($authorBaseUri)) {
|
||||
$ignoreServer = [
|
||||
'label' => DI::l10n()->t("Ignore %s server", $authorBaseUri->getHost()),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$filer = DI::userSession()->getLocalUserId() ? DI::l10n()->t('Save to folder') : false;
|
||||
|
@ -557,6 +563,7 @@ class Post
|
|||
'ignore_author' => $ignore,
|
||||
'collapse' => $collapse,
|
||||
'report' => $report,
|
||||
'ignore_server' => $ignoreServer,
|
||||
'vote' => $buttons,
|
||||
'like_html' => $responses['like']['output'],
|
||||
'dislike_html' => $responses['dislike']['output'],
|
||||
|
@ -571,6 +578,7 @@ class Post
|
|||
'wait' => DI::l10n()->t('Please wait'),
|
||||
'thread_level' => $thread_level,
|
||||
'edited' => $edited,
|
||||
'author_gsid' => $item['author-gsid'],
|
||||
'network' => $item['network'],
|
||||
'network_name' => ContactSelector::networkToName($item['author-network'], $item['author-link'], $item['network'], $item['author-gsid']),
|
||||
'network_icon' => ContactSelector::networkToIcon($item['network'], $item['author-link'], $item['author-gsid']),
|
||||
|
|
|
@ -211,7 +211,7 @@ class PermissionSet extends BaseRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* Selects or creates a PermissionSet based on it's fields
|
||||
* Selects or creates a PermissionSet based on its fields
|
||||
*
|
||||
* @param Entity\PermissionSet $permissionSet
|
||||
*
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\User\Settings\Collection;
|
||||
|
||||
class UserGServers extends \Friendica\BaseCollection
|
||||
{
|
||||
public function current(): \Friendica\User\Settings\Entity\UserGServer
|
||||
{
|
||||
return parent::current();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\User\Settings\Entity;
|
||||
|
||||
use Friendica\Federation\Entity\GServer;
|
||||
|
||||
/**
|
||||
* @property-read int $uid
|
||||
* @property-read int $gsid
|
||||
* @property-read bool $ignored
|
||||
* @property-read ?GServer $gserver
|
||||
*/
|
||||
class UserGServer extends \Friendica\BaseEntity
|
||||
{
|
||||
/** @var int User id */
|
||||
protected $uid;
|
||||
/** @var int GServer id */
|
||||
protected $gsid;
|
||||
/** @var bool Whether the user ignored this server */
|
||||
protected $ignored;
|
||||
/** @var ?GServer */
|
||||
protected $gserver;
|
||||
|
||||
public function __construct(int $uid, int $gsid, bool $ignored = false, ?GServer $gserver = null)
|
||||
{
|
||||
$this->uid = $uid;
|
||||
$this->gsid = $gsid;
|
||||
$this->ignored = $ignored;
|
||||
$this->gserver = $gserver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the ignored property.
|
||||
*
|
||||
* Chainable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function toggleIgnored(): UserGServer
|
||||
{
|
||||
$this->ignored = !$this->ignored;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ignored property.
|
||||
*
|
||||
* Chainable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function ignore(): UserGServer
|
||||
{
|
||||
$this->ignored = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the ignored property.
|
||||
*
|
||||
* Chainable.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function unignore(): UserGServer
|
||||
{
|
||||
$this->ignored = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\User\Settings\Factory;
|
||||
|
||||
use Friendica\Capabilities\ICanCreateFromTableRow;
|
||||
use Friendica\Federation\Entity\GServer;
|
||||
use Friendica\User\Settings\Entity;
|
||||
|
||||
class UserGServer extends \Friendica\BaseFactory implements ICanCreateFromTableRow
|
||||
{
|
||||
/**
|
||||
* @param array $row `user-gserver` table row
|
||||
* @param GServer|null $server Corresponding GServer entity
|
||||
* @return Entity\UserGServer
|
||||
*/
|
||||
public function createFromTableRow(array $row, GServer $server = null): Entity\UserGServer
|
||||
{
|
||||
return new Entity\UserGServer(
|
||||
$row['uid'],
|
||||
$row['gsid'],
|
||||
$row['ignored'],
|
||||
$server,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @param int $gsid
|
||||
* @param GServer|null $gserver Corresponding GServer entity
|
||||
* @return Entity\UserGServer
|
||||
*/
|
||||
public function createFromUserAndServer(int $uid, int $gsid, GServer $gserver = null): Entity\UserGServer
|
||||
{
|
||||
return new Entity\UserGServer(
|
||||
$uid,
|
||||
$gsid,
|
||||
false,
|
||||
$gserver,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2023, the Friendica project
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Friendica\User\Settings\Repository;
|
||||
|
||||
use Exception;
|
||||
use Friendica\BaseCollection;
|
||||
use Friendica\BaseEntity;
|
||||
use Friendica\Content\Pager;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Federation\Repository\GServer;
|
||||
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||
use Friendica\Network\HTTPException\NotFoundException;
|
||||
use Friendica\User\Settings\Collection;
|
||||
use Friendica\User\Settings\Entity;
|
||||
use Friendica\User\Settings\Factory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class UserGServer extends \Friendica\BaseRepository
|
||||
{
|
||||
protected static $table_name = 'user-gserver';
|
||||
|
||||
/** @var Factory\UserGServer */
|
||||
protected $factory;
|
||||
/** @var GServer */
|
||||
protected $gserverRepository;
|
||||
|
||||
public function __construct(GServer $gserverRepository, Database $database, LoggerInterface $logger, Factory\UserGServer $factory)
|
||||
{
|
||||
parent::__construct($database, $logger, $factory);
|
||||
|
||||
$this->gserverRepository = $gserverRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an existing UserGServer entity or create one on the fly
|
||||
*
|
||||
* @param int $uid
|
||||
* @param int $gsid
|
||||
* @param bool $hydrate Populate the related GServer entity
|
||||
* @return Entity\UserGServer
|
||||
*/
|
||||
public function getOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): Entity\UserGServer
|
||||
{
|
||||
try {
|
||||
return $this->selectOneByUserAndServer($uid, $gsid, $hydrate);
|
||||
} catch (NotFoundException $e) {
|
||||
return $this->factory->createFromUserAndServer($uid, $gsid, $hydrate ? $this->gserverRepository->selectOneById($gsid) : null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $uid
|
||||
* @param int $gsid
|
||||
* @param bool $hydrate Populate the related GServer entity
|
||||
* @return Entity\UserGServer
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function selectOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): Entity\UserGServer
|
||||
{
|
||||
return $this->_selectOne(['uid' => $uid, 'gsid' => $gsid], [], $hydrate);
|
||||
}
|
||||
|
||||
public function save(Entity\UserGServer $userGServer): Entity\UserGServer
|
||||
{
|
||||
$fields = [
|
||||
'uid' => $userGServer->uid,
|
||||
'gsid' => $userGServer->gsid,
|
||||
'ignored' => $userGServer->ignored,
|
||||
];
|
||||
|
||||
$this->db->insert(static::$table_name, $fields, Database::INSERT_UPDATE);
|
||||
|
||||
return $userGServer;
|
||||
}
|
||||
|
||||
public function selectByUserWithPagination(int $uid, Pager $pager): Collection\UserGServers
|
||||
{
|
||||
return $this->_select(['uid' => $uid], ['limit' => [$pager->getStart(), $pager->getItemsPerPage()]]);
|
||||
}
|
||||
|
||||
public function countByUser(int $uid): int
|
||||
{
|
||||
return $this->count(['uid' => $uid]);
|
||||
}
|
||||
|
||||
public function isIgnoredByUser(int $uid, int $gsid): bool
|
||||
{
|
||||
return $this->exists(['uid' => $uid, 'gsid' => $gsid, 'ignored' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity\UserGServer $userGServer
|
||||
* @return bool
|
||||
* @throws InternalServerErrorException in case the underlying storage cannot delete the record
|
||||
*/
|
||||
public function delete(Entity\UserGServer $userGServer): bool
|
||||
{
|
||||
try {
|
||||
return $this->db->delete(self::$table_name, ['uid' => $userGServer->uid, 'gsid' => $userGServer->gsid]);
|
||||
} catch (\Exception $exception) {
|
||||
throw new InternalServerErrorException('Cannot delete the UserGServer', $exception);
|
||||
}
|
||||
}
|
||||
|
||||
protected function _selectOne(array $condition, array $params = [], bool $hydrate = true): BaseEntity
|
||||
{
|
||||
$fields = $this->db->selectFirst(static::$table_name, [], $condition, $params);
|
||||
if (!$this->db->isResult($fields)) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
return $this->factory->createFromTableRow($fields, $hydrate ? $this->gserverRepository->selectOneById($fields['gsid']) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $condition
|
||||
* @param array $params
|
||||
* @return Collection\UserGServers
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function _select(array $condition, array $params = [], bool $hydrate = true): BaseCollection
|
||||
{
|
||||
$rows = $this->db->selectToArray(static::$table_name, [], $condition, $params);
|
||||
|
||||
$Entities = new Collection\UserGServers();
|
||||
foreach ($rows as $fields) {
|
||||
$Entities[] = $this->factory->createFromTableRow($fields, $hydrate ? $this->gserverRepository->selectOneById($fields['gsid']) : null);
|
||||
}
|
||||
|
||||
return $Entities;
|
||||
}
|
||||
|
||||
public function listIgnoredByUser(int $uid): Collection\UserGServers
|
||||
{
|
||||
return $this->_select(['uid' => $uid, 'ignored' => 1], [], false);
|
||||
}
|
||||
}
|
|
@ -56,7 +56,7 @@ use Friendica\Database\DBA;
|
|||
|
||||
// This file is required several times during the test in DbaDefinition which justifies this condition
|
||||
if (!defined('DB_UPDATE_VERSION')) {
|
||||
define('DB_UPDATE_VERSION', 1524);
|
||||
define('DB_UPDATE_VERSION', 1529);
|
||||
}
|
||||
|
||||
return [
|
||||
|
@ -159,6 +159,18 @@ return [
|
|||
"email" => ["email(64)"],
|
||||
]
|
||||
],
|
||||
"user-gserver" => [
|
||||
"comment" => "User settings about remote servers",
|
||||
"fields" => [
|
||||
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "foreign" => ["user" => "uid"], "comment" => "Owner User id"],
|
||||
"gsid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["gserver" => "id"], "comment" => "Gserver id"],
|
||||
"ignored" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "server accounts are ignored for the user"],
|
||||
],
|
||||
"indexes" => [
|
||||
"PRIMARY" => ["uid", "gsid"],
|
||||
"gsid" => ["gsid"]
|
||||
],
|
||||
],
|
||||
"item-uri" => [
|
||||
"comment" => "URI and GUID for items",
|
||||
"fields" => [
|
||||
|
@ -218,8 +230,8 @@ return [
|
|||
"archive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
|
||||
"unsearchable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact prefers to not be searchable"],
|
||||
"sensitive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact posts sensitive content"],
|
||||
"baseurl" => ["type" => "varbinary(383)", "default" => "", "comment" => "baseurl of the contact"],
|
||||
"gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID"],
|
||||
"baseurl" => ["type" => "varbinary(383)", "default" => "", "comment" => "baseurl of the contact from the gserver record, can be missing"],
|
||||
"gsid" => ["type" => "int unsigned", "foreign" => ["gserver" => "id", "on delete" => "restrict"], "comment" => "Global Server ID, can be missing"],
|
||||
"bd" => ["type" => "date", "not null" => "1", "default" => DBA::NULL_DATE, "comment" => ""],
|
||||
// User depending fields
|
||||
"reason" => ["type" => "text", "comment" => ""],
|
||||
|
@ -1583,7 +1595,7 @@ return [
|
|||
"profile-name" => ["type" => "varchar(255)", "comment" => "Deprecated"],
|
||||
"is-default" => ["type" => "boolean", "comment" => "Deprecated"],
|
||||
"hide-friends" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide friend list from viewers of this profile"],
|
||||
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
|
||||
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Unused in favor of user.username"],
|
||||
"pdesc" => ["type" => "varchar(255)", "comment" => "Deprecated"],
|
||||
"dob" => ["type" => "varchar(32)", "not null" => "1", "default" => "0000-00-00", "comment" => "Day of birth"],
|
||||
"address" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
|
||||
|
|
|
@ -185,6 +185,7 @@
|
|||
"author-hidden" => ["author", "hidden"],
|
||||
"author-updated" => ["author", "updated"],
|
||||
"author-gsid" => ["author", "gsid"],
|
||||
"author-baseurl" => ["author", "baseurl"],
|
||||
"owner-id" => ["post-user", "owner-id"],
|
||||
"owner-uri-id" => ["owner", "uri-id"],
|
||||
"owner-link" => ["owner", "url"],
|
||||
|
@ -197,6 +198,7 @@
|
|||
"owner-blocked" => ["owner", "blocked"],
|
||||
"owner-hidden" => ["owner", "hidden"],
|
||||
"owner-updated" => ["owner", "updated"],
|
||||
"owner-gsid" => ["owner", "gsid"],
|
||||
"owner-contact-type" => ["owner", "contact-type"],
|
||||
"causer-id" => ["post-user", "causer-id"],
|
||||
"causer-uri-id" => ["causer", "uri-id"],
|
||||
|
@ -209,6 +211,7 @@
|
|||
"causer-network" => ["causer", "network"],
|
||||
"causer-blocked" => ["causer", "blocked"],
|
||||
"causer-hidden" => ["causer", "hidden"],
|
||||
"causer-gsid" => ["causer", "gsid"],
|
||||
"causer-contact-type" => ["causer", "contact-type"],
|
||||
"postopts" => ["post-delivery-data", "postopts"],
|
||||
"inform" => ["post-delivery-data", "inform"],
|
||||
|
@ -340,6 +343,7 @@
|
|||
"contact-pending" => ["contact", "pending"],
|
||||
"contact-rel" => ["contact", "rel"],
|
||||
"contact-uid" => ["contact", "uid"],
|
||||
"contact-gsid" => ["contact", "gsid"],
|
||||
"contact-contact-type" => ["contact", "contact-type"],
|
||||
"writable" => "IF (`post-user`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`)",
|
||||
"self" => ["contact", "self"],
|
||||
|
@ -375,6 +379,7 @@
|
|||
"owner-blocked" => ["owner", "blocked"],
|
||||
"owner-hidden" => ["owner", "hidden"],
|
||||
"owner-updated" => ["owner", "updated"],
|
||||
"owner-gsid" => ["owner", "gsid"],
|
||||
"owner-contact-type" => ["owner", "contact-type"],
|
||||
"causer-id" => ["post-thread-user", "causer-id"],
|
||||
"causer-uri-id" => ["causer", "uri-id"],
|
||||
|
@ -387,6 +392,7 @@
|
|||
"causer-network" => ["causer", "network"],
|
||||
"causer-blocked" => ["causer", "blocked"],
|
||||
"causer-hidden" => ["causer", "hidden"],
|
||||
"causer-gsid" => ["causer", "gsid"],
|
||||
"causer-contact-type" => ["causer", "contact-type"],
|
||||
"postopts" => ["post-delivery-data", "postopts"],
|
||||
"inform" => ["post-delivery-data", "inform"],
|
||||
|
@ -540,6 +546,7 @@
|
|||
"owner-hidden" => ["owner", "hidden"],
|
||||
"owner-updated" => ["owner", "updated"],
|
||||
"owner-contact-type" => ["owner", "contact-type"],
|
||||
"owner-gsid" => ["owner", "gsid"],
|
||||
"causer-id" => ["post", "causer-id"],
|
||||
"causer-uri-id" => ["causer", "uri-id"],
|
||||
"causer-link" => ["causer", "url"],
|
||||
|
@ -552,6 +559,7 @@
|
|||
"causer-blocked" => ["causer", "blocked"],
|
||||
"causer-hidden" => ["causer", "hidden"],
|
||||
"causer-contact-type" => ["causer", "contact-type"],
|
||||
"causer-gsid" => ["causer", "gsid"],
|
||||
"question-id" => ["post-question", "id"],
|
||||
"question-multiple" => ["post-question", "multiple"],
|
||||
"question-voters" => ["post-question", "voters"],
|
||||
|
@ -680,6 +688,7 @@
|
|||
"owner-blocked" => ["owner", "blocked"],
|
||||
"owner-hidden" => ["owner", "hidden"],
|
||||
"owner-updated" => ["owner", "updated"],
|
||||
"owner-gsid" => ["owner", "gsid"],
|
||||
"owner-contact-type" => ["owner", "contact-type"],
|
||||
"causer-id" => ["post-thread", "causer-id"],
|
||||
"causer-uri-id" => ["causer", "uri-id"],
|
||||
|
@ -692,6 +701,7 @@
|
|||
"causer-network" => ["causer", "network"],
|
||||
"causer-blocked" => ["causer", "blocked"],
|
||||
"causer-hidden" => ["causer", "hidden"],
|
||||
"causer-gsid" => ["causer", "gsid"],
|
||||
"causer-contact-type" => ["causer", "contact-type"],
|
||||
"question-id" => ["post-question", "id"],
|
||||
"question-multiple" => ["post-question", "multiple"],
|
||||
|
@ -804,18 +814,16 @@
|
|||
"contact-type" => ["ownercontact", "contact-type"],
|
||||
],
|
||||
"query" => "FROM `post-user`
|
||||
INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid`
|
||||
INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid`
|
||||
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id`
|
||||
STRAIGHT_JOIN `contact` AS `authorcontact` ON `authorcontact`.`id` = `post-thread-user`.`author-id`
|
||||
STRAIGHT_JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread-user`.`owner-id`
|
||||
LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-thread-user`.`uid` AND `author`.`cid` = `post-thread-user`.`author-id`
|
||||
LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-thread-user`.`uid` AND `owner`.`cid` = `post-thread-user`.`owner-id`
|
||||
WHERE `post-user`.`visible` AND NOT `post-user`.`deleted`
|
||||
AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
|
||||
AND (`post-user`.`hidden` IS NULL OR NOT `post-user`.`hidden`)
|
||||
AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked`
|
||||
AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
|
||||
AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`)"
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`)"
|
||||
],
|
||||
"network-thread-view" => [
|
||||
"fields" => [
|
||||
|
@ -836,14 +844,12 @@
|
|||
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id`
|
||||
STRAIGHT_JOIN `contact` AS `authorcontact` ON `authorcontact`.`id` = `post-thread-user`.`author-id`
|
||||
STRAIGHT_JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread-user`.`owner-id`
|
||||
LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-thread-user`.`uid` AND `author`.`cid` = `post-thread-user`.`author-id`
|
||||
LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-thread-user`.`uid` AND `owner`.`cid` = `post-thread-user`.`owner-id`
|
||||
WHERE `post-user`.`visible` AND NOT `post-user`.`deleted`
|
||||
AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
|
||||
AND (`post-thread-user`.`hidden` IS NULL OR NOT `post-thread-user`.`hidden`)
|
||||
AND NOT `authorcontact`.`blocked` AND NOT `ownercontact`.`blocked`
|
||||
AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
|
||||
AND (`owner`.`blocked` IS NULL OR NOT `owner`.`blocked`)"
|
||||
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
|
||||
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`)"
|
||||
],
|
||||
"owner-view" => [
|
||||
"fields" => [
|
||||
|
|
|
@ -639,6 +639,10 @@ return [
|
|||
],
|
||||
|
||||
'/settings' => [
|
||||
'/server' => [
|
||||
'[/]' => [Module\Settings\Server\Index::class, [R::GET, R::POST]],
|
||||
'/{gsid:\d+}/{action}' => [Module\Settings\Server\Action::class, [R::GET, R::POST]],
|
||||
],
|
||||
'[/]' => [Module\Settings\Account::class, [R::GET, R::POST]],
|
||||
'/account' => [
|
||||
'[/]' => [Module\Settings\Account::class, [R::GET, R::POST]],
|
||||
|
|
28
update.php
28
update.php
|
@ -1349,3 +1349,31 @@ function update_1524(): int
|
|||
|
||||
return Update::SUCCESS;
|
||||
}
|
||||
|
||||
function update_1525(): int
|
||||
{
|
||||
// Use expected value for user.username
|
||||
if (!DBA::e('UPDATE `user` u
|
||||
JOIN `profile` p
|
||||
ON p.`uid` = u.`uid`
|
||||
SET u.`username` = p.`name`
|
||||
WHERE p.`name` != ""')) {
|
||||
return Update::FAILED;
|
||||
}
|
||||
|
||||
// Blank out deprecated field profile.name to avoid future confusion
|
||||
if (!DBA::e('UPDATE `profile` p
|
||||
SET p.`name` = ""')) {
|
||||
return Update::FAILED;
|
||||
}
|
||||
|
||||
// Update users' self-contact name if needed
|
||||
if (!DBA::e('UPDATE `contact` c
|
||||
JOIN `user` u
|
||||
ON u.`uid` = c.`uid` AND c.`self` = 1
|
||||
SET c.`name` = u.`username`')) {
|
||||
return Update::FAILED;
|
||||
}
|
||||
|
||||
return Update::SUCCESS;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -57,7 +57,7 @@
|
|||
{{if $c[0]['total'] > 0}}
|
||||
<tr>
|
||||
<th>{{$c[0]['platform']}}</th>
|
||||
<th><strong>{{$c[0]['total']}}</strong></td>
|
||||
<th><strong>{{$c[0]['total']}}</strong></th>
|
||||
<td>{{$c[0]['network']}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -1,121 +1,131 @@
|
|||
<h1>{{$banner}}</h1>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
//$('.toggle-section-content + .toggle-section-content').hide();
|
||||
$('.js-section-toggler').click(function () {
|
||||
$('.toggle-section-content').hide();
|
||||
$(this).parents('.toggle-section').find('.toggle-section-content').toggle();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{{$default nofilter}}
|
||||
<h1>{{$l10n.banner}}</h1>
|
||||
|
||||
<div id="profile-edit-links">
|
||||
<ul>
|
||||
<li><a href="settings/profile/photo" id="profile-photo_upload-link" title="{{$profpic}}">{{$profpic}}</a></li>
|
||||
<li><a href="profile/{{$nickname}}/profile" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
|
||||
<li><a class="btn" href="profile/{{$nickname}}/profile" id="profile-edit-view-link">{{$l10n.viewprof}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="profile-edit-links-end"></div>
|
||||
|
||||
<div id="profile-edit-wrapper">
|
||||
<form id="profile-edit-form" name="form1" action="settings/profiles" method="post">
|
||||
<form enctype="multipart/form-data" action="settings/profile/photo" method="post">
|
||||
<input type="hidden" name="form_security_token" value="{{$form_security_token_photo}}">
|
||||
|
||||
<!-- Profile picture -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$l10n.picture_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
|
||||
<div id="profile-photo-upload-wrapper">
|
||||
<label id="profile-photo-upload-label" for="profile-photo-upload">{{$l10n.profile_photo}}:</label>
|
||||
<input name="userfile" type="file" id="profile-photo-upload" size="48"/>
|
||||
</div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<button type="submit" name="submit" class="profile-edit-submit-button">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form id="profile-edit-form" name="form1" action="" method="post">
|
||||
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
|
||||
|
||||
<div id="profile-edit-name-wrapper">
|
||||
<label id="profile-edit-name-label" for="profile-edit-name">{{$name.1}} </label>
|
||||
<input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-name-end"></div>
|
||||
<div id="profile-edit-about-wrapper">
|
||||
<label id="profile-edit-about-label" for="profile-edit-about">{{$about.1}} </label>
|
||||
<input type="text" size="32" name="about" id="profile-edit-about" value="{{$about.1}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-about-end"></div>
|
||||
<div id="profile-edit-dob-wrapper">
|
||||
{{$dob nofilter}}
|
||||
</div>
|
||||
<div id="profile-edit-dob-end"></div>
|
||||
{{$hide_friends nofilter}}
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
<div id="profile-edit-address-wrapper">
|
||||
<label id="profile-edit-address-label" for="profile-edit-address">{{$address.1}} </label>
|
||||
<input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-address-end"></div>
|
||||
<div id="profile-edit-locality-wrapper">
|
||||
<label id="profile-edit-locality-label" for="profile-edit-locality">{{$locality.1}} </label>
|
||||
<input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-locality-end"></div>
|
||||
<div id="profile-edit-postal-code-wrapper">
|
||||
<label id="profile-edit-postal-code-label" for="profile-edit-postal-code">{{$postal_code.1}} </label>
|
||||
<input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-postal-code-end"></div>
|
||||
<div id="profile-edit-country-name-wrapper">
|
||||
<label id="profile-edit-country-name-label" for="profile-edit-country-name">{{$country_name.1}} </label>
|
||||
<select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
|
||||
<option selected="selected">{{$country_name.2}}</option>
|
||||
<option>temp</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="profile-edit-country-name-end"></div>
|
||||
<div id="profile-edit-region-wrapper">
|
||||
<label id="profile-edit-region-label" for="profile-edit-region">{{$region.1}} </label>
|
||||
<select name="region" id="profile-edit-region" onChange="Update_Globals();">
|
||||
<option selected="selected">{{$region.2}}</option>
|
||||
<option>temp</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="profile-edit-region-end"></div>
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
<div id="profile-edit-homepage-wrapper">
|
||||
<label id="profile-edit-homepage-label" for="profile-edit-homepage">{{$homepage.1}} </label>
|
||||
<input type="url" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-homepage-desc">{{$homepage.3}}</div>
|
||||
<div id="profile-edit-homepage-end"></div>
|
||||
<div id="profile-edit-xmpp-wrapper">
|
||||
<label id="profile-edit-xmpp-label" for="profile-edit-xmpp">{{$xmpp.1}} </label>
|
||||
<input type="text" size="32" name="xmpp" id="profile-edit-xmpp" title="{{$lbl_ex2}}" value="{{$xmpp.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
|
||||
<div id="profile-edit-xmpp-end"></div>
|
||||
<div id="profile-edit-matrix-wrapper">
|
||||
<label id="profile-edit-matrix-label" for="profile-edit-matrix">{{$matrix.1}} </label>
|
||||
<input type="text" size="32" name="matrix" id="profile-edit-matrix" title="{{$lbl_ex2}}" value="{{$matrix.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-matrix-desc">{{$matrix.3}}</div>
|
||||
<div id="profile-edit-matrix-end"></div>
|
||||
<div id="profile-edit-pubkeywords-wrapper">
|
||||
<label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords">{{$pub_keywords.1}} </label>
|
||||
<input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
|
||||
<div id="profile-edit-pubkeywords-end"></div>
|
||||
<div id="profile-edit-prvkeywords-wrapper">
|
||||
<label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords">{{$prv_keywords.1}} </label>
|
||||
<input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
|
||||
<div id="profile-edit-prvkeywords-end"></div>
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
<!-- Basic information -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$l10n.personal_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
|
||||
<h2>{{$lbl_custom_fields_section}}</h2>
|
||||
{{$custom_fields_description nofilter}}
|
||||
<div id="profile-custom-fields">
|
||||
{{foreach $custom_fields as $custom_field}}
|
||||
{{include file="settings/profile/field/edit.tpl" profile_field=$custom_field}}
|
||||
{{/foreach}}
|
||||
</div>
|
||||
{{include file="field_input.tpl" field=$username}}
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
{{include file="field_textarea.tpl" field=$about}}
|
||||
|
||||
{{include file="field_input.tpl" field=$xmpp}}
|
||||
|
||||
{{include file="field_input.tpl" field=$matrix}}
|
||||
|
||||
{{include file="field_input.tpl" field=$homepage}}
|
||||
|
||||
<div id="profile-edit-dob-wrapper">
|
||||
{{$dob nofilter}}
|
||||
</div>
|
||||
<div id="profile-edit-dob-end"></div>
|
||||
|
||||
{{$hide_friends nofilter}}
|
||||
|
||||
{{include file="field_input.tpl" field=$pub_keywords}}
|
||||
|
||||
{{include file="field_input.tpl" field=$prv_keywords}}
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<button type="submit" name="submit" class="profile-edit-submit-button">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- About you -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$l10n.location_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
|
||||
{{include file="field_input.tpl" field=$address}}
|
||||
|
||||
{{include file="field_input.tpl" field=$locality}}
|
||||
|
||||
{{include file="field_input.tpl" field=$postal_code}}
|
||||
|
||||
<div id="profile-edit-country-name-wrapper">
|
||||
<label id="profile-edit-country-name-label" for="profile-edit-country-name">{{$country_name.1}} </label>
|
||||
<select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
|
||||
<option selected="selected">{{$country_name.2}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="profile-edit-country-name-end"></div>
|
||||
|
||||
<div id="profile-edit-region-wrapper">
|
||||
<label id="profile-edit-region-label" for="profile-edit-region">{{$region.1}} </label>
|
||||
<select name="region" id="profile-edit-region" onChange="Update_Globals();">
|
||||
<option selected="selected">{{$region.2}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="profile-edit-region-end"></div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<button type="submit" name="submit" class="profile-edit-submit-button">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Interests -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$l10n.custom_fields_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
{{$custom_fields_description nofilter}}
|
||||
<div id="profile-custom-fields">
|
||||
{{foreach $custom_fields as $custom_field}}
|
||||
{{include file="settings/profile/field/edit.tpl" profile_field=$custom_field}}
|
||||
{{/foreach}}
|
||||
</div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<button type="submit" name="submit" class="profile-edit-submit-button">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
</form>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<div id="settings-server" class="generic-page-wrapper">
|
||||
<h1>{{$l10n.title}}</h1>
|
||||
|
||||
<form action="{{$action}}" method="POST">
|
||||
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
|
||||
<input type="hidden" name="redirect_url" value="settings/server">
|
||||
|
||||
<p>{{$l10n.action}}</p>
|
||||
|
||||
{{if $l10n.desc}}
|
||||
<p>{{$l10n.desc}}</p>
|
||||
{{/if}}
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{$l10n.siteName}}</th>
|
||||
<td>{{$GServer->siteName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{$l10n.siteUrl}}</th>
|
||||
<td><a href="{{$GServer->url}}">{{$GServer->url}}</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><button type="submit" class="btn btn-primary">{{$l10n.submit}}</button></p>
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,45 @@
|
|||
<div id="settings-server" class="generic-page-wrapper">
|
||||
<h1>{{$l10n.title}} ({{$count}})</h1>
|
||||
|
||||
<p>{{$l10n.desc nofilter}}</p>
|
||||
|
||||
{{$paginate nofilter}}
|
||||
|
||||
<form action="" method="POST">
|
||||
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
|
||||
|
||||
<p><button type="submit" class="btn btn-primary">{{$l10n.submit}}</button></p>
|
||||
|
||||
<table class="table table-striped table-condensed table-bordered">
|
||||
<tr>
|
||||
<th>{{$l10n.siteName}}</th>
|
||||
<th><span title="{{$l10n.ignored_title}}">{{$l10n.ignored}} <i class="fa fa-question-circle icon-question-sign"></i></span></th>
|
||||
<th>
|
||||
<span title="{{$l10n.delete_title}}">
|
||||
<i class="fa fa-trash icon-trash" aria-hidden="true" title="{{$l10n.delete}}"></i>
|
||||
<span class="sr-only">{{$l10n.delete}}</span>
|
||||
<i class="fa fa-question-circle icon-question-sign"></i>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
{{foreach $servers as $index => $server}}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{$server->gserver->url}}">{{($server->gserver->siteName) ? $server->gserver->siteName : $server->gserver->url}} <i class="fa fa-external-link"></i></a>
|
||||
</td>
|
||||
<td>
|
||||
{{include file="field_checkbox.tpl" field=$ignoredCheckboxes[$index]}}
|
||||
</td>
|
||||
<td>
|
||||
{{include file="field_checkbox.tpl" field=$deleteCheckboxes[$index]}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/foreach}}
|
||||
|
||||
</table>
|
||||
<p><button type="submit" class="btn btn-primary">{{$l10n.submit}}</button></p>
|
||||
</form>
|
||||
|
||||
{{$paginate nofilter}}
|
||||
</div>
|
|
@ -1,5 +1,11 @@
|
|||
<div id="exception" class="generic-page-wrapper">
|
||||
<img class="hare" src="images/friendica-404_svg_flexy-o-hare.png"/>
|
||||
<h1>{{$title}}</h1>
|
||||
{{$message nofilter}}
|
||||
<h1>{{$l10n.title}}</h1>
|
||||
<p>{{$l10n.desc1}}</p>
|
||||
<p>{{$l10n.desc2}}</p>
|
||||
<ul>
|
||||
{{foreach $l10n.reasons as $reason}}
|
||||
<li>{{$reason}}</li>
|
||||
{{/foreach}}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -210,6 +210,10 @@ function confirmCollapse() {
|
|||
return confirm(aStr.collapseAuthor);
|
||||
}
|
||||
|
||||
function confirmIgnoreServer() {
|
||||
return confirm(aStr.ignoreServer + "\n" + aStr.ignoreServerDesc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide and removes an item element from the DOM after the deletion url is
|
||||
* successful, restore it else.
|
||||
|
@ -325,4 +329,34 @@ function collapseAuthor(url, elementId) {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ignore author server
|
||||
*
|
||||
* @param {string} url The server ignore URL
|
||||
* @param {string} elementId The DOM id of the item element
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function ignoreServer(url, elementId) {
|
||||
if (confirmIgnoreServer()) {
|
||||
$("body").css("cursor", "wait");
|
||||
|
||||
var $el = $(document.getElementById(elementId));
|
||||
|
||||
$el.fadeTo("fast", 0.33, function () {
|
||||
$.post(url)
|
||||
.then(function () {
|
||||
$el.remove();
|
||||
})
|
||||
.fail(function () {
|
||||
// @todo Show related error message
|
||||
$el.fadeTo("fast", 1);
|
||||
})
|
||||
.always(function () {
|
||||
$("body").css("cursor", "auto");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
// @license-end
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
{{if $ignored}}<li><div id="ignore-message">{{$ignored}}</div></li>{{/if}}
|
||||
{{if $collapsed}}<li><div id="collapse-message">{{$collapsed}}</div></li>{{/if}}
|
||||
{{if $archived}}<li><div id="archive-message">{{$archived}}</div></li>{{/if}}
|
||||
{{if $serverIgnored}}<li><div id="serverIgnored-message">{{$serverIgnored}} <a href="settings/server">{{$manageServers}}</a></div></li>{{/if}}
|
||||
</ul>
|
||||
</div> {{* End of contact-edit-status-wrapper *}}
|
||||
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
They are loaded into the html <head> so that js functions can use them *}}
|
||||
<script type="text/javascript">
|
||||
const aStr = {
|
||||
delitem : "{{$l10n.delitem|escape:'javascript' nofilter}}",
|
||||
blockAuthor : "{{$l10n.blockAuthor|escape:'javascript' nofilter}}",
|
||||
ignoreAuthor : "{{$l10n.ignoreAuthor|escape:'javascript' nofilter}}",
|
||||
collapseAuthor : "{{$l10n.collapseAuthor|escape:'javascript' nofilter}}",
|
||||
delitem : "{{$l10n.delitem|escape:'javascript' nofilter}}",
|
||||
blockAuthor : "{{$l10n.blockAuthor|escape:'javascript' nofilter}}",
|
||||
ignoreAuthor : "{{$l10n.ignoreAuthor|escape:'javascript' nofilter}}",
|
||||
collapseAuthor : "{{$l10n.collapseAuthor|escape:'javascript' nofilter}}",
|
||||
ignoreServer : "{{$l10n.ignoreServer|escape:'javascript' nofilter}}",
|
||||
ignoreServerDesc : "{{$l10n.ignoreServerDesc|escape:'javascript' nofilter}}",
|
||||
};
|
||||
const aActErr = {
|
||||
like : "{{$l10n.likeError|escape:'javascript' nofilter}}",
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<div class="generic-page-wrapper">
|
||||
<h1>{{$banner}}</h1>
|
||||
<h2>{{$l10n.banner}}</h2>
|
||||
|
||||
{{* The actions dropdown which can performed to the current profile *}}
|
||||
<div id="profile-edit-links">
|
||||
<ul class="nav nav-pills preferences">
|
||||
<li class="dropdown pull-right">
|
||||
<button type="button" class="btn btn-link dropdown-toggle" id="profile-edit-links-dropdown" data-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa fa-angle-down" aria-hidden="true"></i> {{$profile_action}}
|
||||
<i class="fa fa-angle-down" aria-hidden="true"></i> {{$l10n.profile_action}}
|
||||
</button>
|
||||
<ul class="dropdown-menu pull-right" role="menu" aria-labelledby="profile-edit-links-dropdown">
|
||||
<li role="presentation"><a role="menuitem" href="{{$profpiclink}}" id="profile-photo_upload-link" title="{{$profpic}}"><i class="fa fa-user" aria-hidden="true"></i> {{$profpic}}</a></li>
|
||||
<li role="presentation"><button role="menuitem" type="button" class="btn-link" id="profile-photo_upload-link-new" title="{{$lbl_profile_photo}}" onclick="openClose('profile-photo-upload-section');"><i class="fa fa-user" aria-hidden="true"></i> {{$lbl_profile_photo}}</button></li>
|
||||
<li role="presentation"><a role="menuitem" href="{{$profpiclink}}" id="profile-photo_upload-link"><i class="fa fa-user" aria-hidden="true"></i> {{$l10n.profpic}}</a></li>
|
||||
<li role="presentation"><button role="menuitem" type="button" class="btn-link" id="profile-photo_upload-link-new" onclick="openClose('profile-photo-upload-section');"><i class="fa fa-user" aria-hidden="true"></i> {{$l10n.profile_photo}}</button></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li role="presentation"><a role="menuitem" href="profile/{{$nickname}}/profile" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
|
||||
<li role="presentation"><a role="menuitem" href="profile/{{$nickname}}/profile" id="profile-edit-view-link">{{$l10n.viewprof}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -26,12 +26,12 @@
|
|||
<div id="profile-photo-upload-section" class="panel">
|
||||
<a id="profile-photo-upload-close" class="close pull-right" onclick="openClose('profile-photo-upload-section');"><i class="fa fa-times" aria-hidden="true"></i></a>
|
||||
<div id="profile-photo-upload-wrapper">
|
||||
<label id="profile-photo-upload-label" for="profile-photo-upload">{{$lbl_profile_photo}}:</label>
|
||||
<label id="profile-photo-upload-label" for="profile-photo-upload">{{$l10n.profile_photo}}:</label>
|
||||
<input name="userfile" type="file" id="profile-photo-upload" size="48" />
|
||||
</div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper pull-right">
|
||||
<button type="submit" name="submit" class="profile-edit-submit-button btn btn-primary" value="{{$submit}}">{{$submit}}</button>
|
||||
<button type="submit" name="submit" class="profile-edit-submit-button btn btn-primary">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
@ -53,14 +53,14 @@
|
|||
<div class="section-subtitle-wrapper panel-heading" role="tab" id="personal">
|
||||
<h2>
|
||||
<button class="btn-link accordion-toggle" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#personal-collapse" aria-expanded="true" aria-controls="personal-collapse">
|
||||
{{$lbl_personal_section}}
|
||||
{{$l10n.personal_section}}
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
{{* for the $detailed_profile we use bootstraps collapsable panel-groups to have expandable groups *}}
|
||||
<div id="personal-collapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="personal">
|
||||
<div class="panel-body">
|
||||
{{include file="field_input.tpl" field=$name}}
|
||||
{{include file="field_input.tpl" field=$username}}
|
||||
|
||||
{{include file="field_textarea.tpl" field=$about}}
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
|||
{{$hide_friends nofilter}}
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
|
||||
<button type="submit" name="submit" class="btn btn-primary">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -79,7 +79,7 @@
|
|||
<div class="section-subtitle-wrapper panel-heading" role="tab" id="location">
|
||||
<h2>
|
||||
<button class="btn-link accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#location-collapse" aria-expanded="false" aria-controls="location-collapse">
|
||||
{{$lbl_location_section}}
|
||||
{{$l10n.location_section}}
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
|
@ -109,7 +109,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
|
||||
<button type="submit" name="submit" class="btn btn-primary">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -119,7 +119,7 @@
|
|||
<div class="section-subtitle-wrapper panel-heading" role="tab" id="miscellaneous">
|
||||
<h2>
|
||||
<button class="btn-link accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#miscellaneous-collapse" aria-expanded="false" aria-controls="miscellaneous-collapse">
|
||||
{{$lbl_miscellaneous_section}}
|
||||
{{$l10n.miscellaneous_section}}
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
|
@ -136,7 +136,7 @@
|
|||
{{include file="field_input.tpl" field=$prv_keywords}}
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
|
||||
<button type="submit" name="submit" class="btn btn-primary">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -146,7 +146,7 @@
|
|||
<div class="section-subtitle-wrapper panel-heading" role="tab" id="custom-fields">
|
||||
<h2>
|
||||
<button class="btn-link accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#custom-fields-collapse" aria-expanded="false" aria-controls="custom-fields-collapse">
|
||||
{{$lbl_custom_fields_section}}
|
||||
{{$l10n.custom_fields_section}}
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
|
@ -160,7 +160,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
|
||||
<button type="submit" name="submit" class="btn btn-primary">{{$l10n.submit}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -401,13 +401,17 @@ as the value of $top_child_total (this is done at the end of this file)
|
|||
{{/if}}
|
||||
{{if $item.ignore_author}}
|
||||
<li role="menuitem">
|
||||
<a class="btn-link navicon ignore" href="javascript:ignoreAuthor('item/ignore/{{$item.id}}', 'item-{{$item.guid}}');" title="{{$item.ignore_author.label}}"><i class="fa fa-ban" aria-hidden="true"></i> {{$item.ignore_author.label}}</a>
|
||||
<a class="btn-link navicon ignore" href="javascript:ignoreAuthor('item/ignore/{{$item.id}}', 'item-{{$item.guid}}');" title="{{$item.ignore_author.label}}"><i class="fa fa-eye-slash" aria-hidden="true"></i> {{$item.ignore_author.label}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{if $item.collapse}}
|
||||
<li role="menuitem">
|
||||
<a class="btn-link navicon collapse" href="javascript:collapseAuthor('item/collapse/{{$item.id}}', 'item-{{$item.guid}}');" title="{{$item.collapse.label}}"><i class="fa fa-ban" aria-hidden="true"></i> {{$item.collapse.label}}</a>
|
||||
<a class="btn-link navicon collapse" href="javascript:collapseAuthor('item/collapse/{{$item.id}}', 'item-{{$item.guid}}');" title="{{$item.collapse.label}}"><i class="fa fa-minus-square" aria-hidden="true"></i> {{$item.collapse.label}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{if $item.ignore_server}}
|
||||
<li role="menuitem">
|
||||
<a class="btn-link navicon ignoreServer" href="javascript:ignoreServer('settings/server/{{$item.author_gsid}}/ignore', 'item-{{$item.guid}}');" title="{{$item.ignore_server.label}}"><i class="fa fa-eye-slash" aria-hidden="true"></i> {{$item.ignore_server.label}}</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{if $item.report}}
|
||||
|
|
|
@ -3281,3 +3281,7 @@ fbrowser.photo .photo-album-image-wrapper { margin-left: 10px; }
|
|||
#colorbox img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#settings-server td + td {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
<script>
|
||||
$(document).ready(function () {
|
||||
//$('.toggle-section-content + .toggle-section-content').hide();
|
||||
$('.js-section-toggler').click(function () {
|
||||
$('.toggle-section-content').hide();
|
||||
$(this).parents('.toggle-section').find('.toggle-section-content').toggle();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<h1>{{$banner}}</h1>
|
||||
|
||||
<div id="profile-edit-links">
|
||||
<ul>
|
||||
<li><a class="btn" href="profile/{{$nickname}}/profile" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="profile-edit-links-end"></div>
|
||||
|
||||
<div id="profile-edit-wrapper">
|
||||
<form enctype="multipart/form-data" action="settings/profile/photo" method="post">
|
||||
<input type="hidden" name="form_security_token" value="{{$form_security_token_photo}}">
|
||||
|
||||
<!-- Profile picture -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_picture_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
|
||||
<div id="profile-photo-upload-wrapper">
|
||||
<label id="profile-photo-upload-label" for="profile-photo-upload">{{$lbl_profile_photo}}:</label>
|
||||
<input name="userfile" type="file" id="profile-photo-upload" size="48"/>
|
||||
</div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form id="profile-edit-form" name="form1" action="" method="post">
|
||||
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
|
||||
|
||||
<!-- Basic information -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_personal_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
|
||||
<div id="profile-edit-name-wrapper">
|
||||
<label id="profile-edit-name-label" for="profile-edit-name">{{$name.1}} </label>
|
||||
<input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-name-end"></div>
|
||||
|
||||
<div id="profile-edit-about-wrapper">
|
||||
<label id="profile-edit-about-label" for="profile-edit-about">{{$about.1}} </label>
|
||||
<input type="text" size="32" name="about" id="profile-edit-about" value="{{$about.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-about-end"></div>
|
||||
|
||||
<div id="profile-edit-xmpp-wrapper">
|
||||
<label id="profile-edit-xmpp-label" for="profile-edit-xmpp">{{$xmpp.1}} </label>
|
||||
<input type="text" size="32" name="xmpp" id="profile-edit-xmpp" value="{{$xmpp.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
|
||||
<div id="profile-edit-xmpp-end"></div>
|
||||
|
||||
<div id="profile-edit-matrix-wrapper">
|
||||
<label id="profile-edit-matrix-label" for="profile-edit-matrix">{{$matrix.1}} </label>
|
||||
<input type="text" size="32" name="matrix" id="profile-edit-matrix" value="{{$matrix.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-matrix-desc">{{$matrix.3}}</div>
|
||||
<div id="profile-edit-matrix-end"></div>
|
||||
|
||||
<div id="profile-edit-homepage-wrapper">
|
||||
<label id="profile-edit-homepage-label" for="profile-edit-homepage">{{$homepage.1}} </label>
|
||||
<input type="text" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-homepage-desc">{{$homepage.3}}</div>
|
||||
<div id="profile-edit-homepage-end"></div>
|
||||
|
||||
<div id="profile-edit-dob-wrapper">
|
||||
{{$dob nofilter}}
|
||||
</div>
|
||||
<div id="profile-edit-dob-end"></div>
|
||||
|
||||
{{$hide_friends nofilter}}
|
||||
|
||||
<div id="profile-edit-pubkeywords-wrapper">
|
||||
<label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords">{{$pub_keywords.1}} </label>
|
||||
<input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
|
||||
<div id="profile-edit-pubkeywords-end"></div>
|
||||
|
||||
<div id="profile-edit-prvkeywords-wrapper">
|
||||
<label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords">{{$prv_keywords.1}} </label>
|
||||
<input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
|
||||
<div id="profile-edit-prvkeywords-end"></div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- About you -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_location_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
|
||||
<div id="profile-edit-address-wrapper">
|
||||
<label id="profile-edit-address-label" for="profile-edit-address">{{$address.1}} </label>
|
||||
<input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-address-end"></div>
|
||||
|
||||
<div id="profile-edit-locality-wrapper">
|
||||
<label id="profile-edit-locality-label" for="profile-edit-locality">{{$locality.1}} </label>
|
||||
<input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-locality-end"></div>
|
||||
|
||||
<div id="profile-edit-postal-code-wrapper">
|
||||
<label id="profile-edit-postal-code-label" for="profile-edit-postal-code">{{$postal_code.1}} </label>
|
||||
<input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}"/>
|
||||
</div>
|
||||
<div id="profile-edit-postal-code-end"></div>
|
||||
|
||||
<div id="profile-edit-country-name-wrapper">
|
||||
<label id="profile-edit-country-name-label" for="profile-edit-country-name">{{$country_name.1}} </label>
|
||||
<select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
|
||||
<option selected="selected">{{$country_name.2}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="profile-edit-country-name-end"></div>
|
||||
|
||||
<div id="profile-edit-region-wrapper">
|
||||
<label id="profile-edit-region-label" for="profile-edit-region">{{$region.1}} </label>
|
||||
<select name="region" id="profile-edit-region" onChange="Update_Globals();">
|
||||
<option selected="selected">{{$region.2}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="profile-edit-region-end"></div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Interests -->
|
||||
<div class="toggle-section js-toggle-section">
|
||||
<h2><a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_custom_fields_section}} »</a></h2>
|
||||
<div class="js-section toggle-section-content hidden">
|
||||
{{$custom_fields_description nofilter}}
|
||||
<div id="profile-custom-fields">
|
||||
{{foreach $custom_fields as $custom_field}}
|
||||
{{include file="settings/profile/field/edit.tpl" profile_field=$custom_field}}
|
||||
{{/foreach}}
|
||||
</div>
|
||||
|
||||
<div class="profile-edit-submit-wrapper">
|
||||
<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
|
||||
</div>
|
||||
<div class="profile-edit-submit-end"></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
Fill_Country('{{$country_name.2}}');
|
||||
Fill_States('{{$region.2}}');
|
||||
</script>
|
Loading…
Reference in New Issue