Merge pull request #10860 from nupplaphil/feat/depository_profilefield
Move ProfileField to Depository Paradigm
This commit is contained in:
commit
235eab0d99
36 changed files with 1519 additions and 644 deletions
22
database.sql
22
database.sql
|
@ -1,6 +1,6 @@
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- Friendica 2021.12-dev (Siberian Iris)
|
-- Friendica 2021.12-dev (Siberian Iris)
|
||||||
-- DB_UPDATE_VERSION 1439
|
-- DB_UPDATE_VERSION 1440
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -2587,3 +2587,23 @@ CREATE VIEW `workerqueue-view` AS SELECT
|
||||||
FROM `process`
|
FROM `process`
|
||||||
INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`
|
INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`
|
||||||
WHERE NOT `workerqueue`.`done`;
|
WHERE NOT `workerqueue`.`done`;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- VIEW profile_field-view
|
||||||
|
--
|
||||||
|
DROP VIEW IF EXISTS `profile_field-view`;
|
||||||
|
CREATE VIEW `profile_field-view` AS SELECT
|
||||||
|
`profile_field`.`id` AS `id`,
|
||||||
|
`profile_field`.`uid` AS `uid`,
|
||||||
|
`profile_field`.`label` AS `label`,
|
||||||
|
`profile_field`.`value` AS `value`,
|
||||||
|
`profile_field`.`order` AS `order`,
|
||||||
|
`profile_field`.`psid` AS `psid`,
|
||||||
|
`permissionset`.`allow_cid` AS `allow_cid`,
|
||||||
|
`permissionset`.`allow_gid` AS `allow_gid`,
|
||||||
|
`permissionset`.`deny_cid` AS `deny_cid`,
|
||||||
|
`permissionset`.`deny_gid` AS `deny_gid`,
|
||||||
|
`profile_field`.`created` AS `created`,
|
||||||
|
`profile_field`.`edited` AS `edited`
|
||||||
|
FROM `profile_field`
|
||||||
|
INNER JOIN `permissionset` ON `permissionset`.`id` = `profile_field`.`psid`;
|
||||||
|
|
|
@ -87,7 +87,7 @@ class BaseCollection extends \ArrayIterator
|
||||||
*/
|
*/
|
||||||
public function column($column, $index_key = null)
|
public function column($column, $index_key = null)
|
||||||
{
|
{
|
||||||
return array_column($this->getArrayCopy(), $column, $index_key);
|
return array_column($this->getArrayCopy(true), $column, $index_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,4 +124,21 @@ class BaseCollection extends \ArrayIterator
|
||||||
{
|
{
|
||||||
return new static(array_reverse($this->getArrayCopy()), $this->getTotalCount());
|
return new static(array_reverse($this->getArrayCopy()), $this->getTotalCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*
|
||||||
|
* includes recursion for entity::toArray() function
|
||||||
|
* @see BaseEntity::toArray()
|
||||||
|
*/
|
||||||
|
public function getArrayCopy(bool $recursive = false): array
|
||||||
|
{
|
||||||
|
if (!$recursive) {
|
||||||
|
return parent::getArrayCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_map(function ($item) {
|
||||||
|
return is_object($item) ? $item->toArray() : $item;
|
||||||
|
}, parent::getArrayCopy());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,4 +53,18 @@ abstract class BaseEntity extends BaseDataTransferObject
|
||||||
|
|
||||||
return $this->$name;
|
return $this->$name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
* @return bool
|
||||||
|
* @throws HTTPException\InternalServerErrorException
|
||||||
|
*/
|
||||||
|
public function __isset($name)
|
||||||
|
{
|
||||||
|
if (!property_exists($this, $name)) {
|
||||||
|
throw new HTTPException\InternalServerErrorException('Unknown property ' . $name . ' in Entity ' . static::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !empty($this->$name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\Database\DBStructure;
|
use Friendica\Database\DBStructure;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Photo;
|
use Friendica\Model\Photo;
|
||||||
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Object\Image;
|
use Friendica\Object\Image;
|
||||||
use Friendica\Security\PermissionSet\Depository\PermissionSet;
|
use Friendica\Security\PermissionSet\Depository\PermissionSet;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
@ -278,7 +279,7 @@ class UserImport
|
||||||
$profile['id'] = DBA::lastInsertId();
|
$profile['id'] = DBA::lastInsertId();
|
||||||
}
|
}
|
||||||
|
|
||||||
DI::profileField()->migrateFromLegacyProfile($profile);
|
Profile::migrate($profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
$permissionSet = DI::permissionSet()->selectDefaultForUser($newuid);
|
$permissionSet = DI::permissionSet()->selectDefaultForUser($newuid);
|
||||||
|
|
12
src/DI.php
12
src/DI.php
|
@ -452,12 +452,14 @@ abstract class DI
|
||||||
return self::$dice->create(Security\PermissionSet\Factory\PermissionSet::class);
|
return self::$dice->create(Security\PermissionSet\Factory\PermissionSet::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function profileField(): Profile\ProfileField\Depository\ProfileField
|
||||||
* @return Repository\ProfileField
|
|
||||||
*/
|
|
||||||
public static function profileField()
|
|
||||||
{
|
{
|
||||||
return self::$dice->create(Repository\ProfileField::class);
|
return self::$dice->create(Profile\ProfileField\Depository\ProfileField::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function profileFieldFactory(): Profile\ProfileField\Factory\ProfileField
|
||||||
|
{
|
||||||
|
return self::$dice->create(Profile\ProfileField\Factory\ProfileField::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function notification(): Navigation\Notifications\Depository\Notification
|
public static function notification(): Navigation\Notifications\Depository\Notification
|
||||||
|
|
|
@ -27,8 +27,7 @@ use Friendica\Collection\Api\Mastodon\Fields;
|
||||||
use Friendica\Model\APContact;
|
use Friendica\Model\APContact;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Network\HTTPException;
|
use Friendica\Network\HTTPException;
|
||||||
use Friendica\Repository\ProfileField;
|
use Friendica\Profile\ProfileField\Depository\ProfileField as ProfileFieldDepository;
|
||||||
use Friendica\Security\PermissionSet\Depository\PermissionSet;
|
|
||||||
use ImagickException;
|
use ImagickException;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
@ -36,17 +35,17 @@ class Account extends BaseFactory
|
||||||
{
|
{
|
||||||
/** @var BaseURL */
|
/** @var BaseURL */
|
||||||
private $baseUrl;
|
private $baseUrl;
|
||||||
/** @var ProfileField */
|
/** @var ProfileFieldDepository */
|
||||||
private $profileFieldRepo;
|
private $profileFieldDepo;
|
||||||
/** @var Field */
|
/** @var Field */
|
||||||
private $mstdnFieldFactory;
|
private $mstdnFieldFactory;
|
||||||
|
|
||||||
public function __construct(LoggerInterface $logger, BaseURL $baseURL, ProfileField $profileFieldRepo, Field $mstdnFieldFactory)
|
public function __construct(LoggerInterface $logger, BaseURL $baseURL, ProfileFieldDepository $profileFieldDepo, Field $mstdnFieldFactory)
|
||||||
{
|
{
|
||||||
parent::__construct($logger);
|
parent::__construct($logger);
|
||||||
|
|
||||||
$this->baseUrl = $baseURL;
|
$this->baseUrl = $baseURL;
|
||||||
$this->profileFieldRepo = $profileFieldRepo;
|
$this->profileFieldDepo = $profileFieldDepo;
|
||||||
$this->mstdnFieldFactory = $mstdnFieldFactory;
|
$this->mstdnFieldFactory = $mstdnFieldFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ class Account extends BaseFactory
|
||||||
|
|
||||||
$self_contact = Contact::selectFirst(['uid'], ['nurl' => $publicContact['nurl'], 'self' => true]);
|
$self_contact = Contact::selectFirst(['uid'], ['nurl' => $publicContact['nurl'], 'self' => true]);
|
||||||
if (!empty($self_contact['uid'])) {
|
if (!empty($self_contact['uid'])) {
|
||||||
$profileFields = $this->profileFieldRepo->select(['uid' => $self_contact['uid'], 'psid' => PermissionSet::PUBLIC]);
|
$profileFields = $this->profileFieldDepo->selectPublicFieldsByUserId($self_contact['uid']);
|
||||||
$fields = $this->mstdnFieldFactory->createFromProfileFields($profileFields);
|
$fields = $this->mstdnFieldFactory->createFromProfileFields($profileFields);
|
||||||
} else {
|
} else {
|
||||||
$fields = new Fields();
|
$fields = new Fields();
|
||||||
|
@ -95,7 +94,7 @@ class Account extends BaseFactory
|
||||||
{
|
{
|
||||||
$publicContact = Contact::selectFirst([], ['uid' => $userId, 'self' => true]);
|
$publicContact = Contact::selectFirst([], ['uid' => $userId, 'self' => true]);
|
||||||
|
|
||||||
$profileFields = $this->profileFieldRepo->select(['uid' => $userId, 'psid' => PermissionSet::PUBLIC]);
|
$profileFields = $this->profileFieldDepo->selectPublicFieldsByUserId($userId);
|
||||||
$fields = $this->mstdnFieldFactory->createFromProfileFields($profileFields);
|
$fields = $this->mstdnFieldFactory->createFromProfileFields($profileFields);
|
||||||
|
|
||||||
$apContact = APContact::getByURL($publicContact['url'], false);
|
$apContact = APContact::getByURL($publicContact['url'], false);
|
||||||
|
|
|
@ -23,15 +23,16 @@ namespace Friendica\Factory\Api\Mastodon;
|
||||||
|
|
||||||
use Friendica\BaseFactory;
|
use Friendica\BaseFactory;
|
||||||
use Friendica\Collection\Api\Mastodon\Fields;
|
use Friendica\Collection\Api\Mastodon\Fields;
|
||||||
use Friendica\Collection\ProfileFields;
|
use Friendica\Profile\ProfileField\Collection\ProfileFields;
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Model\ProfileField;
|
use Friendica\Profile\ProfileField\Entity\ProfileField;
|
||||||
use Friendica\Network\HTTPException;
|
use Friendica\Network\HTTPException;
|
||||||
|
|
||||||
class Field extends BaseFactory
|
class Field extends BaseFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param ProfileField $profileField
|
* @param ProfileField $profileField
|
||||||
|
*
|
||||||
* @return \Friendica\Object\Api\Mastodon\Field
|
* @return \Friendica\Object\Api\Mastodon\Field
|
||||||
* @throws HTTPException\InternalServerErrorException
|
* @throws HTTPException\InternalServerErrorException
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -38,6 +38,7 @@ use Friendica\DI;
|
||||||
use Friendica\Network\HTTPException;
|
use Friendica\Network\HTTPException;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Protocol\Diaspora;
|
use Friendica\Protocol\Diaspora;
|
||||||
|
use Friendica\Security\PermissionSet\Entity\PermissionSet;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\HTTPSignature;
|
use Friendica\Util\HTTPSignature;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
|
@ -936,4 +937,86 @@ class Profile
|
||||||
|
|
||||||
return ['total' => $total, 'entries' => $profiles];
|
return ['total' => $total, 'entries' => $profiles];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrates a legacy profile to the new slimmer profile with extra custom fields.
|
||||||
|
* Multi profiles are converted to ACl-protected custom fields and deleted.
|
||||||
|
*
|
||||||
|
* @param array $profile One profile array
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public static function migrate(array $profile)
|
||||||
|
{
|
||||||
|
// Already processed, aborting
|
||||||
|
if ($profile['is-default'] === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contacts = [];
|
||||||
|
|
||||||
|
if (!$profile['is-default']) {
|
||||||
|
$contacts = Contact::selectToArray(['id'], [
|
||||||
|
'uid' => $profile['uid'],
|
||||||
|
'profile-id' => $profile['id']
|
||||||
|
]);
|
||||||
|
if (!count($contacts)) {
|
||||||
|
// No contact visibility selected defaults to user-only permission
|
||||||
|
$contacts = Contact::selectToArray(['id'], ['uid' => $profile['uid'], 'self' => true]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$permissionSet = DI::permissionSet()->selectOrCreate(
|
||||||
|
new PermissionSet(
|
||||||
|
$profile['uid'],
|
||||||
|
array_column($contacts, 'id') ?? []
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$order = 1;
|
||||||
|
|
||||||
|
$custom_fields = [
|
||||||
|
'hometown' => DI::l10n()->t('Hometown:'),
|
||||||
|
'marital' => DI::l10n()->t('Marital Status:'),
|
||||||
|
'with' => DI::l10n()->t('With:'),
|
||||||
|
'howlong' => DI::l10n()->t('Since:'),
|
||||||
|
'sexual' => DI::l10n()->t('Sexual Preference:'),
|
||||||
|
'politic' => DI::l10n()->t('Political Views:'),
|
||||||
|
'religion' => DI::l10n()->t('Religious Views:'),
|
||||||
|
'likes' => DI::l10n()->t('Likes:'),
|
||||||
|
'dislikes' => DI::l10n()->t('Dislikes:'),
|
||||||
|
'pdesc' => DI::l10n()->t('Title/Description:'),
|
||||||
|
'summary' => DI::l10n()->t('Summary'),
|
||||||
|
'music' => DI::l10n()->t('Musical interests'),
|
||||||
|
'book' => DI::l10n()->t('Books, literature'),
|
||||||
|
'tv' => DI::l10n()->t('Television'),
|
||||||
|
'film' => DI::l10n()->t('Film/dance/culture/entertainment'),
|
||||||
|
'interest' => DI::l10n()->t('Hobbies/Interests'),
|
||||||
|
'romance' => DI::l10n()->t('Love/romance'),
|
||||||
|
'work' => DI::l10n()->t('Work/employment'),
|
||||||
|
'education' => DI::l10n()->t('School/education'),
|
||||||
|
'contact' => DI::l10n()->t('Contact information and Social Networks'),
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($custom_fields as $field => $label) {
|
||||||
|
if (!empty($profile[$field]) && $profile[$field] > DBA::NULL_DATE && $profile[$field] > DBA::NULL_DATETIME) {
|
||||||
|
DI::profileField()->save(DI::profileFieldFactory()->createFromValues(
|
||||||
|
$profile['uid'],
|
||||||
|
$order,
|
||||||
|
trim($label, ':'),
|
||||||
|
$profile[$field],
|
||||||
|
$permissionSet
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile[$field] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($profile['is-default']) {
|
||||||
|
$profile['profile-name'] = null;
|
||||||
|
$profile['is-default'] = null;
|
||||||
|
DBA::update('profile', $profile, ['id' => $profile['id']]);
|
||||||
|
} else if (!empty($profile['id'])) {
|
||||||
|
DBA::delete('profile', ['id' => $profile['id']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @copyright Copyright (C) 2010-2021, 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\Model;
|
|
||||||
|
|
||||||
use Friendica\BaseModel;
|
|
||||||
use Friendica\Database\Database;
|
|
||||||
use Friendica\Network\HTTPException\NotFoundException;
|
|
||||||
use Friendica\Security\PermissionSet\Depository\PermissionSet as PermissionSetDepository;
|
|
||||||
use Friendica\Security\PermissionSet\Entity\PermissionSet;
|
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom profile field model class.
|
|
||||||
*
|
|
||||||
* Custom profile fields are user-created arbitrary profile fields that can be assigned a permission set to restrict its
|
|
||||||
* display to specific Friendica contacts as it requires magic authentication to work.
|
|
||||||
*
|
|
||||||
* @property int uid
|
|
||||||
* @property int order
|
|
||||||
* @property int psid
|
|
||||||
* @property string label
|
|
||||||
* @property string value
|
|
||||||
* @property string created
|
|
||||||
* @property string edited
|
|
||||||
* @property PermissionSet permissionSet
|
|
||||||
*/
|
|
||||||
class ProfileField extends BaseModel
|
|
||||||
{
|
|
||||||
/** @var PermissionSet */
|
|
||||||
private $permissionSet;
|
|
||||||
|
|
||||||
/** @var PermissionSetDepository */
|
|
||||||
private $permissionSetDepository;
|
|
||||||
|
|
||||||
public function __construct(Database $dba, LoggerInterface $logger, PermissionSetDepository $permissionSetDepository, array $data = [])
|
|
||||||
{
|
|
||||||
parent::__construct($dba, $logger, $data);
|
|
||||||
|
|
||||||
$this->permissionSetDepository = $permissionSetDepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __get($name)
|
|
||||||
{
|
|
||||||
$this->checkValid();
|
|
||||||
|
|
||||||
switch ($name) {
|
|
||||||
case 'permissionSet':
|
|
||||||
if (empty($this->permissionSet)) {
|
|
||||||
$permissionSet = $this->permissionSetDepository->selectOneById($this->psid, $this->uid);
|
|
||||||
if ($permissionSet->uid !== $this->uid) {
|
|
||||||
throw new NotFoundException(sprintf('PermissionSet %d (user-id: %d) for ProfileField %d (user-id: %d) is invalid.', $permissionSet->id, $permissionSet->uid, $this->id, $this->uid));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->permissionSet = $permissionSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
$return = $this->permissionSet;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$return = parent::__get($name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -86,7 +86,7 @@ class Objects extends BaseModule
|
||||||
$permissionSets = DI::permissionSet()->selectByContactId($requester_id, $item['uid']);
|
$permissionSets = DI::permissionSet()->selectByContactId($requester_id, $item['uid']);
|
||||||
if (!empty($permissionSets)) {
|
if (!empty($permissionSets)) {
|
||||||
$psid = array_merge($permissionSets->column('id'),
|
$psid = array_merge($permissionSets->column('id'),
|
||||||
[DI::permissionSet()->selectEmptyForUser($item['uid'])]);
|
[DI::permissionSet()->selectPublicForUser($item['uid'])]);
|
||||||
$validated = in_array($item['psid'], $psid);
|
$validated = in_array($item['psid'], $psid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
namespace Friendica\Module\Api\Friendica\Profile;
|
namespace Friendica\Module\Api\Friendica\Profile;
|
||||||
|
|
||||||
use Friendica\Collection\ProfileFields;
|
use Friendica\Profile\ProfileField\Collection\ProfileFields;
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
|
@ -45,7 +45,7 @@ class Show extends BaseApi
|
||||||
|
|
||||||
$profile = Profile::getByUID($uid);
|
$profile = Profile::getByUID($uid);
|
||||||
|
|
||||||
$profileFields = DI::profileField()->select(['uid' => $uid, 'psid' => PermissionSet::PUBLIC]);
|
$profileFields = DI::profileField()->selectPublicFieldsByUserId($uid);
|
||||||
|
|
||||||
$profile = self::formatProfile($profile, $profileFields);
|
$profile = self::formatProfile($profile, $profileFields);
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ class Status extends BaseProfile
|
||||||
$permissionSets = DI::permissionSet()->selectByContactId($remote_user, $profile['uid']);
|
$permissionSets = DI::permissionSet()->selectByContactId($remote_user, $profile['uid']);
|
||||||
if (!empty($permissionSets)) {
|
if (!empty($permissionSets)) {
|
||||||
$condition = ['psid' => array_merge($permissionSets->column('id'),
|
$condition = ['psid' => array_merge($permissionSets->column('id'),
|
||||||
[DI::permissionSet()->selectEmptyForUser($profile['uid'])->id])];
|
[DI::permissionSet()->selectPublicForUser($profile['uid'])->id])];
|
||||||
}
|
}
|
||||||
} elseif ($profile['uid'] == local_user()) {
|
} elseif ($profile['uid'] == local_user()) {
|
||||||
$condition = [];
|
$condition = [];
|
||||||
|
|
|
@ -30,7 +30,8 @@ use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Model\ProfileField;
|
use Friendica\Profile\ProfileField\Collection\ProfileFields;
|
||||||
|
use Friendica\Profile\ProfileField\Entity\ProfileField;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Module\BaseSettings;
|
use Friendica\Module\BaseSettings;
|
||||||
use Friendica\Module\Security\Login;
|
use Friendica\Module\Security\Login;
|
||||||
|
@ -100,16 +101,13 @@ class Index extends BaseSettings
|
||||||
$homepage = 'http://' . $homepage;
|
$homepage = 'http://' . $homepage;
|
||||||
}
|
}
|
||||||
|
|
||||||
$profileFields = DI::profileField()->selectByUserId(local_user());
|
$profileFieldsNew = self::getProfileFieldsFromInput(
|
||||||
|
|
||||||
$profileFields = DI::profileField()->updateCollectionFromForm(
|
|
||||||
local_user(),
|
local_user(),
|
||||||
$profileFields,
|
|
||||||
$_REQUEST['profile_field'],
|
$_REQUEST['profile_field'],
|
||||||
$_REQUEST['profile_field_order']
|
$_REQUEST['profile_field_order']
|
||||||
);
|
);
|
||||||
|
|
||||||
DI::profileField()->saveCollection($profileFields);
|
DI::profileField()->saveCollectionForUser(local_user(), $profileFieldsNew);
|
||||||
|
|
||||||
$result = Profile::update(
|
$result = Profile::update(
|
||||||
[
|
[
|
||||||
|
@ -265,6 +263,56 @@ class Index extends BaseSettings
|
||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getProfileFieldsFromInput(int $uid, array $profileFieldInputs, array $profileFieldOrder): ProfileFields
|
||||||
|
{
|
||||||
|
$profileFields = new 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(
|
||||||
|
$uid,
|
||||||
|
DI::aclFormatter()->toString($profileFieldInputs['new']['contact_allow'] ?? ''),
|
||||||
|
DI::aclFormatter()->toString($profileFieldInputs['new']['group_allow'] ?? ''),
|
||||||
|
DI::aclFormatter()->toString($profileFieldInputs['new']['contact_deny'] ?? ''),
|
||||||
|
DI::aclFormatter()->toString($profileFieldInputs['new']['group_deny'] ?? '')
|
||||||
|
));
|
||||||
|
|
||||||
|
$profileFields->append(DI::profileFieldFactory()->createFromValues(
|
||||||
|
$uid,
|
||||||
|
$profileFieldOrder['new'],
|
||||||
|
$profileFieldInputs['new']['label'],
|
||||||
|
$profileFieldInputs['new']['value'],
|
||||||
|
$permissionSet
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($profileFieldInputs['new']);
|
||||||
|
unset($profileFieldOrder['new']);
|
||||||
|
|
||||||
|
foreach ($profileFieldInputs as $id => $profileFieldInput) {
|
||||||
|
$permissionSet = DI::permissionSet()->selectOrCreate(DI::permissionSetFactory()->createFromString(
|
||||||
|
$uid,
|
||||||
|
DI::aclFormatter()->toString($profileFieldInput['contact_allow'] ?? ''),
|
||||||
|
DI::aclFormatter()->toString($profileFieldInput['group_allow'] ?? ''),
|
||||||
|
DI::aclFormatter()->toString($profileFieldInput['contact_deny'] ?? ''),
|
||||||
|
DI::aclFormatter()->toString($profileFieldInput['group_deny'] ?? '')
|
||||||
|
));
|
||||||
|
|
||||||
|
$profileFields->append(DI::profileFieldFactory()->createFromValues(
|
||||||
|
$uid,
|
||||||
|
$profileFieldOrder[$id],
|
||||||
|
$profileFieldInput['label'],
|
||||||
|
$profileFieldInput['value'],
|
||||||
|
$permissionSet
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $profileFields;
|
||||||
|
}
|
||||||
|
|
||||||
private static function cleanKeywords($keywords)
|
private static function cleanKeywords($keywords)
|
||||||
{
|
{
|
||||||
$keywords = str_replace(',', ' ', $keywords);
|
$keywords = str_replace(',', ' ', $keywords);
|
||||||
|
|
|
@ -19,17 +19,23 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Friendica\Collection;
|
namespace Friendica\Profile\ProfileField\Collection;
|
||||||
|
|
||||||
use Friendica\BaseCollection;
|
use Friendica\BaseCollection;
|
||||||
|
use Friendica\Profile\ProfileField\Entity;
|
||||||
|
|
||||||
class ProfileFields extends BaseCollection
|
class ProfileFields extends BaseCollection
|
||||||
{
|
{
|
||||||
|
public function current(): Entity\ProfileField
|
||||||
|
{
|
||||||
|
return parent::current();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callable $callback
|
* @param callable $callback
|
||||||
* @return ProfileFields
|
* @return ProfileFields
|
||||||
*/
|
*/
|
||||||
public function map(callable $callback)
|
public function map(callable $callback): ProfileFields
|
||||||
{
|
{
|
||||||
return parent::map($callback);
|
return parent::map($callback);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +45,7 @@ class ProfileFields extends BaseCollection
|
||||||
* @param int $flag
|
* @param int $flag
|
||||||
* @return ProfileFields
|
* @return ProfileFields
|
||||||
*/
|
*/
|
||||||
public function filter(callable $callback = null, int $flag = 0)
|
public function filter(callable $callback = null, int $flag = 0): ProfileFields
|
||||||
{
|
{
|
||||||
return parent::filter($callback, $flag);
|
return parent::filter($callback, $flag);
|
||||||
}
|
}
|
281
src/Profile/ProfileField/Depository/ProfileField.php
Normal file
281
src/Profile/ProfileField/Depository/ProfileField.php
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2021, 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\Profile\ProfileField\Depository;
|
||||||
|
|
||||||
|
use Friendica\BaseDepository;
|
||||||
|
use Friendica\Database\Database;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\ProfileFieldNotFoundException;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\ProfileFieldPersistenceException;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\UnexpectedPermissionSetException;
|
||||||
|
use Friendica\Profile\ProfileField\Factory;
|
||||||
|
use Friendica\Profile\ProfileField\Entity;
|
||||||
|
use Friendica\Profile\ProfileField\Collection;
|
||||||
|
use Friendica\Security\PermissionSet\Depository\PermissionSet as PermissionSetDepository;
|
||||||
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class ProfileField extends BaseDepository
|
||||||
|
{
|
||||||
|
/** @var Factory\ProfileField */
|
||||||
|
protected $factory;
|
||||||
|
|
||||||
|
protected static $table_name = 'profile_field';
|
||||||
|
|
||||||
|
protected static $view_name = 'profile_field-view';
|
||||||
|
|
||||||
|
/** @var PermissionSetDepository */
|
||||||
|
protected $permissionSetDepository;
|
||||||
|
|
||||||
|
public function __construct(Database $database, LoggerInterface $logger, Factory\ProfileField $factory, PermissionSetDepository $permissionSetDepository)
|
||||||
|
{
|
||||||
|
parent::__construct($database, $logger, $factory);
|
||||||
|
|
||||||
|
$this->permissionSetDepository = $permissionSetDepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $condition
|
||||||
|
* @param array $params
|
||||||
|
*
|
||||||
|
* @return Entity\ProfileField
|
||||||
|
*
|
||||||
|
* @throws ProfileFieldNotFoundException
|
||||||
|
* @throws UnexpectedPermissionSetException
|
||||||
|
*/
|
||||||
|
private function selectOne(array $condition, array $params = []): Entity\ProfileField
|
||||||
|
{
|
||||||
|
$fields = $this->db->selectFirst(static::$view_name, [], $condition, $params);
|
||||||
|
if (!$this->db->isResult($fields)) {
|
||||||
|
throw new ProfileFieldNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->factory->createFromTableRow($fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $condition
|
||||||
|
* @param array $params
|
||||||
|
*
|
||||||
|
* @return Collection\ProfileFields
|
||||||
|
*
|
||||||
|
* @throws ProfileFieldPersistenceException In case of underlying persistence exceptions
|
||||||
|
* @throws UnexpectedPermissionSetException
|
||||||
|
*/
|
||||||
|
private function select(array $condition, array $params = []): Collection\ProfileFields
|
||||||
|
{
|
||||||
|
$rows = $this->db->selectToArray(static::$view_name, [], $condition, $params);
|
||||||
|
|
||||||
|
$Entities = new Collection\ProfileFields();
|
||||||
|
foreach ($rows as $fields) {
|
||||||
|
$this->logger->warning('row', ['row' => $fields]);
|
||||||
|
$Entities[] = $this->factory->createFromTableRow($fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $Entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a given ProfileField into a DB compatible row array
|
||||||
|
*
|
||||||
|
* @param Entity\ProfileField $profileField
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function convertToTableRow(Entity\ProfileField $profileField): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'uid' => $profileField->uid,
|
||||||
|
'label' => $profileField->label,
|
||||||
|
'value' => $profileField->value,
|
||||||
|
'order' => $profileField->order,
|
||||||
|
'created' => $profileField->created->format(DateTimeFormat::MYSQL),
|
||||||
|
'edited' => $profileField->edited->format(DateTimeFormat::MYSQL),
|
||||||
|
'psid' => $profileField->permissionSet->id
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all public available ProfileFields for a specific user
|
||||||
|
*
|
||||||
|
* @param int $uid the user id
|
||||||
|
*
|
||||||
|
* @return Collection\ProfileFields
|
||||||
|
*
|
||||||
|
* @throws ProfileFieldPersistenceException In case of underlying persistence exceptions
|
||||||
|
*/
|
||||||
|
public function selectPublicFieldsByUserId(int $uid): Collection\ProfileFields
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$publicPermissionSet = $this->permissionSetDepository->selectPublicForUser($uid);
|
||||||
|
|
||||||
|
return $this->select([
|
||||||
|
'uid' => $uid,
|
||||||
|
'psid' => $publicPermissionSet->id
|
||||||
|
]);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
throw new ProfileFieldPersistenceException(sprintf('Cannot select public ProfileField for user "%d"', $uid), $exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $uid Field owner user Id
|
||||||
|
*
|
||||||
|
* @throws ProfileFieldPersistenceException In case of underlying persistence exceptions
|
||||||
|
*/
|
||||||
|
public function selectByUserId(int $uid): Collection\ProfileFields
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->select(
|
||||||
|
['uid' => $uid],
|
||||||
|
['order' => ['order']]
|
||||||
|
);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
throw new ProfileFieldPersistenceException(sprintf('Cannot select ProfileField for user "%d"', $uid), $exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all custom profile field a given contact is able to access to, including public profile fields.
|
||||||
|
*
|
||||||
|
* @param int $cid Private contact id, must be owned by $uid
|
||||||
|
* @param int $uid Field owner user id
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function selectByContactId(int $cid, int $uid): Collection\ProfileFields
|
||||||
|
{
|
||||||
|
$permissionSets = $this->permissionSetDepository->selectByContactId($cid, $uid);
|
||||||
|
|
||||||
|
$permissionSetIds = $permissionSets->column('id');
|
||||||
|
|
||||||
|
// Includes public custom fields
|
||||||
|
$permissionSetIds[] = $this->permissionSetDepository->selectPublicForUser($uid)->id;
|
||||||
|
|
||||||
|
return $this->select(
|
||||||
|
['uid' => $uid, 'psid' => $permissionSetIds],
|
||||||
|
['order' => ['order']]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return Entity\ProfileField
|
||||||
|
*
|
||||||
|
* @ProfileFieldNotFoundException In case there is no ProfileField found
|
||||||
|
*/
|
||||||
|
public function selectOneById(int $id): Entity\ProfileField
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->selectOne(['id' => $id]);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
throw new ProfileFieldNotFoundException(sprintf('Cannot find Profile "%s"', $id), $exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delets a whole collection of ProfileFields
|
||||||
|
*
|
||||||
|
* @param Collection\ProfileFields $profileFields
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws ProfileFieldPersistenceException in case the persistence layer cannot delete the ProfileFields
|
||||||
|
*/
|
||||||
|
public function deleteCollection(Collection\ProfileFields $profileFields): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->db->delete(self::$table_name, ['id' => $profileFields->column('id')]);
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
throw new ProfileFieldPersistenceException('Cannot delete ProfileFields', $exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Entity\ProfileField $profileField
|
||||||
|
*
|
||||||
|
* @return Entity\ProfileField
|
||||||
|
* @throws ProfileFieldPersistenceException in case the persistence layer cannot save the ProfileField
|
||||||
|
*/
|
||||||
|
public function save(Entity\ProfileField $profileField): Entity\ProfileField
|
||||||
|
{
|
||||||
|
if ($profileField->permissionSet->id === null) {
|
||||||
|
throw new ProfileFieldPersistenceException('PermissionSet needs to be saved first.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = $this->convertToTableRow($profileField);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($profileField->id) {
|
||||||
|
$this->db->update(self::$table_name, $fields, ['id' => $profileField->id]);
|
||||||
|
} else {
|
||||||
|
$this->db->insert(self::$table_name, $fields);
|
||||||
|
|
||||||
|
$profileField = $this->selectOneById($this->db->lastInsertId());
|
||||||
|
}
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
throw new ProfileFieldPersistenceException(sprintf('Cannot save ProfileField with id "%d" and label "%s"', $profileField->id, $profileField->label), $exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $profileField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveCollectionForUser(int $uid, Collection\ProfileFields $profileFields): Collection\ProfileFields
|
||||||
|
{
|
||||||
|
$savedProfileFields = new Collection\ProfileFields();
|
||||||
|
|
||||||
|
$profileFieldsOld = $this->selectByUserId($uid);
|
||||||
|
|
||||||
|
// Prunes profile field whose label has been emptied
|
||||||
|
$labels = $profileFields->column('label');
|
||||||
|
$prunedProfileFieldsOld = $profileFieldsOld->filter(function (Entity\ProfileField $profileFieldOld) use ($labels) {
|
||||||
|
return array_search($profileFieldOld->label, $labels) === false;
|
||||||
|
});
|
||||||
|
$this->deleteCollection($prunedProfileFieldsOld);
|
||||||
|
|
||||||
|
// Update the order based on the new Profile Field Collection
|
||||||
|
$order = 0;
|
||||||
|
$labelProfileFieldsOld = array_flip($profileFieldsOld->column('label'));
|
||||||
|
|
||||||
|
foreach ($profileFields as $profileField) {
|
||||||
|
// Update existing field (preserve
|
||||||
|
if (array_key_exists($profileField->label, $labelProfileFieldsOld)) {
|
||||||
|
$profileFieldOldId = $labelProfileFieldsOld[$profileField->label];
|
||||||
|
/** @var Entity\ProfileField $foundProfileFieldOld */
|
||||||
|
$foundProfileFieldOld = $profileFieldsOld[$profileFieldOldId];
|
||||||
|
$foundProfileFieldOld->update(
|
||||||
|
$profileField->value,
|
||||||
|
$order,
|
||||||
|
$profileField->permissionSet
|
||||||
|
);
|
||||||
|
|
||||||
|
$savedProfileFields->append($this->save($foundProfileFieldOld));
|
||||||
|
} else {
|
||||||
|
$profileField->setOrder($order);
|
||||||
|
$savedProfileFields->append($this->save($profileField));
|
||||||
|
}
|
||||||
|
|
||||||
|
$order++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $savedProfileFields;
|
||||||
|
}
|
||||||
|
}
|
112
src/Profile/ProfileField/Entity/ProfileField.php
Normal file
112
src/Profile/ProfileField/Entity/ProfileField.php
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2021, 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\Profile\ProfileField\Entity;
|
||||||
|
|
||||||
|
use Friendica\BaseEntity;
|
||||||
|
use Friendica\Network\HTTPException\InternalServerErrorException;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\ProfileFieldNotFoundException;
|
||||||
|
use Friendica\Security\PermissionSet\Entity\PermissionSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom profile field entity class.
|
||||||
|
*
|
||||||
|
* Custom profile fields are user-created arbitrary profile fields that can be assigned a permission set to restrict its
|
||||||
|
* display to specific Friendica contacts as it requires magic authentication to work.
|
||||||
|
*
|
||||||
|
* @property-read int|null $id
|
||||||
|
* @property-read int $uid
|
||||||
|
* @property-read int $order
|
||||||
|
* @property-read string $label
|
||||||
|
* @property-read string $value
|
||||||
|
* @property-read \DateTime $created
|
||||||
|
* @property-read \DateTime $edited
|
||||||
|
* @property PermissionSet $permissionSet
|
||||||
|
*/
|
||||||
|
class ProfileField extends BaseEntity
|
||||||
|
{
|
||||||
|
/** @var int|null */
|
||||||
|
protected $id;
|
||||||
|
/** @var PermissionSet */
|
||||||
|
protected $permissionSet;
|
||||||
|
/** @var int */
|
||||||
|
protected $uid;
|
||||||
|
/** @var int */
|
||||||
|
protected $order;
|
||||||
|
/** @var string */
|
||||||
|
protected $label;
|
||||||
|
/** @var string */
|
||||||
|
protected $value;
|
||||||
|
/** @var \DateTime */
|
||||||
|
protected $created;
|
||||||
|
/** @var \DateTime */
|
||||||
|
protected $edited;
|
||||||
|
|
||||||
|
public function __construct(int $uid, int $order, string $label, string $value, \DateTime $created, \DateTime $edited, PermissionSet $permissionSet, int $id = null)
|
||||||
|
{
|
||||||
|
$this->permissionSet = $permissionSet;
|
||||||
|
$this->uid = $uid;
|
||||||
|
$this->order = $order;
|
||||||
|
$this->label = $label;
|
||||||
|
$this->value = $value;
|
||||||
|
$this->created = $created;
|
||||||
|
$this->edited = $edited;
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ProfileFieldNotFoundException
|
||||||
|
*/
|
||||||
|
public function __get($name)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return parent::__get($name);
|
||||||
|
} catch (InternalServerErrorException $exception) {
|
||||||
|
throw new ProfileFieldNotFoundException($exception->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a ProfileField
|
||||||
|
*
|
||||||
|
* @param string $value The current or changed value
|
||||||
|
* @param int $order The current or changed order
|
||||||
|
* @param PermissionSet $permissionSet The current or changed PermissionSet
|
||||||
|
*/
|
||||||
|
public function update(string $value, int $order, PermissionSet $permissionSet)
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
$this->order = $order;
|
||||||
|
$this->permissionSet = $permissionSet;
|
||||||
|
$this->edited = new \DateTime('now', new \DateTimeZone('UTC'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the order of the ProfileField
|
||||||
|
*
|
||||||
|
* @param int $order
|
||||||
|
*/
|
||||||
|
public function setOrder(int $order)
|
||||||
|
{
|
||||||
|
$this->order = $order;
|
||||||
|
$this->edited = new \DateTime('now', new \DateTimeZone('UTC'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2021, 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\Profile\ProfileField\Exception;
|
||||||
|
|
||||||
|
use OutOfBoundsException;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class ProfileFieldNotFoundException extends OutOfBoundsException
|
||||||
|
{
|
||||||
|
public function __construct($message = "", Throwable $previous = null)
|
||||||
|
{
|
||||||
|
parent::__construct($message, 404, $previous);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2021, 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\Profile\ProfileField\Exception;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class ProfileFieldPersistenceException extends \RuntimeException
|
||||||
|
{
|
||||||
|
public function __construct($message = "", Throwable $previous = null)
|
||||||
|
{
|
||||||
|
parent::__construct($message, 500, $previous);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2021, 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\Profile\ProfileField\Exception;
|
||||||
|
|
||||||
|
class UnexpectedPermissionSetException extends \Exception
|
||||||
|
{
|
||||||
|
}
|
106
src/Profile/ProfileField/Factory/ProfileField.php
Normal file
106
src/Profile/ProfileField/Factory/ProfileField.php
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @copyright Copyright (C) 2010-2021, 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\Profile\ProfileField\Factory;
|
||||||
|
|
||||||
|
use Friendica\BaseFactory;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\UnexpectedPermissionSetException;
|
||||||
|
use Friendica\Security\PermissionSet\Factory\PermissionSet as PermissionSetFactory;
|
||||||
|
use Friendica\Profile\ProfileField\Entity;
|
||||||
|
use Friendica\Capabilities\ICanCreateFromTableRow;
|
||||||
|
use Friendica\Security\PermissionSet\Entity\PermissionSet;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class ProfileField extends BaseFactory implements ICanCreateFromTableRow
|
||||||
|
{
|
||||||
|
/** @var PermissionSetFactory */
|
||||||
|
private $permissionSetFactory;
|
||||||
|
|
||||||
|
public function __construct(LoggerInterface $logger, PermissionSetFactory $permissionSetFactory)
|
||||||
|
{
|
||||||
|
parent::__construct($logger);
|
||||||
|
|
||||||
|
$this->permissionSetFactory = $permissionSetFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*
|
||||||
|
* @throws UnexpectedPermissionSetException
|
||||||
|
*/
|
||||||
|
public function createFromTableRow(array $row, PermissionSet $permissionSet = null): Entity\ProfileField
|
||||||
|
{
|
||||||
|
if (empty($permissionSet) &&
|
||||||
|
(!array_key_exists('psid', $row) || !array_key_exists('allow_cid', $row) || !array_key_exists('allow_gid', $row) || !array_key_exists('deny_cid', $row) || !array_key_exists('deny_gid', $row))
|
||||||
|
) {
|
||||||
|
throw new UnexpectedPermissionSetException('Either set the PermissionSet fields (join) or the PermissionSet itself');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Entity\ProfileField(
|
||||||
|
$row['uid'],
|
||||||
|
$row['order'],
|
||||||
|
$row['label'],
|
||||||
|
$row['value'],
|
||||||
|
new \DateTime($row['created'] ?? 'now', new \DateTimeZone('UTC')),
|
||||||
|
new \DateTime($row['edited'] ?? 'now', new \DateTimeZone('UTC')),
|
||||||
|
$permissionSet ?? $this->permissionSetFactory->createFromString(
|
||||||
|
$row['uid'],
|
||||||
|
$row['allow_cid'],
|
||||||
|
$row['allow_gid'],
|
||||||
|
$row['deny_cid'],
|
||||||
|
$row['deny_gid'],
|
||||||
|
$row['psid']
|
||||||
|
),
|
||||||
|
$row['id'] ?? null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ProfileField instance based on it's values
|
||||||
|
*
|
||||||
|
* @param int $uid
|
||||||
|
* @param int $order
|
||||||
|
* @param string $label
|
||||||
|
* @param string $value
|
||||||
|
* @param PermissionSet $permissionSet
|
||||||
|
* @param int|null $id
|
||||||
|
*
|
||||||
|
* @return Entity\ProfileField
|
||||||
|
* @throws UnexpectedPermissionSetException
|
||||||
|
*/
|
||||||
|
public function createFromValues(
|
||||||
|
int $uid,
|
||||||
|
int $order,
|
||||||
|
string $label,
|
||||||
|
string $value,
|
||||||
|
PermissionSet $permissionSet,
|
||||||
|
int $id = null
|
||||||
|
): Entity\ProfileField {
|
||||||
|
return $this->createFromTableRow([
|
||||||
|
'uid' => $uid,
|
||||||
|
'order' => $order,
|
||||||
|
'psid' => $permissionSet->id,
|
||||||
|
'label' => $label,
|
||||||
|
'value' => $value,
|
||||||
|
'id' => $id,
|
||||||
|
], $permissionSet);
|
||||||
|
}
|
||||||
|
}
|
|
@ -229,7 +229,7 @@ class Transmitter
|
||||||
$permissionSets = DI::permissionSet()->selectByContactId($requester_id, $owner['uid']);
|
$permissionSets = DI::permissionSet()->selectByContactId($requester_id, $owner['uid']);
|
||||||
if (!empty($permissionSets)) {
|
if (!empty($permissionSets)) {
|
||||||
$condition = ['psid' => array_merge($permissionSets->column('id'),
|
$condition = ['psid' => array_merge($permissionSets->column('id'),
|
||||||
[DI::permissionSet()->selectEmptyForUser($owner['uid'])])];
|
[DI::permissionSet()->selectPublicForUser($owner['uid'])])];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,324 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* @copyright Copyright (C) 2010-2021, 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\Repository;
|
|
||||||
|
|
||||||
use Friendica\BaseModel;
|
|
||||||
use Friendica\BaseRepository;
|
|
||||||
use Friendica\Collection;
|
|
||||||
use Friendica\Core\L10n;
|
|
||||||
use Friendica\Database\Database;
|
|
||||||
use Friendica\Database\DBA;
|
|
||||||
use Friendica\Model;
|
|
||||||
use Friendica\Security\PermissionSet\Depository\PermissionSet;
|
|
||||||
use Friendica\Util\DateTimeFormat;
|
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
|
|
||||||
class ProfileField extends BaseRepository
|
|
||||||
{
|
|
||||||
protected static $table_name = 'profile_field';
|
|
||||||
|
|
||||||
protected static $model_class = Model\ProfileField::class;
|
|
||||||
|
|
||||||
protected static $collection_class = Collection\ProfileFields::class;
|
|
||||||
|
|
||||||
/** @var PermissionSet */
|
|
||||||
private $permissionSet;
|
|
||||||
/** @var \Friendica\Security\PermissionSet\Factory\PermissionSet */
|
|
||||||
private $permissionSetFactory;
|
|
||||||
/** @var L10n */
|
|
||||||
private $l10n;
|
|
||||||
|
|
||||||
public function __construct(Database $dba, LoggerInterface $logger, PermissionSet $permissionSet, \Friendica\Security\PermissionSet\Factory\PermissionSet $permissionSetFactory, L10n $l10n)
|
|
||||||
{
|
|
||||||
parent::__construct($dba, $logger);
|
|
||||||
|
|
||||||
$this->permissionSet = $permissionSet;
|
|
||||||
$this->permissionSetFactory = $permissionSetFactory;
|
|
||||||
$this->l10n = $l10n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $data
|
|
||||||
* @return Model\ProfileField
|
|
||||||
*/
|
|
||||||
protected function create(array $data)
|
|
||||||
{
|
|
||||||
return new Model\ProfileField($this->dba, $this->logger, $this->permissionSet, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $condition
|
|
||||||
* @return Model\ProfileField
|
|
||||||
* @throws \Friendica\Network\HTTPException\NotFoundException
|
|
||||||
*/
|
|
||||||
public function selectFirst(array $condition)
|
|
||||||
{
|
|
||||||
return parent::selectFirst($condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $condition
|
|
||||||
* @param array $params
|
|
||||||
* @return Collection\ProfileFields
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function select(array $condition = [], array $params = [])
|
|
||||||
{
|
|
||||||
return parent::select($condition, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $condition
|
|
||||||
* @param array $params
|
|
||||||
* @param int|null $min_id
|
|
||||||
* @param int|null $max_id
|
|
||||||
* @param int $limit
|
|
||||||
* @return Collection\ProfileFields
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function selectByBoundaries(array $condition = [], array $params = [], int $min_id = null, int $max_id = null, int $limit = self::LIMIT)
|
|
||||||
{
|
|
||||||
return parent::selectByBoundaries($condition, $params, $min_id, $max_id, $limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $uid Field owner user Id
|
|
||||||
* @return Collection\ProfileFields
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function selectByUserId(int $uid)
|
|
||||||
{
|
|
||||||
return $this->select(
|
|
||||||
['uid' => $uid],
|
|
||||||
['order' => ['order']]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve all custom profile field a given contact is able to access to, including public profile fields.
|
|
||||||
*
|
|
||||||
* @param int $cid Private contact id, must be owned by $uid
|
|
||||||
* @param int $uid Field owner user id
|
|
||||||
* @return Collection\ProfileFields
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function selectByContactId(int $cid, int $uid)
|
|
||||||
{
|
|
||||||
$permissionSets = $this->permissionSet->selectByContactId($cid, $uid);
|
|
||||||
|
|
||||||
$psids = $permissionSets->column('id');
|
|
||||||
|
|
||||||
// Includes public custom fields
|
|
||||||
$psids[] = 0;
|
|
||||||
|
|
||||||
return $this->select(
|
|
||||||
['uid' => $uid, 'psid' => $psids],
|
|
||||||
['order' => ['order']]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $fields
|
|
||||||
* @return Model\ProfileField|bool
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function insert(array $fields)
|
|
||||||
{
|
|
||||||
$fields['created'] = DateTimeFormat::utcNow();
|
|
||||||
$fields['edited'] = DateTimeFormat::utcNow();
|
|
||||||
|
|
||||||
return parent::insert($fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Model\ProfileField $model
|
|
||||||
* @return bool
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function update(BaseModel $model)
|
|
||||||
{
|
|
||||||
$model->edited = DateTimeFormat::utcNow();
|
|
||||||
|
|
||||||
return parent::update($model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $uid User Id
|
|
||||||
* @param Collection\ProfileFields $profileFields Collection of existing profile fields
|
|
||||||
* @param array $profileFieldInputs Array of profile field form inputs indexed by profile field id
|
|
||||||
* @param array $profileFieldOrder List of profile field id in order
|
|
||||||
* @return Collection\ProfileFields
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function updateCollectionFromForm(int $uid, Collection\ProfileFields $profileFields, array $profileFieldInputs, array $profileFieldOrder)
|
|
||||||
{
|
|
||||||
// Returns an associative array of id => order values
|
|
||||||
$profileFieldOrder = array_flip($profileFieldOrder);
|
|
||||||
|
|
||||||
// Creation of the new field
|
|
||||||
if (!empty($profileFieldInputs['new']['label'])) {
|
|
||||||
$psid = $this->permissionSet->selectOrCreate($this->permissionSetFactory->createFromString(
|
|
||||||
$uid,
|
|
||||||
$profileFieldInputs['new']['contact_allow'] ?? '',
|
|
||||||
$profileFieldInputs['new']['group_allow'] ?? '',
|
|
||||||
$profileFieldInputs['new']['contact_deny'] ?? '',
|
|
||||||
$profileFieldInputs['new']['group_deny'] ?? ''
|
|
||||||
))->id;
|
|
||||||
|
|
||||||
$newProfileField = $this->insert([
|
|
||||||
'uid' => $uid,
|
|
||||||
'label' => $profileFieldInputs['new']['label'],
|
|
||||||
'value' => $profileFieldInputs['new']['value'],
|
|
||||||
'psid' => $psid,
|
|
||||||
'order' => $profileFieldOrder['new'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$profileFieldInputs[$newProfileField->id] = $profileFieldInputs['new'];
|
|
||||||
$profileFieldOrder[$newProfileField->id] = $profileFieldOrder['new'];
|
|
||||||
|
|
||||||
$profileFields[] = $newProfileField;
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($profileFieldInputs['new']);
|
|
||||||
unset($profileFieldOrder['new']);
|
|
||||||
|
|
||||||
// Prunes profile field whose label has been emptied
|
|
||||||
$profileFields = $profileFields->filter(function (Model\ProfileField $profileField) use (&$profileFieldInputs, &$profileFieldOrder) {
|
|
||||||
$keepModel = !isset($profileFieldInputs[$profileField->id]) || !empty($profileFieldInputs[$profileField->id]['label']);
|
|
||||||
|
|
||||||
if (!$keepModel) {
|
|
||||||
unset($profileFieldInputs[$profileField->id]);
|
|
||||||
unset($profileFieldOrder[$profileField->id]);
|
|
||||||
$this->delete($profileField);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $keepModel;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Regenerates the order values if items were deleted
|
|
||||||
$profileFieldOrder = array_flip(array_keys($profileFieldOrder));
|
|
||||||
|
|
||||||
// Update existing profile fields from form values
|
|
||||||
$profileFields = $profileFields->map(function (Model\ProfileField $profileField) use ($uid, &$profileFieldInputs, &$profileFieldOrder) {
|
|
||||||
if (isset($profileFieldInputs[$profileField->id]) && isset($profileFieldOrder[$profileField->id])) {
|
|
||||||
$psid = $this->permissionSet->selectOrCreate($this->permissionSetFactory->createFromString(
|
|
||||||
$uid,
|
|
||||||
$profileFieldInputs[$profileField->id]['contact_allow'] ?? '',
|
|
||||||
$profileFieldInputs[$profileField->id]['group_allow'] ?? '',
|
|
||||||
$profileFieldInputs[$profileField->id]['contact_deny'] ?? '',
|
|
||||||
$profileFieldInputs[$profileField->id]['group_deny'] ?? ''
|
|
||||||
))->id;
|
|
||||||
|
|
||||||
$profileField->psid = $psid;
|
|
||||||
$profileField->label = $profileFieldInputs[$profileField->id]['label'];
|
|
||||||
$profileField->value = $profileFieldInputs[$profileField->id]['value'];
|
|
||||||
$profileField->order = $profileFieldOrder[$profileField->id];
|
|
||||||
|
|
||||||
unset($profileFieldInputs[$profileField->id]);
|
|
||||||
unset($profileFieldOrder[$profileField->id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $profileField;
|
|
||||||
});
|
|
||||||
|
|
||||||
return $profileFields;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Migrates a legacy profile to the new slimmer profile with extra custom fields.
|
|
||||||
* Multi profiles are converted to ACl-protected custom fields and deleted.
|
|
||||||
*
|
|
||||||
* @param array $profile Profile table row
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function migrateFromLegacyProfile(array $profile)
|
|
||||||
{
|
|
||||||
// Already processed, aborting
|
|
||||||
if ($profile['is-default'] === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$contacts = [];
|
|
||||||
|
|
||||||
if (!$profile['is-default']) {
|
|
||||||
$contacts = Model\Contact::selectToArray(['id'], ['uid' => $profile['uid'], 'profile-id' => $profile['id']]);
|
|
||||||
if (!count($contacts)) {
|
|
||||||
// No contact visibility selected defaults to user-only permission
|
|
||||||
$contacts = Model\Contact::selectToArray(['id'], ['uid' => $profile['uid'], 'self' => true]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$psid = $this->permissionSet->selectOrCreate(
|
|
||||||
new \Friendica\Security\PermissionSet\Entity\PermissionSet(
|
|
||||||
$profile['uid'],
|
|
||||||
array_column($contacts, 'id') ?? []
|
|
||||||
)
|
|
||||||
)->id;
|
|
||||||
|
|
||||||
$order = 1;
|
|
||||||
|
|
||||||
$custom_fields = [
|
|
||||||
'hometown' => $this->l10n->t('Hometown:'),
|
|
||||||
'marital' => $this->l10n->t('Marital Status:'),
|
|
||||||
'with' => $this->l10n->t('With:'),
|
|
||||||
'howlong' => $this->l10n->t('Since:'),
|
|
||||||
'sexual' => $this->l10n->t('Sexual Preference:'),
|
|
||||||
'politic' => $this->l10n->t('Political Views:'),
|
|
||||||
'religion' => $this->l10n->t('Religious Views:'),
|
|
||||||
'likes' => $this->l10n->t('Likes:'),
|
|
||||||
'dislikes' => $this->l10n->t('Dislikes:'),
|
|
||||||
'pdesc' => $this->l10n->t('Title/Description:'),
|
|
||||||
'summary' => $this->l10n->t('Summary'),
|
|
||||||
'music' => $this->l10n->t('Musical interests'),
|
|
||||||
'book' => $this->l10n->t('Books, literature'),
|
|
||||||
'tv' => $this->l10n->t('Television'),
|
|
||||||
'film' => $this->l10n->t('Film/dance/culture/entertainment'),
|
|
||||||
'interest' => $this->l10n->t('Hobbies/Interests'),
|
|
||||||
'romance' => $this->l10n->t('Love/romance'),
|
|
||||||
'work' => $this->l10n->t('Work/employment'),
|
|
||||||
'education' => $this->l10n->t('School/education'),
|
|
||||||
'contact' => $this->l10n->t('Contact information and Social Networks'),
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($custom_fields as $field => $label) {
|
|
||||||
if (!empty($profile[$field]) && $profile[$field] > DBA::NULL_DATE && $profile[$field] > DBA::NULL_DATETIME) {
|
|
||||||
$this->insert([
|
|
||||||
'uid' => $profile['uid'],
|
|
||||||
'psid' => $psid,
|
|
||||||
'order' => $order++,
|
|
||||||
'label' => trim($label, ':'),
|
|
||||||
'value' => $profile[$field],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$profile[$field] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($profile['is-default']) {
|
|
||||||
$profile['profile-name'] = null;
|
|
||||||
$profile['is-default'] = null;
|
|
||||||
$this->dba->update('profile', $profile, ['id' => $profile['id']]);
|
|
||||||
} elseif (!empty($profile['id'])) {
|
|
||||||
$this->dba->delete('profile', ['id' => $profile['id']]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -53,6 +53,22 @@ class PermissionSet extends BaseDepository
|
||||||
$this->aclFormatter = $aclFormatter;
|
$this->aclFormatter = $aclFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replaces the PUBLIC id for the public permissionSet
|
||||||
|
* (no need to create the default permission set over and over again)
|
||||||
|
*
|
||||||
|
* @param $condition
|
||||||
|
*/
|
||||||
|
private function checkPublicSelect(&$condition)
|
||||||
|
{
|
||||||
|
if (empty($condition['allow_cid']) &&
|
||||||
|
empty($condition['allow_gid']) &&
|
||||||
|
empty($condition['deny_cid']) &&
|
||||||
|
empty($condition['deny_gid'])) {
|
||||||
|
$condition['uid'] = self::PUBLIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $condition
|
* @param array $condition
|
||||||
* @param array $params
|
* @param array $params
|
||||||
|
@ -89,22 +105,18 @@ class PermissionSet extends BaseDepository
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $id A permissionset table row id or self::PUBLIC
|
* @param int $id A PermissionSet table row id or self::PUBLIC
|
||||||
* @param int|null $uid Should be provided when id can be self::PUBLIC
|
* @param int $uid The owner of the PermissionSet
|
||||||
* @return Entity\PermissionSet
|
* @return Entity\PermissionSet
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
*/
|
*/
|
||||||
public function selectOneById(int $id, int $uid = null): Entity\PermissionSet
|
public function selectOneById(int $id, int $uid): Entity\PermissionSet
|
||||||
{
|
{
|
||||||
if ($id === self::PUBLIC) {
|
if ($id === self::PUBLIC) {
|
||||||
if (empty($uid)) {
|
|
||||||
throw new \InvalidArgumentException('Missing uid for Public permission set instantiation');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->factory->createFromString($uid);
|
return $this->factory->createFromString($uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->selectOne(['id' => $id]);
|
return $this->selectOne(['id' => $id, 'uid' => $uid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,15 +186,15 @@ class PermissionSet extends BaseDepository
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the empty PermissionSet for a given user, create it if it doesn't exist
|
* Fetch the public PermissionSet
|
||||||
*
|
*
|
||||||
* @param int $uid
|
* @param int $uid
|
||||||
*
|
*
|
||||||
* @return Entity\PermissionSet
|
* @return Entity\PermissionSet
|
||||||
*/
|
*/
|
||||||
public function selectEmptyForUser(int $uid): Entity\PermissionSet
|
public function selectPublicForUser(int $uid): Entity\PermissionSet
|
||||||
{
|
{
|
||||||
return $this->selectOrCreate($this->factory->createFromString($uid));
|
return $this->factory->createFromString($uid, '', '', '', '', self::PUBLIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,6 +210,11 @@ class PermissionSet extends BaseDepository
|
||||||
return $permissionSet;
|
return $permissionSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't select/update Public permission sets
|
||||||
|
if ($permissionSet->isPublic()) {
|
||||||
|
return $this->selectPublicForUser($permissionSet->uid);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return $this->selectOne($this->convertToTableRow($permissionSet));
|
return $this->selectOne($this->convertToTableRow($permissionSet));
|
||||||
} catch (NotFoundException $exception) {
|
} catch (NotFoundException $exception) {
|
||||||
|
@ -205,8 +222,19 @@ class PermissionSet extends BaseDepository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Entity\PermissionSet $permissionSet
|
||||||
|
*
|
||||||
|
* @return Entity\PermissionSet
|
||||||
|
* @throws NotFoundException
|
||||||
|
*/
|
||||||
public function save(Entity\PermissionSet $permissionSet): Entity\PermissionSet
|
public function save(Entity\PermissionSet $permissionSet): Entity\PermissionSet
|
||||||
{
|
{
|
||||||
|
// Don't save/update the common public PermissionSet
|
||||||
|
if ($permissionSet->isPublic()) {
|
||||||
|
return $this->selectPublicForUser($permissionSet->uid);
|
||||||
|
}
|
||||||
|
|
||||||
$fields = $this->convertToTableRow($permissionSet);
|
$fields = $this->convertToTableRow($permissionSet);
|
||||||
|
|
||||||
if ($permissionSet->id) {
|
if ($permissionSet->id) {
|
||||||
|
@ -214,7 +242,7 @@ class PermissionSet extends BaseDepository
|
||||||
} else {
|
} else {
|
||||||
$this->db->insert(self::$table_name, $fields);
|
$this->db->insert(self::$table_name, $fields);
|
||||||
|
|
||||||
$permissionSet = $this->selectOneById($this->db->lastInsertId());
|
$permissionSet = $this->selectOneById($this->db->lastInsertId(), $permissionSet->uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $permissionSet;
|
return $permissionSet;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace Friendica\Security\PermissionSet\Entity;
|
namespace Friendica\Security\PermissionSet\Entity;
|
||||||
|
|
||||||
use Friendica\BaseEntity;
|
use Friendica\BaseEntity;
|
||||||
|
use Friendica\Security\PermissionSet\Depository\PermissionSet as PermissionSetDepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property-read int|null $id
|
* @property-read int|null $id
|
||||||
|
@ -47,6 +48,21 @@ class PermissionSet extends BaseEntity
|
||||||
$this->deny_gid = $deny_gid;
|
$this->deny_gid = $deny_gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks, if the current PermissionSet is a/the public PermissionSet
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPublic(): bool
|
||||||
|
{
|
||||||
|
return (($this->id === PermissionSetDepository::PUBLIC) ||
|
||||||
|
(is_null($this->id) &&
|
||||||
|
empty($this->allow_cid) &&
|
||||||
|
empty($this->allow_gid) &&
|
||||||
|
empty($this->deny_cid) &&
|
||||||
|
empty($this->deny_gid)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Entity with a new allowed_cid list (wipes the id because it isn't the same entity anymore)
|
* Creates a new Entity with a new allowed_cid list (wipes the id because it isn't the same entity anymore)
|
||||||
*
|
*
|
||||||
|
|
|
@ -51,7 +51,8 @@ class PermissionSet extends BaseFactory implements ICanCreateFromTableRow
|
||||||
string $allow_cid = '',
|
string $allow_cid = '',
|
||||||
string $allow_gid = '',
|
string $allow_gid = '',
|
||||||
string $deny_cid = '',
|
string $deny_cid = '',
|
||||||
string $deny_gid = ''): Entity\PermissionSet
|
string $deny_gid = '',
|
||||||
|
int $id = null): Entity\PermissionSet
|
||||||
{
|
{
|
||||||
return $this->createFromTableRow([
|
return $this->createFromTableRow([
|
||||||
'uid' => $uid,
|
'uid' => $uid,
|
||||||
|
@ -59,6 +60,7 @@ class PermissionSet extends BaseFactory implements ICanCreateFromTableRow
|
||||||
'allow_gid' => $allow_gid,
|
'allow_gid' => $allow_gid,
|
||||||
'deny_cid' => $deny_cid,
|
'deny_cid' => $deny_cid,
|
||||||
'deny_gid' => $deny_gid,
|
'deny_gid' => $deny_gid,
|
||||||
|
'id' => $id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
|
||||||
if (!defined('DB_UPDATE_VERSION')) {
|
if (!defined('DB_UPDATE_VERSION')) {
|
||||||
define('DB_UPDATE_VERSION', 1439);
|
define('DB_UPDATE_VERSION', 1440);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -1047,5 +1047,23 @@
|
||||||
INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`
|
INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`
|
||||||
WHERE NOT `workerqueue`.`done`"
|
WHERE NOT `workerqueue`.`done`"
|
||||||
],
|
],
|
||||||
|
"profile_field-view" => [
|
||||||
|
"fields" => [
|
||||||
|
"id" => ["profile_field", "id"],
|
||||||
|
"uid" => ["profile_field", "uid"],
|
||||||
|
"label" => ["profile_field", "label"],
|
||||||
|
"value" => ["profile_field", "value"],
|
||||||
|
"order" => ["profile_field", "order"],
|
||||||
|
"psid"=> ["profile_field", "psid"],
|
||||||
|
"allow_cid" => ["permissionset", "allow_cid"],
|
||||||
|
"allow_gid" => ["permissionset", "allow_gid"],
|
||||||
|
"deny_cid" => ["permissionset", "deny_cid"],
|
||||||
|
"deny_gid" => ["permissionset", "deny_gid"],
|
||||||
|
"created" => ["profile_field", "created"],
|
||||||
|
"edited" => ["profile_field", "edited"],
|
||||||
|
],
|
||||||
|
"query" => "FROM `profile_field`
|
||||||
|
INNER JOIN `permissionset` ON `permissionset`.`id` = `profile_field`.`psid`"
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
9
tests/Util/CollectionDouble.php
Normal file
9
tests/Util/CollectionDouble.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Test\Util;
|
||||||
|
|
||||||
|
use Friendica\BaseCollection;
|
||||||
|
|
||||||
|
class CollectionDouble extends BaseCollection
|
||||||
|
{
|
||||||
|
}
|
26
tests/Util/EntityDouble.php
Normal file
26
tests/Util/EntityDouble.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Test\Util;
|
||||||
|
|
||||||
|
use Friendica\BaseEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property-read string $protString
|
||||||
|
* @property-read int $protInt
|
||||||
|
* @property-read \DateTime $protDateTime
|
||||||
|
*/
|
||||||
|
class EntityDouble extends BaseEntity
|
||||||
|
{
|
||||||
|
protected $protString;
|
||||||
|
protected $protInt;
|
||||||
|
protected $protDateTime;
|
||||||
|
private $privString;
|
||||||
|
|
||||||
|
public function __construct(string $protString, int $protInt, \DateTime $protDateTime, string $privString)
|
||||||
|
{
|
||||||
|
$this->protString = $protString;
|
||||||
|
$this->protInt = $protInt;
|
||||||
|
$this->protDateTime = $protDateTime;
|
||||||
|
$this->privString = $privString;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,8 @@ use Friendica\Model\Notification;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
// Empty these tables
|
// Empty these tables
|
||||||
|
'profile_field',
|
||||||
|
'permissionset',
|
||||||
'cache',
|
'cache',
|
||||||
'conversation',
|
'conversation',
|
||||||
'pconfig',
|
'pconfig',
|
||||||
|
|
24
tests/src/CollectionTest.php
Normal file
24
tests/src/CollectionTest.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Test\src;
|
||||||
|
|
||||||
|
use Friendica\Test\MockedTest;
|
||||||
|
use Friendica\Test\Util\CollectionDouble;
|
||||||
|
use Friendica\Test\Util\EntityDouble;
|
||||||
|
|
||||||
|
class CollectionTest extends MockedTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test if the BaseCollection::column() works as expected
|
||||||
|
*/
|
||||||
|
public function testGetArrayCopy()
|
||||||
|
{
|
||||||
|
$collection = new CollectionDouble();
|
||||||
|
$collection->append(new EntityDouble('test', 23, new \DateTime('now', new \DateTimeZone('UTC')), 'privTest'));
|
||||||
|
$collection->append(new EntityDouble('test2', 25, new \DateTime('now', new \DateTimeZone('UTC')), 'privTest23'));
|
||||||
|
|
||||||
|
self::assertEquals(['test', 'test2'], $collection->column('protString'));
|
||||||
|
self::assertEmpty($collection->column('privString'));
|
||||||
|
self::assertEquals([23,25], $collection->column('protInt'));
|
||||||
|
}
|
||||||
|
}
|
136
tests/src/Profile/ProfileField/Depository/ProfileFieldTest.php
Normal file
136
tests/src/Profile/ProfileField/Depository/ProfileFieldTest.php
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Test\src\Profile\ProfileField\Depository;
|
||||||
|
|
||||||
|
use Friendica\Profile\ProfileField\Collection\ProfileFields;
|
||||||
|
use Friendica\Profile\ProfileField\Depository\ProfileField as ProfileFieldDepository;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\ProfileFieldPersistenceException;
|
||||||
|
use Friendica\Profile\ProfileField\Factory\ProfileField as ProfileFieldFactory;
|
||||||
|
use Friendica\Security\PermissionSet\Depository\PermissionSet;
|
||||||
|
use Friendica\Security\PermissionSet\Factory\PermissionSet as PermissionSetFactory;
|
||||||
|
use Friendica\Security\PermissionSet\Depository\PermissionSet as PermissionSetDepository;
|
||||||
|
use Friendica\Test\FixtureTest;
|
||||||
|
use Friendica\DI;
|
||||||
|
|
||||||
|
class ProfileFieldTest extends FixtureTest
|
||||||
|
{
|
||||||
|
/** @var ProfileFieldDepository */
|
||||||
|
private $depository;
|
||||||
|
/** @var ProfileFieldFactory */
|
||||||
|
private $factory;
|
||||||
|
/** @var PermissionSetFactory */
|
||||||
|
private $permissionSetFactory;
|
||||||
|
/** @var PermissionSetDepository */
|
||||||
|
private $permissionSetDepository;
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->depository = DI::profileField();
|
||||||
|
$this->factory = DI::profileFieldFactory();
|
||||||
|
$this->permissionSetFactory = DI::permissionSetFactory();
|
||||||
|
$this->permissionSetDepository = DI::permissionSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test create ProfileField without a valid PermissionSet
|
||||||
|
*/
|
||||||
|
public function testSavingWithoutPermissionSet()
|
||||||
|
{
|
||||||
|
self::expectExceptionMessage('PermissionSet needs to be saved first.');
|
||||||
|
self::expectException(ProfileFieldPersistenceException::class);
|
||||||
|
|
||||||
|
$profileField = $this->factory->createFromValues(42, 0, 'public', 'value', $this->permissionSetFactory->createFromString(42, '', '<~>'));
|
||||||
|
|
||||||
|
self::assertEquals($profileField->uid, $profileField->permissionSet->uid);
|
||||||
|
|
||||||
|
$this->depository->save($profileField);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test saving a new entity
|
||||||
|
*/
|
||||||
|
public function testSaveNew()
|
||||||
|
{
|
||||||
|
$profileField = $this->factory->createFromValues(42, 0, 'public', 'value', $this->permissionSetDepository->save($this->permissionSetFactory->createFromString(42, '', '<~>')));
|
||||||
|
|
||||||
|
self::assertEquals($profileField->uid, $profileField->permissionSet->uid);
|
||||||
|
|
||||||
|
$savedProfileField = $this->depository->save($profileField);
|
||||||
|
|
||||||
|
self::assertNotNull($savedProfileField->id);
|
||||||
|
self::assertNull($profileField->id);
|
||||||
|
|
||||||
|
$selectedProfileField = $this->depository->selectOneById($savedProfileField->id);
|
||||||
|
|
||||||
|
self::assertEquals($savedProfileField, $selectedProfileField);
|
||||||
|
|
||||||
|
$profileFields = new ProfileFields([$selectedProfileField]);
|
||||||
|
$this->depository->deleteCollection($profileFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test updating the order of a ProfileField
|
||||||
|
*/
|
||||||
|
public function testUpdateOrder()
|
||||||
|
{
|
||||||
|
$profileField = $this->factory->createFromValues(42, 0, 'public', 'value', $this->permissionSetDepository->save($this->permissionSetFactory->createFromString(42, '', '<~>')));
|
||||||
|
|
||||||
|
self::assertEquals($profileField->uid, $profileField->permissionSet->uid);
|
||||||
|
|
||||||
|
$savedProfileField = $this->depository->save($profileField);
|
||||||
|
|
||||||
|
self::assertNotNull($savedProfileField->id);
|
||||||
|
self::assertNull($profileField->id);
|
||||||
|
|
||||||
|
$selectedProfileField = $this->depository->selectOneById($savedProfileField->id);
|
||||||
|
|
||||||
|
self::assertEquals($savedProfileField, $selectedProfileField);
|
||||||
|
|
||||||
|
$selectedProfileField->setOrder(66);
|
||||||
|
|
||||||
|
$updatedOrderProfileField = $this->depository->save($selectedProfileField);
|
||||||
|
|
||||||
|
self::assertEquals($selectedProfileField->id, $updatedOrderProfileField->id);
|
||||||
|
self::assertEquals(66, $updatedOrderProfileField->order);
|
||||||
|
|
||||||
|
// Even using the ID of the old, saved ProfileField returns the right instance
|
||||||
|
$updatedFromOldProfileField = $this->depository->selectOneById($savedProfileField->id);
|
||||||
|
self::assertEquals(66, $updatedFromOldProfileField->order);
|
||||||
|
|
||||||
|
$profileFields = new ProfileFields([$updatedFromOldProfileField]);
|
||||||
|
$this->depository->deleteCollection($profileFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test updating a whole entity
|
||||||
|
*/
|
||||||
|
public function testUpdate()
|
||||||
|
{
|
||||||
|
$profileField = $this->factory->createFromValues(42, 0, 'public', 'value', $this->permissionSetDepository->save($this->permissionSetFactory->createFromString(42, '', '<~>')));
|
||||||
|
|
||||||
|
self::assertEquals($profileField->uid, $profileField->permissionSet->uid);
|
||||||
|
|
||||||
|
$savedProfileField = $this->depository->save($profileField);
|
||||||
|
|
||||||
|
self::assertNotNull($savedProfileField->id);
|
||||||
|
self::assertNull($profileField->id);
|
||||||
|
|
||||||
|
$selectedProfileField = $this->depository->selectOneById($savedProfileField->id);
|
||||||
|
|
||||||
|
self::assertEquals($savedProfileField, $selectedProfileField);
|
||||||
|
|
||||||
|
$savedProfileField->update('another', 5, $this->permissionSetDepository->selectPublicForUser(42));
|
||||||
|
self::assertEquals(PermissionSet::PUBLIC, $savedProfileField->permissionSet->id);
|
||||||
|
|
||||||
|
$publicProfileField = $this->depository->save($savedProfileField);
|
||||||
|
|
||||||
|
self::assertEquals($this->permissionSetDepository->selectPublicForUser(42), $publicProfileField->permissionSet);
|
||||||
|
self::assertEquals('another', $publicProfileField->value);
|
||||||
|
self::assertEquals(5, $publicProfileField->order);
|
||||||
|
|
||||||
|
$profileFields = new ProfileFields([$publicProfileField]);
|
||||||
|
$this->depository->deleteCollection($profileFields);
|
||||||
|
}
|
||||||
|
}
|
208
tests/src/Profile/ProfileField/Entity/ProfileFieldTest.php
Normal file
208
tests/src/Profile/ProfileField/Entity/ProfileFieldTest.php
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Friendica\Test\src\Profile\ProfileField\Entity;
|
||||||
|
|
||||||
|
use Friendica\Profile\ProfileField\Entity\ProfileField;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\ProfileFieldNotFoundException;
|
||||||
|
use Friendica\Profile\ProfileField\Exception\UnexpectedPermissionSetException;
|
||||||
|
use Friendica\Profile\ProfileField\Factory\ProfileField as ProfileFieldFactory;
|
||||||
|
use Friendica\Security\PermissionSet\Depository\PermissionSet as PermissionSetDepository;
|
||||||
|
use Friendica\Security\PermissionSet\Factory\PermissionSet as PermissionSetFactory;
|
||||||
|
use Friendica\Test\MockedTest;
|
||||||
|
use Friendica\Util\ACLFormatter;
|
||||||
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
use Friendica\Util\Logger\VoidLogger;
|
||||||
|
use Mockery\MockInterface;
|
||||||
|
|
||||||
|
class ProfileFieldTest extends MockedTest
|
||||||
|
{
|
||||||
|
/** @var MockInterface|PermissionSetDepository */
|
||||||
|
protected $permissionSetDepository;
|
||||||
|
/** @var ProfileFieldFactory */
|
||||||
|
protected $profileFieldFactory;
|
||||||
|
/** @var MockInterface|PermissionSetFactory */
|
||||||
|
protected $permissionSetFactory;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->permissionSetDepository = \Mockery::mock(PermissionSetDepository::class);
|
||||||
|
$this->permissionSetFactory = new PermissionSetFactory(new VoidLogger(), new ACLFormatter());
|
||||||
|
$this->profileFieldFactory = new ProfileFieldFactory(new VoidLogger(), $this->permissionSetFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dataEntity()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
'uid' => 23,
|
||||||
|
'order' => 1,
|
||||||
|
'psid' => 2,
|
||||||
|
'label' => 'test',
|
||||||
|
'value' => 'more',
|
||||||
|
'created' => new \DateTime('2021-10-10T21:12:00.000000+0000', new \DateTimeZone('UTC')),
|
||||||
|
'edited' => new \DateTime('2021-10-10T21:12:00.000000+0000', new \DateTimeZone('UTC')),
|
||||||
|
'permissionSet' => [
|
||||||
|
'uid' => 23,
|
||||||
|
'allow_cid' => "<1>",
|
||||||
|
'allow_gid' => "<~>",
|
||||||
|
'deny_cid' => '<2>',
|
||||||
|
'deny_gid' => '<3>',
|
||||||
|
'id' => 2,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'withId' => [
|
||||||
|
'uid' => 23,
|
||||||
|
'order' => 1,
|
||||||
|
'psid' => 2,
|
||||||
|
'label' => 'test',
|
||||||
|
'value' => 'more',
|
||||||
|
'created' => new \DateTime('2021-10-10T21:12:00.000000+0000', new \DateTimeZone('UTC')),
|
||||||
|
'edited' => new \DateTime('2021-10-10T21:12:00.000000+0000', new \DateTimeZone('UTC')),
|
||||||
|
'permissionSet' => [
|
||||||
|
'uid' => 23,
|
||||||
|
'allow_cid' => "<1>",
|
||||||
|
'allow_gid' => "<~>",
|
||||||
|
'deny_cid' => '<2>',
|
||||||
|
'deny_gid' => '<3>',
|
||||||
|
'id' => 2,
|
||||||
|
],
|
||||||
|
'id' => 54,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataEntity
|
||||||
|
*/
|
||||||
|
public function testEntity(int $uid, int $order, int $psid, string $label, string $value, \DateTime $created, \DateTime $edited, array $permissionSet, $id = null)
|
||||||
|
{
|
||||||
|
$entity = new ProfileField($uid, $order, $label, $value, $created, $edited, $this->permissionSetFactory->createFromTableRow($permissionSet), $id);
|
||||||
|
|
||||||
|
self::assertEquals($uid, $entity->uid);
|
||||||
|
self::assertEquals($order, $entity->order);
|
||||||
|
self::assertEquals($psid, $entity->permissionSet->id);
|
||||||
|
self::assertEquals($label, $entity->label);
|
||||||
|
self::assertEquals($value, $entity->value);
|
||||||
|
self::assertEquals($created, $entity->created);
|
||||||
|
self::assertEquals($edited, $entity->edited);
|
||||||
|
self::assertEquals($id, $entity->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataEntity
|
||||||
|
*/
|
||||||
|
public function testUpdate(int $uid, int $order, int $psid, string $label, string $value, \DateTime $created, \DateTime $edited, array $permissionSet, $id = null)
|
||||||
|
{
|
||||||
|
$permissionSet = $this->permissionSetFactory->createFromTableRow(['uid' => 2, 'id' => $psid]);
|
||||||
|
|
||||||
|
$entity = $this->profileFieldFactory->createFromTableRow([
|
||||||
|
'uid' => $uid,
|
||||||
|
'order' => $order,
|
||||||
|
'psid' => $psid,
|
||||||
|
'label' => $label,
|
||||||
|
'value' => $value,
|
||||||
|
'created' => $created->format(DateTimeFormat::MYSQL),
|
||||||
|
'edited' => $edited->format(DateTimeFormat::MYSQL),
|
||||||
|
'id' => $id,
|
||||||
|
], $permissionSet);
|
||||||
|
|
||||||
|
$permissionSetNew = $this->permissionSetFactory->createFromTableRow([
|
||||||
|
'uid' => 2,
|
||||||
|
'allow_cid' => '<1>',
|
||||||
|
'id' => 23
|
||||||
|
]);
|
||||||
|
|
||||||
|
$entity->update('updatedValue', 2345, $permissionSetNew);
|
||||||
|
|
||||||
|
self::assertEquals($uid, $entity->uid);
|
||||||
|
self::assertEquals(2345, $entity->order);
|
||||||
|
self::assertEquals(23, $entity->permissionSet->id);
|
||||||
|
self::assertEquals($label, $entity->label);
|
||||||
|
self::assertEquals('updatedValue', $entity->value);
|
||||||
|
self::assertEquals($created, $entity->created);
|
||||||
|
self::assertGreaterThan($edited, $entity->edited);
|
||||||
|
self::assertEquals($id, $entity->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataEntity
|
||||||
|
*/
|
||||||
|
public function testSetOrder(int $uid, int $order, int $psid, string $label, string $value, \DateTime $created, \DateTime $edited, array $permissionSet, $id = null)
|
||||||
|
{
|
||||||
|
$permissionSet = $this->permissionSetFactory->createFromTableRow(['uid' => 2, 'id' => $psid]);
|
||||||
|
|
||||||
|
$entity = $this->profileFieldFactory->createFromTableRow([
|
||||||
|
'uid' => $uid,
|
||||||
|
'order' => $order,
|
||||||
|
'psid' => $psid,
|
||||||
|
'label' => $label,
|
||||||
|
'value' => $value,
|
||||||
|
'created' => $created->format(DateTimeFormat::MYSQL),
|
||||||
|
'edited' => $edited->format(DateTimeFormat::MYSQL),
|
||||||
|
'id' => $id,
|
||||||
|
], $permissionSet);
|
||||||
|
|
||||||
|
$entity->setOrder(2345);
|
||||||
|
|
||||||
|
self::assertEquals($uid, $entity->uid);
|
||||||
|
self::assertEquals(2345, $entity->order);
|
||||||
|
self::assertEquals($psid, $entity->permissionSet->id);
|
||||||
|
self::assertEquals($label, $entity->label);
|
||||||
|
self::assertEquals($value, $entity->value);
|
||||||
|
self::assertEquals($created, $entity->created);
|
||||||
|
self::assertGreaterThan($edited, $entity->edited);
|
||||||
|
self::assertEquals($id, $entity->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the exception because of a wrong property
|
||||||
|
*
|
||||||
|
* @dataProvider dataEntity
|
||||||
|
*/
|
||||||
|
public function testWrongGet(int $uid, int $order, int $psid, string $label, string $value, \DateTime $created, \DateTime $edited, array $permissionSet, $id = null)
|
||||||
|
{
|
||||||
|
$entity = new ProfileField($uid, $order, $label, $value, $created, $edited, $this->permissionSetFactory->createFromTableRow($permissionSet), $id);
|
||||||
|
|
||||||
|
self::expectException(ProfileFieldNotFoundException::class);
|
||||||
|
$entity->wrong;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test gathering the permissionset
|
||||||
|
*
|
||||||
|
* @dataProvider dataEntity
|
||||||
|
*/
|
||||||
|
public function testPermissionSet(int $uid, int $order, int $psid, string $label, string $value, \DateTime $created, \DateTime $edited, array $permissionSet, $id = null)
|
||||||
|
{
|
||||||
|
$entity = new ProfileField($uid, $order, $label, $value, $created, $edited, $this->permissionSetFactory->createFromTableRow($permissionSet), $id);
|
||||||
|
|
||||||
|
$permissionSet = $this->permissionSetFactory->createFromTableRow(['uid' => $uid, 'id' => $psid]);
|
||||||
|
|
||||||
|
$this->permissionSetDepository->shouldReceive('selectOneById')->with($psid, $uid)->andReturns($permissionSet);
|
||||||
|
|
||||||
|
self::assertEquals($psid, $entity->permissionSet->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the exception because the factory cannot find a permissionSet ID, nor the permissionSet itself
|
||||||
|
*
|
||||||
|
* @dataProvider dataEntity
|
||||||
|
*/
|
||||||
|
public function testMissingPermissionFactory(int $uid, int $order, int $psid, string $label, string $value, \DateTime $created, \DateTime $edited, array $permissionSet, $id = null)
|
||||||
|
{
|
||||||
|
self::expectException(UnexpectedPermissionSetException::class);
|
||||||
|
self::expectExceptionMessage('Either set the PermissionSet fields (join) or the PermissionSet itself');
|
||||||
|
|
||||||
|
$entity = $this->profileFieldFactory->createFromTableRow([
|
||||||
|
'uid' => $uid,
|
||||||
|
'order' => $order,
|
||||||
|
'label' => $label,
|
||||||
|
'value' => $value,
|
||||||
|
'created' => $created->format(DateTimeFormat::MYSQL),
|
||||||
|
'edited' => $edited->format(DateTimeFormat::MYSQL),
|
||||||
|
'id' => $id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,39 +2,63 @@
|
||||||
|
|
||||||
namespace Friendica\Test\src\Security\PermissionSet\Depository;
|
namespace Friendica\Test\src\Security\PermissionSet\Depository;
|
||||||
|
|
||||||
use Dice\Dice;
|
use Friendica\Security\PermissionSet\Depository\PermissionSet as PermissionSetDepository;
|
||||||
use Friendica\Database\Database;
|
use Friendica\Security\PermissionSet\Entity\PermissionSet;
|
||||||
|
use Friendica\Security\PermissionSet\Factory\PermissionSet as PermissionSetFactory;
|
||||||
|
use Friendica\Test\FixtureTest;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Security\PermissionSet\Depository\PermissionSet;
|
|
||||||
use Friendica\Test\MockedTest;
|
|
||||||
use Friendica\Test\Util\Database\StaticDatabase;
|
|
||||||
|
|
||||||
class PermissionSetTest extends MockedTest
|
class PermissionSetTest extends FixtureTest
|
||||||
{
|
{
|
||||||
/** @var PermissionSet */
|
/** @var PermissionSetDepository */
|
||||||
private $depository;
|
private $depository;
|
||||||
|
/** @var PermissionSetFactory */
|
||||||
|
private $factory;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
$dice = (new Dice())
|
parent::setUp();
|
||||||
->addRules(include __DIR__ . '/../../../../../static/dependencies.config.php')
|
|
||||||
->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true]);
|
|
||||||
DI::init($dice);
|
|
||||||
|
|
||||||
$this->depository = DI::permissionSet();
|
$this->depository = DI::permissionSet();
|
||||||
}
|
$this->factory = DI::permissionSetFactory();
|
||||||
|
|
||||||
public function testSelectOneByIdPublicMissingUid()
|
|
||||||
{
|
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
|
||||||
|
|
||||||
$this->depository->selectOneById(PermissionSet::PUBLIC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSelectOneByIdPublic()
|
public function testSelectOneByIdPublic()
|
||||||
{
|
{
|
||||||
$permissionSet = $this->depository->selectOneById(PermissionSet::PUBLIC, 1);
|
$permissionSet = $this->depository->selectPublicForUser(1);
|
||||||
|
|
||||||
$this->assertInstanceOf(\Friendica\Security\PermissionSet\Entity\PermissionSet::class, $permissionSet);
|
$this->assertInstanceOf(PermissionSet::class, $permissionSet);
|
||||||
|
self::assertEmpty($permissionSet->allow_cid);
|
||||||
|
self::assertEmpty($permissionSet->allow_gid);
|
||||||
|
self::assertEmpty($permissionSet->deny_cid);
|
||||||
|
self::assertEmpty($permissionSet->deny_gid);
|
||||||
|
self::assertEmpty(PermissionSetDepository::PUBLIC, $permissionSet->id);
|
||||||
|
self::assertEquals(1, $permissionSet->uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test create/update PermissionSets
|
||||||
|
*/
|
||||||
|
public function testSaving()
|
||||||
|
{
|
||||||
|
$permissionSet = $this->factory->createFromString(42, '', '<~>');
|
||||||
|
|
||||||
|
$permissionSet = $this->depository->selectOrCreate($permissionSet);
|
||||||
|
|
||||||
|
self::assertNotNull($permissionSet->id);
|
||||||
|
|
||||||
|
$permissionSetSelected = $this->depository->selectOneById($permissionSet->id, 42);
|
||||||
|
|
||||||
|
self::assertEquals($permissionSet, $permissionSetSelected);
|
||||||
|
|
||||||
|
$newPermissionSet = $permissionSet->withAllowedContacts(['1', '2']);
|
||||||
|
$savedPermissionSet = $this->depository->save($newPermissionSet);
|
||||||
|
|
||||||
|
self::assertNotNull($savedPermissionSet->id);
|
||||||
|
self::assertNull($newPermissionSet->id);
|
||||||
|
|
||||||
|
$permissionSetSavedSelected = $this->depository->selectOneById($savedPermissionSet->id, 42);
|
||||||
|
|
||||||
|
self::assertEquals($savedPermissionSet, $permissionSetSavedSelected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
update.php
12
update.php
|
@ -55,6 +55,7 @@ use Friendica\Model\Photo;
|
||||||
use Friendica\Model\Post;
|
use Friendica\Model\Post;
|
||||||
use Friendica\Model\Profile;
|
use Friendica\Model\Profile;
|
||||||
use Friendica\Model\Storage;
|
use Friendica\Model\Storage;
|
||||||
|
use Friendica\Security\PermissionSet\Depository\PermissionSet;
|
||||||
use Friendica\Worker\Delivery;
|
use Friendica\Worker\Delivery;
|
||||||
|
|
||||||
// Post-update script of PR 5751
|
// Post-update script of PR 5751
|
||||||
|
@ -206,7 +207,7 @@ function update_1332()
|
||||||
$profiles = DBA::select('profile', [], $condition);
|
$profiles = DBA::select('profile', [], $condition);
|
||||||
|
|
||||||
while ($profile = DBA::fetch($profiles)) {
|
while ($profile = DBA::fetch($profiles)) {
|
||||||
DI::profileField()->migrateFromLegacyProfile($profile);
|
Profile::migrate($profile);
|
||||||
}
|
}
|
||||||
DBA::close($profiles);
|
DBA::close($profiles);
|
||||||
|
|
||||||
|
@ -1028,3 +1029,12 @@ function update_1439()
|
||||||
}
|
}
|
||||||
DBA::close($intros);
|
DBA::close($intros);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function update_1440()
|
||||||
|
{
|
||||||
|
// Fix wrong public permissionset
|
||||||
|
DBA::p("UPDATE `profile_field` SET `psid` = ? WHERE psid IN (SELECT `id` FROM `permissionset` WHERE `id` != ? AND `allow_cid` = '' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = '')", PermissionSet::PUBLIC, PermissionSet::PUBLIC);
|
||||||
|
DBA::delete('permissionset', ["`id` != ? AND `allow_cid` = '' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''", PermissionSet::PUBLIC]);
|
||||||
|
|
||||||
|
return Update::SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 2021.12-dev\n"
|
"Project-Id-Version: 2021.12-dev\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-10-16 19:31-0400\n"
|
"POT-Creation-Date: 2021-10-18 00:07+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -331,7 +331,7 @@ msgid "Access denied."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mod/cal.php:61 mod/cal.php:78 mod/photos.php:69 mod/photos.php:143
|
#: mod/cal.php:61 mod/cal.php:78 mod/photos.php:69 mod/photos.php:143
|
||||||
#: mod/photos.php:815 src/Model/Profile.php:228 src/Module/HCard.php:52
|
#: mod/photos.php:815 src/Model/Profile.php:229 src/Module/HCard.php:52
|
||||||
#: src/Module/Profile/Common.php:41 src/Module/Profile/Common.php:52
|
#: src/Module/Profile/Common.php:41 src/Module/Profile/Common.php:52
|
||||||
#: src/Module/Profile/Contacts.php:40 src/Module/Profile/Contacts.php:50
|
#: src/Module/Profile/Contacts.php:40 src/Module/Profile/Contacts.php:50
|
||||||
#: src/Module/Profile/Media.php:38 src/Module/Profile/Status.php:58
|
#: src/Module/Profile/Media.php:38 src/Module/Profile/Status.php:58
|
||||||
|
@ -509,7 +509,7 @@ msgstr ""
|
||||||
msgid "Permission settings"
|
msgid "Permission settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mod/editpost.php:116 src/Core/ACL.php:327
|
#: mod/editpost.php:116 src/Core/ACL.php:325
|
||||||
msgid "CC: email addresses"
|
msgid "CC: email addresses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -527,7 +527,7 @@ msgstr ""
|
||||||
msgid "Categories (comma-separated list)"
|
msgid "Categories (comma-separated list)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mod/editpost.php:123 src/Core/ACL.php:328
|
#: mod/editpost.php:123 src/Core/ACL.php:326
|
||||||
msgid "Example: bob@example.com, mary@example.com"
|
msgid "Example: bob@example.com, mary@example.com"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -545,7 +545,7 @@ msgid "Cancel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mod/editpost.php:134 src/Content/Conversation.php:380
|
#: mod/editpost.php:134 src/Content/Conversation.php:380
|
||||||
#: src/Content/Widget/VCard.php:107 src/Model/Profile.php:459
|
#: src/Content/Widget/VCard.php:107 src/Model/Profile.php:460
|
||||||
#: src/Module/Admin/Logs/View.php:92
|
#: src/Module/Admin/Logs/View.php:92
|
||||||
msgid "Message"
|
msgid "Message"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -615,13 +615,13 @@ msgid "Event Finishes:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mod/events.php:506 src/Module/Profile/Profile.php:172
|
#: mod/events.php:506 src/Module/Profile/Profile.php:172
|
||||||
#: src/Module/Settings/Profile/Index.php:239
|
#: src/Module/Settings/Profile/Index.php:237
|
||||||
msgid "Description:"
|
msgid "Description:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: mod/events.php:508 src/Content/Widget/VCard.php:98 src/Model/Event.php:80
|
#: mod/events.php:508 src/Content/Widget/VCard.php:98 src/Model/Event.php:80
|
||||||
#: src/Model/Event.php:107 src/Model/Event.php:466 src/Model/Event.php:915
|
#: src/Model/Event.php:107 src/Model/Event.php:466 src/Model/Event.php:915
|
||||||
#: src/Model/Profile.php:367 src/Module/Contact.php:565
|
#: src/Model/Profile.php:368 src/Module/Contact.php:565
|
||||||
#: src/Module/Directory.php:150 src/Module/Notifications/Introductions.php:165
|
#: src/Module/Directory.php:150 src/Module/Notifications/Introductions.php:165
|
||||||
#: src/Module/Profile/Profile.php:194
|
#: src/Module/Profile/Profile.php:194
|
||||||
msgid "Location:"
|
msgid "Location:"
|
||||||
|
@ -647,7 +647,7 @@ msgstr ""
|
||||||
#: src/Module/Install.php:245 src/Module/Install.php:287
|
#: src/Module/Install.php:245 src/Module/Install.php:287
|
||||||
#: src/Module/Install.php:324 src/Module/Invite.php:177
|
#: src/Module/Install.php:324 src/Module/Invite.php:177
|
||||||
#: src/Module/Item/Compose.php:150 src/Module/Profile/Profile.php:247
|
#: src/Module/Item/Compose.php:150 src/Module/Profile/Profile.php:247
|
||||||
#: src/Module/Settings/Profile/Index.php:223 src/Object/Post.php:963
|
#: src/Module/Settings/Profile/Index.php:221 src/Object/Post.php:963
|
||||||
#: view/theme/duepuntozero/config.php:69 view/theme/frio/config.php:160
|
#: view/theme/duepuntozero/config.php:69 view/theme/frio/config.php:160
|
||||||
#: view/theme/quattro/config.php:71 view/theme/vier/config.php:119
|
#: view/theme/quattro/config.php:71 view/theme/vier/config.php:119
|
||||||
msgid "Submit"
|
msgid "Submit"
|
||||||
|
@ -2374,7 +2374,7 @@ msgstr ""
|
||||||
msgid "All contacts"
|
msgid "All contacts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/BaseModule.php:212 src/Content/Widget.php:231 src/Core/ACL.php:195
|
#: src/BaseModule.php:212 src/Content/Widget.php:231 src/Core/ACL.php:193
|
||||||
#: src/Module/Contact.php:756 src/Module/PermissionTooltip.php:75
|
#: src/Module/Contact.php:756 src/Module/PermissionTooltip.php:75
|
||||||
#: src/Module/PermissionTooltip.php:97
|
#: src/Module/PermissionTooltip.php:97
|
||||||
msgid "Followers"
|
msgid "Followers"
|
||||||
|
@ -2988,7 +2988,7 @@ msgstr ""
|
||||||
|
|
||||||
#: src/Content/Item.php:444 src/Content/Item.php:466 src/Model/Contact.php:1010
|
#: src/Content/Item.php:444 src/Content/Item.php:466 src/Model/Contact.php:1010
|
||||||
#: src/Model/Contact.php:1068 src/Model/Contact.php:1077
|
#: src/Model/Contact.php:1068 src/Model/Contact.php:1077
|
||||||
#: src/Module/Directory.php:160 src/Module/Settings/Profile/Index.php:226
|
#: src/Module/Directory.php:160 src/Module/Settings/Profile/Index.php:224
|
||||||
msgid "View Profile"
|
msgid "View Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -3357,7 +3357,7 @@ msgid "The end"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Content/Text/HTML.php:885 src/Content/Widget/VCard.php:103
|
#: src/Content/Text/HTML.php:885 src/Content/Widget/VCard.php:103
|
||||||
#: src/Model/Profile.php:453
|
#: src/Model/Profile.php:454
|
||||||
msgid "Follow"
|
msgid "Follow"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -3533,68 +3533,68 @@ msgstr[1] ""
|
||||||
msgid "More Trending Tags"
|
msgid "More Trending Tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Content/Widget/VCard.php:96 src/Model/Profile.php:372
|
#: src/Content/Widget/VCard.php:96 src/Model/Profile.php:373
|
||||||
#: src/Module/Contact.php:567 src/Module/Profile/Profile.php:176
|
#: src/Module/Contact.php:567 src/Module/Profile/Profile.php:176
|
||||||
msgid "XMPP:"
|
msgid "XMPP:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Content/Widget/VCard.php:97 src/Model/Profile.php:373
|
#: src/Content/Widget/VCard.php:97 src/Model/Profile.php:374
|
||||||
#: src/Module/Contact.php:569 src/Module/Profile/Profile.php:180
|
#: src/Module/Contact.php:569 src/Module/Profile/Profile.php:180
|
||||||
msgid "Matrix:"
|
msgid "Matrix:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Content/Widget/VCard.php:101 src/Model/Profile.php:465
|
#: src/Content/Widget/VCard.php:101 src/Model/Profile.php:466
|
||||||
#: src/Module/Notifications/Introductions.php:179
|
#: src/Module/Notifications/Introductions.php:179
|
||||||
msgid "Network:"
|
msgid "Network:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Content/Widget/VCard.php:105 src/Model/Profile.php:455
|
#: src/Content/Widget/VCard.php:105 src/Model/Profile.php:456
|
||||||
msgid "Unfollow"
|
msgid "Unfollow"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:166 src/Module/Profile/Profile.php:242
|
#: src/Core/ACL.php:164 src/Module/Profile/Profile.php:242
|
||||||
msgid "Yourself"
|
msgid "Yourself"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:202 src/Module/PermissionTooltip.php:81
|
#: src/Core/ACL.php:200 src/Module/PermissionTooltip.php:81
|
||||||
#: src/Module/PermissionTooltip.php:103
|
#: src/Module/PermissionTooltip.php:103
|
||||||
msgid "Mutuals"
|
msgid "Mutuals"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:294
|
#: src/Core/ACL.php:292
|
||||||
msgid "Post to Email"
|
msgid "Post to Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:321
|
#: src/Core/ACL.php:319
|
||||||
msgid "Public"
|
msgid "Public"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:322
|
#: src/Core/ACL.php:320
|
||||||
msgid ""
|
msgid ""
|
||||||
"This content will be shown to all your followers and can be seen in the "
|
"This content will be shown to all your followers and can be seen in the "
|
||||||
"community pages and by anyone with its link."
|
"community pages and by anyone with its link."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:323
|
#: src/Core/ACL.php:321
|
||||||
msgid "Limited/Private"
|
msgid "Limited/Private"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:324
|
#: src/Core/ACL.php:322
|
||||||
msgid ""
|
msgid ""
|
||||||
"This content will be shown only to the people in the first box, to the "
|
"This content will be shown only to the people in the first box, to the "
|
||||||
"exception of the people mentioned in the second box. It won't appear "
|
"exception of the people mentioned in the second box. It won't appear "
|
||||||
"anywhere public."
|
"anywhere public."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:325
|
#: src/Core/ACL.php:323
|
||||||
msgid "Show to:"
|
msgid "Show to:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:326
|
#: src/Core/ACL.php:324
|
||||||
msgid "Except to:"
|
msgid "Except to:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/ACL.php:329
|
#: src/Core/ACL.php:327
|
||||||
msgid "Connectors"
|
msgid "Connectors"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4178,35 +4178,35 @@ msgid ""
|
||||||
"\t\t\t\t\tThe friendica database was successfully updated from %s to %s."
|
"\t\t\t\t\tThe friendica database was successfully updated from %s to %s."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/UserImport.php:124
|
#: src/Core/UserImport.php:125
|
||||||
msgid "Error decoding account file"
|
msgid "Error decoding account file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/UserImport.php:130
|
#: src/Core/UserImport.php:131
|
||||||
msgid "Error! No version data in file! This is not a Friendica account file?"
|
msgid "Error! No version data in file! This is not a Friendica account file?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/UserImport.php:138
|
#: src/Core/UserImport.php:139
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "User '%s' already exists on this server!"
|
msgid "User '%s' already exists on this server!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/UserImport.php:174
|
#: src/Core/UserImport.php:175
|
||||||
msgid "User creation error"
|
msgid "User creation error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/UserImport.php:219
|
#: src/Core/UserImport.php:220
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "%d contact not imported"
|
msgid "%d contact not imported"
|
||||||
msgid_plural "%d contacts not imported"
|
msgid_plural "%d contacts not imported"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: src/Core/UserImport.php:272
|
#: src/Core/UserImport.php:273
|
||||||
msgid "User profile creation error"
|
msgid "User profile creation error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Core/UserImport.php:325
|
#: src/Core/UserImport.php:326
|
||||||
msgid "Done. You can now login with your username and password"
|
msgid "Done. You can now login with your username and password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4515,66 +4515,146 @@ msgstr ""
|
||||||
msgid "[no subject]"
|
msgid "[no subject]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:355 src/Module/Profile/Profile.php:256
|
#: src/Model/Profile.php:356 src/Module/Profile/Profile.php:256
|
||||||
#: src/Module/Profile/Profile.php:258
|
#: src/Module/Profile/Profile.php:258
|
||||||
msgid "Edit profile"
|
msgid "Edit profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:357
|
#: src/Model/Profile.php:358
|
||||||
msgid "Change profile photo"
|
msgid "Change profile photo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:370 src/Module/Directory.php:155
|
#: src/Model/Profile.php:371 src/Module/Directory.php:155
|
||||||
#: src/Module/Profile/Profile.php:184
|
#: src/Module/Profile/Profile.php:184
|
||||||
msgid "Homepage:"
|
msgid "Homepage:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:371 src/Module/Contact.php:571
|
#: src/Model/Profile.php:372 src/Module/Contact.php:571
|
||||||
#: src/Module/Notifications/Introductions.php:167
|
#: src/Module/Notifications/Introductions.php:167
|
||||||
msgid "About:"
|
msgid "About:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:457
|
#: src/Model/Profile.php:458
|
||||||
msgid "Atom feed"
|
msgid "Atom feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:495 src/Model/Profile.php:592
|
#: src/Model/Profile.php:496 src/Model/Profile.php:593
|
||||||
msgid "g A l F d"
|
msgid "g A l F d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:496
|
#: src/Model/Profile.php:497
|
||||||
msgid "F d"
|
msgid "F d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:558 src/Model/Profile.php:643
|
#: src/Model/Profile.php:559 src/Model/Profile.php:644
|
||||||
msgid "[today]"
|
msgid "[today]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:568
|
#: src/Model/Profile.php:569
|
||||||
msgid "Birthday Reminders"
|
msgid "Birthday Reminders"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:569
|
#: src/Model/Profile.php:570
|
||||||
msgid "Birthdays this week:"
|
msgid "Birthdays this week:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:630
|
#: src/Model/Profile.php:631
|
||||||
msgid "[No description]"
|
msgid "[No description]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:656
|
#: src/Model/Profile.php:657
|
||||||
msgid "Event Reminders"
|
msgid "Event Reminders"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:657
|
#: src/Model/Profile.php:658
|
||||||
msgid "Upcoming events the next 7 days:"
|
msgid "Upcoming events the next 7 days:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Profile.php:845
|
#: src/Model/Profile.php:846
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "OpenWebAuth: %1$s welcomes %2$s"
|
msgid "OpenWebAuth: %1$s welcomes %2$s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:978
|
||||||
|
msgid "Hometown:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:979
|
||||||
|
msgid "Marital Status:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:980
|
||||||
|
msgid "With:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:981
|
||||||
|
msgid "Since:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:982
|
||||||
|
msgid "Sexual Preference:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:983
|
||||||
|
msgid "Political Views:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:984
|
||||||
|
msgid "Religious Views:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:985
|
||||||
|
msgid "Likes:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:986
|
||||||
|
msgid "Dislikes:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:987
|
||||||
|
msgid "Title/Description:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:988 src/Module/Admin/Summary.php:234
|
||||||
|
msgid "Summary"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:989
|
||||||
|
msgid "Musical interests"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:990
|
||||||
|
msgid "Books, literature"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:991
|
||||||
|
msgid "Television"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:992
|
||||||
|
msgid "Film/dance/culture/entertainment"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:993
|
||||||
|
msgid "Hobbies/Interests"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:994
|
||||||
|
msgid "Love/romance"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:995
|
||||||
|
msgid "Work/employment"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:996
|
||||||
|
msgid "School/education"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Model/Profile.php:997
|
||||||
|
msgid "Contact information and Social Networks"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/Model/Storage/FilesystemConfig.php:77
|
#: src/Model/Storage/FilesystemConfig.php:77
|
||||||
msgid "Storage base path"
|
msgid "Storage base path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -6607,10 +6687,6 @@ msgstr ""
|
||||||
msgid "Server Settings"
|
msgid "Server Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Admin/Summary.php:234 src/Repository/ProfileField.php:290
|
|
||||||
msgid "Summary"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Module/Admin/Summary.php:236
|
#: src/Module/Admin/Summary.php:236
|
||||||
msgid "Registered users"
|
msgid "Registered users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -7731,7 +7807,7 @@ msgid "Sort by post received date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Conversation/Network.php:250
|
#: src/Module/Conversation/Network.php:250
|
||||||
#: src/Module/Settings/Profile/Index.php:228
|
#: src/Module/Settings/Profile/Index.php:226
|
||||||
msgid "Personal"
|
msgid "Personal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -7955,7 +8031,7 @@ msgid "Twitter Source / Tweet URL (requires API key)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Debug/Feed.php:38 src/Module/Filer/SaveTag.php:40
|
#: src/Module/Debug/Feed.php:38 src/Module/Filer/SaveTag.php:40
|
||||||
#: src/Module/Settings/Profile/Index.php:142
|
#: src/Module/Settings/Profile/Index.php:140
|
||||||
msgid "You must be logged in to use this module"
|
msgid "You must be logged in to use this module"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -8718,12 +8794,12 @@ msgstr ""
|
||||||
msgid "Birthday:"
|
msgid "Birthday:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Profile/Profile.php:167 src/Module/Settings/Profile/Index.php:246
|
#: src/Module/Profile/Profile.php:167 src/Module/Settings/Profile/Index.php:244
|
||||||
#: src/Util/Temporal.php:165
|
#: src/Util/Temporal.php:165
|
||||||
msgid "Age: "
|
msgid "Age: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Profile/Profile.php:167 src/Module/Settings/Profile/Index.php:246
|
#: src/Module/Profile/Profile.php:167 src/Module/Settings/Profile/Index.php:244
|
||||||
#: src/Util/Temporal.php:165
|
#: src/Util/Temporal.php:165
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "%d year old"
|
msgid "%d year old"
|
||||||
|
@ -9298,133 +9374,133 @@ msgstr ""
|
||||||
msgid "Beginning of week:"
|
msgid "Beginning of week:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:83
|
#: src/Module/Settings/Profile/Index.php:84
|
||||||
msgid "Profile Name is required."
|
msgid "Profile Name is required."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:134
|
#: src/Module/Settings/Profile/Index.php:132
|
||||||
msgid "Profile couldn't be updated."
|
msgid "Profile couldn't be updated."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:173
|
#: src/Module/Settings/Profile/Index.php:171
|
||||||
#: src/Module/Settings/Profile/Index.php:193
|
#: src/Module/Settings/Profile/Index.php:191
|
||||||
msgid "Label:"
|
msgid "Label:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:174
|
#: src/Module/Settings/Profile/Index.php:172
|
||||||
#: src/Module/Settings/Profile/Index.php:194
|
#: src/Module/Settings/Profile/Index.php:192
|
||||||
msgid "Value:"
|
msgid "Value:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:184
|
#: src/Module/Settings/Profile/Index.php:182
|
||||||
#: src/Module/Settings/Profile/Index.php:204
|
#: src/Module/Settings/Profile/Index.php:202
|
||||||
msgid "Field Permissions"
|
msgid "Field Permissions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:185
|
#: src/Module/Settings/Profile/Index.php:183
|
||||||
#: src/Module/Settings/Profile/Index.php:205
|
#: src/Module/Settings/Profile/Index.php:203
|
||||||
msgid "(click to open/close)"
|
msgid "(click to open/close)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:191
|
#: src/Module/Settings/Profile/Index.php:189
|
||||||
msgid "Add a new profile field"
|
msgid "Add a new profile field"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:221
|
#: src/Module/Settings/Profile/Index.php:219
|
||||||
msgid "Profile Actions"
|
msgid "Profile Actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:222
|
#: src/Module/Settings/Profile/Index.php:220
|
||||||
msgid "Edit Profile Details"
|
msgid "Edit Profile Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:224
|
#: src/Module/Settings/Profile/Index.php:222
|
||||||
msgid "Change Profile Photo"
|
msgid "Change Profile Photo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:229
|
#: src/Module/Settings/Profile/Index.php:227
|
||||||
msgid "Profile picture"
|
msgid "Profile picture"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:230
|
#: src/Module/Settings/Profile/Index.php:228
|
||||||
msgid "Location"
|
msgid "Location"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:231 src/Util/Temporal.php:93
|
#: src/Module/Settings/Profile/Index.php:229 src/Util/Temporal.php:93
|
||||||
#: src/Util/Temporal.php:95
|
#: src/Util/Temporal.php:95
|
||||||
msgid "Miscellaneous"
|
msgid "Miscellaneous"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:232
|
#: src/Module/Settings/Profile/Index.php:230
|
||||||
msgid "Custom Profile Fields"
|
msgid "Custom Profile Fields"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:234 src/Module/Welcome.php:58
|
#: src/Module/Settings/Profile/Index.php:232 src/Module/Welcome.php:58
|
||||||
msgid "Upload Profile Photo"
|
msgid "Upload Profile Photo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:238
|
#: src/Module/Settings/Profile/Index.php:236
|
||||||
msgid "Display name:"
|
msgid "Display name:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:241
|
#: src/Module/Settings/Profile/Index.php:239
|
||||||
msgid "Street Address:"
|
msgid "Street Address:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:242
|
#: src/Module/Settings/Profile/Index.php:240
|
||||||
msgid "Locality/City:"
|
msgid "Locality/City:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:243
|
#: src/Module/Settings/Profile/Index.php:241
|
||||||
msgid "Region/State:"
|
msgid "Region/State:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:244
|
#: src/Module/Settings/Profile/Index.php:242
|
||||||
msgid "Postal/Zip Code:"
|
msgid "Postal/Zip Code:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:245
|
#: src/Module/Settings/Profile/Index.php:243
|
||||||
msgid "Country:"
|
msgid "Country:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:247
|
#: src/Module/Settings/Profile/Index.php:245
|
||||||
msgid "XMPP (Jabber) address:"
|
msgid "XMPP (Jabber) address:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:247
|
#: src/Module/Settings/Profile/Index.php:245
|
||||||
msgid "The XMPP address will be published so that people can follow you there."
|
msgid "The XMPP address will be published so that people can follow you there."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:248
|
#: src/Module/Settings/Profile/Index.php:246
|
||||||
msgid "Matrix (Element) address:"
|
msgid "Matrix (Element) address:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:248
|
#: src/Module/Settings/Profile/Index.php:246
|
||||||
msgid ""
|
msgid ""
|
||||||
"The Matrix address will be published so that people can follow you there."
|
"The Matrix address will be published so that people can follow you there."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:249
|
#: src/Module/Settings/Profile/Index.php:247
|
||||||
msgid "Homepage URL:"
|
msgid "Homepage URL:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:250
|
#: src/Module/Settings/Profile/Index.php:248
|
||||||
msgid "Public Keywords:"
|
msgid "Public Keywords:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:250
|
#: src/Module/Settings/Profile/Index.php:248
|
||||||
msgid "(Used for suggesting potential friends, can be seen by others)"
|
msgid "(Used for suggesting potential friends, can be seen by others)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:251
|
#: src/Module/Settings/Profile/Index.php:249
|
||||||
msgid "Private Keywords:"
|
msgid "Private Keywords:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:251
|
#: src/Module/Settings/Profile/Index.php:249
|
||||||
msgid "(Used for searching profiles, never shown to others)"
|
msgid "(Used for searching profiles, never shown to others)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Module/Settings/Profile/Index.php:252
|
#: src/Module/Settings/Profile/Index.php:250
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<p>Custom fields appear on <a href=\"%s\">your profile page</a>.</p>\n"
|
"<p>Custom fields appear on <a href=\"%s\">your profile page</a>.</p>\n"
|
||||||
|
@ -10124,15 +10200,15 @@ msgstr ""
|
||||||
msgid "%s created a new post"
|
msgid "%s created a new post"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Navigation/Notifications/Factory/Introduction.php:134
|
#: src/Navigation/Notifications/Factory/Introduction.php:133
|
||||||
msgid "Friend Suggestion"
|
msgid "Friend Suggestion"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Navigation/Notifications/Factory/Introduction.php:160
|
#: src/Navigation/Notifications/Factory/Introduction.php:159
|
||||||
msgid "Friend/Connect Request"
|
msgid "Friend/Connect Request"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Navigation/Notifications/Factory/Introduction.php:160
|
#: src/Navigation/Notifications/Factory/Introduction.php:159
|
||||||
msgid "New Follower"
|
msgid "New Follower"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -10483,82 +10559,6 @@ msgstr ""
|
||||||
msgid "The folder view/smarty3/ must be writable by webserver."
|
msgid "The folder view/smarty3/ must be writable by webserver."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:280
|
|
||||||
msgid "Hometown:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:281
|
|
||||||
msgid "Marital Status:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:282
|
|
||||||
msgid "With:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:283
|
|
||||||
msgid "Since:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:284
|
|
||||||
msgid "Sexual Preference:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:285
|
|
||||||
msgid "Political Views:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:286
|
|
||||||
msgid "Religious Views:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:287
|
|
||||||
msgid "Likes:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:288
|
|
||||||
msgid "Dislikes:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:289
|
|
||||||
msgid "Title/Description:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:291
|
|
||||||
msgid "Musical interests"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:292
|
|
||||||
msgid "Books, literature"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:293
|
|
||||||
msgid "Television"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:294
|
|
||||||
msgid "Film/dance/culture/entertainment"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:295
|
|
||||||
msgid "Hobbies/Interests"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:296
|
|
||||||
msgid "Love/romance"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:297
|
|
||||||
msgid "Work/employment"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:298
|
|
||||||
msgid "School/education"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Repository/ProfileField.php:299
|
|
||||||
msgid "Contact information and Social Networks"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/Security/Authentication.php:209
|
#: src/Security/Authentication.php:209
|
||||||
msgid "Login failed."
|
msgid "Login failed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
Loading…
Reference in a new issue