summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChristopher Ng <chrng8@gmail.com>2021-10-14 08:19:40 +0000
committerChristopher Ng <chrng8@gmail.com>2021-10-19 04:59:35 +0000
commit309354852f12ae88d5eef05d311d6ebcba8ee762 (patch)
tree640c4e2394ba2a868d8d1cb6b5271fd1271bbdab /lib
parent7215148a242815a5064ce5d00a387c634dc936f3 (diff)
downloadnextcloud-server-309354852f12ae88d5eef05d311d6ebcba8ee762.tar.gz
nextcloud-server-309354852f12ae88d5eef05d311d6ebcba8ee762.zip
Profile backend
Signed-off-by: Christopher Ng <chrng8@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/composer/composer/autoload_classmap.php14
-rw-r--r--lib/composer/composer/autoload_static.php14
-rw-r--r--lib/private/AppFramework/Bootstrap/Coordinator.php21
-rw-r--r--lib/private/AppFramework/Bootstrap/RegistrationContext.php28
-rw-r--r--lib/private/Contacts/ContactsMenu/ActionProviderStore.php6
-rw-r--r--lib/private/Contacts/ContactsMenu/ContactsStore.php54
-rw-r--r--lib/private/Contacts/ContactsMenu/Entry.php37
-rw-r--r--lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php93
-rw-r--r--lib/private/Profile/Actions/EmailAction.php94
-rw-r--r--lib/private/Profile/Actions/PhoneAction.php94
-rw-r--r--lib/private/Profile/Actions/TwitterAction.php97
-rw-r--r--lib/private/Profile/Actions/WebsiteAction.php94
-rw-r--r--lib/private/Profile/ProfileManager.php333
-rw-r--r--lib/private/Profile/TProfileHelper.php46
-rw-r--r--lib/private/Setup.php3
-rw-r--r--lib/private/Template/SCSSCacher.php9
-rw-r--r--lib/public/Accounts/IAccountManager.php26
-rw-r--r--lib/public/AppFramework/Bootstrap/IRegistrationContext.php13
-rw-r--r--lib/public/Profile/ILinkAction.php115
-rw-r--r--lib/public/Profile/ParameterDoesNotExistException.php40
20 files changed, 1208 insertions, 23 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 343d2ddf027..fa1ef50c41e 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -460,6 +460,8 @@ return array(
'OCP\\Preview\\IProvider' => $baseDir . '/lib/public/Preview/IProvider.php',
'OCP\\Preview\\IProviderV2' => $baseDir . '/lib/public/Preview/IProviderV2.php',
'OCP\\Preview\\IVersionedPreviewFile' => $baseDir . '/lib/public/Preview/IVersionedPreviewFile.php',
+ 'OCP\\Profile\\ILinkAction' => $baseDir . '/lib/public/Profile/ILinkAction.php',
+ 'OCP\\Profile\\ParameterDoesNotExistException' => $baseDir . '/lib/public/Profile/ParameterDoesNotExistException.php',
'OCP\\Remote\\Api\\IApiCollection' => $baseDir . '/lib/public/Remote/Api/IApiCollection.php',
'OCP\\Remote\\Api\\IApiFactory' => $baseDir . '/lib/public/Remote/Api/IApiFactory.php',
'OCP\\Remote\\Api\\ICapabilitiesApi' => $baseDir . '/lib/public/Remote/Api/ICapabilitiesApi.php',
@@ -804,6 +806,7 @@ return array(
'OC\\Contacts\\ContactsMenu\\Entry' => $baseDir . '/lib/private/Contacts/ContactsMenu/Entry.php',
'OC\\Contacts\\ContactsMenu\\Manager' => $baseDir . '/lib/private/Contacts/ContactsMenu/Manager.php',
'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => $baseDir . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php',
+ 'OC\\Contacts\\ContactsMenu\\Providers\\ProfileProvider' => $baseDir . '/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php',
'OC\\Core\\Application' => $baseDir . '/core/Application.php',
'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => $baseDir . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php',
'OC\\Core\\BackgroundJobs\\CheckForUserCertificates' => $baseDir . '/core/BackgroundJobs/CheckForUserCertificates.php',
@@ -924,6 +927,8 @@ return array(
'OC\\Core\\Controller\\OCJSController' => $baseDir . '/core/Controller/OCJSController.php',
'OC\\Core\\Controller\\OCSController' => $baseDir . '/core/Controller/OCSController.php',
'OC\\Core\\Controller\\PreviewController' => $baseDir . '/core/Controller/PreviewController.php',
+ 'OC\\Core\\Controller\\ProfileApiController' => $baseDir . '/core/Controller/ProfileApiController.php',
+ 'OC\\Core\\Controller\\ProfilePageController' => $baseDir . '/core/Controller/ProfilePageController.php',
'OC\\Core\\Controller\\RecommendedAppsController' => $baseDir . '/core/Controller/RecommendedAppsController.php',
'OC\\Core\\Controller\\SearchController' => $baseDir . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => $baseDir . '/core/Controller/SetupController.php',
@@ -940,6 +945,8 @@ return array(
'OC\\Core\\Data\\LoginFlowV2Tokens' => $baseDir . '/core/Data/LoginFlowV2Tokens.php',
'OC\\Core\\Db\\LoginFlowV2' => $baseDir . '/core/Db/LoginFlowV2.php',
'OC\\Core\\Db\\LoginFlowV2Mapper' => $baseDir . '/core/Db/LoginFlowV2Mapper.php',
+ 'OC\\Core\\Db\\ProfileConfig' => $baseDir . '/core/Db/ProfileConfig.php',
+ 'OC\\Core\\Db\\ProfileConfigMapper' => $baseDir . '/core/Db/ProfileConfigMapper.php',
'OC\\Core\\Exception\\LoginFlowV2NotFoundException' => $baseDir . '/core/Exception/LoginFlowV2NotFoundException.php',
'OC\\Core\\Exception\\ResetPasswordException' => $baseDir . '/core/Exception/ResetPasswordException.php',
'OC\\Core\\Middleware\\TwoFactorMiddleware' => $baseDir . '/core/Middleware/TwoFactorMiddleware.php',
@@ -980,6 +987,7 @@ return array(
'OC\\Core\\Migrations\\Version22000Date20210216080825' => $baseDir . '/core/Migrations/Version22000Date20210216080825.php',
'OC\\Core\\Migrations\\Version23000Date20210721100600' => $baseDir . '/core/Migrations/Version23000Date20210721100600.php',
'OC\\Core\\Migrations\\Version23000Date20210906132259' => $baseDir . '/core/Migrations/Version23000Date20210906132259.php',
+ 'OC\\Core\\Migrations\\Version23000Date20210930122352' => $baseDir . '/core/Migrations/Version23000Date20210930122352.php',
'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php',
'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php',
'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php',
@@ -1300,6 +1308,12 @@ return array(
'OC\\Preview\\WatcherConnector' => $baseDir . '/lib/private/Preview/WatcherConnector.php',
'OC\\Preview\\WebP' => $baseDir . '/lib/private/Preview/WebP.php',
'OC\\Preview\\XBitmap' => $baseDir . '/lib/private/Preview/XBitmap.php',
+ 'OC\\Profile\\Actions\\EmailAction' => $baseDir . '/lib/private/Profile/Actions/EmailAction.php',
+ 'OC\\Profile\\Actions\\PhoneAction' => $baseDir . '/lib/private/Profile/Actions/PhoneAction.php',
+ 'OC\\Profile\\Actions\\TwitterAction' => $baseDir . '/lib/private/Profile/Actions/TwitterAction.php',
+ 'OC\\Profile\\Actions\\WebsiteAction' => $baseDir . '/lib/private/Profile/Actions/WebsiteAction.php',
+ 'OC\\Profile\\ProfileManager' => $baseDir . '/lib/private/Profile/ProfileManager.php',
+ 'OC\\Profile\\TProfileHelper' => $baseDir . '/lib/private/Profile/TProfileHelper.php',
'OC\\RedisFactory' => $baseDir . '/lib/private/RedisFactory.php',
'OC\\Remote\\Api\\ApiBase' => $baseDir . '/lib/private/Remote/Api/ApiBase.php',
'OC\\Remote\\Api\\ApiCollection' => $baseDir . '/lib/private/Remote/Api/ApiCollection.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 96ed5a614bc..89892d45ab0 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -489,6 +489,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Preview\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IProvider.php',
'OCP\\Preview\\IProviderV2' => __DIR__ . '/../../..' . '/lib/public/Preview/IProviderV2.php',
'OCP\\Preview\\IVersionedPreviewFile' => __DIR__ . '/../../..' . '/lib/public/Preview/IVersionedPreviewFile.php',
+ 'OCP\\Profile\\ILinkAction' => __DIR__ . '/../../..' . '/lib/public/Profile/ILinkAction.php',
+ 'OCP\\Profile\\ParameterDoesNotExistException' => __DIR__ . '/../../..' . '/lib/public/Profile/ParameterDoesNotExistException.php',
'OCP\\Remote\\Api\\IApiCollection' => __DIR__ . '/../../..' . '/lib/public/Remote/Api/IApiCollection.php',
'OCP\\Remote\\Api\\IApiFactory' => __DIR__ . '/../../..' . '/lib/public/Remote/Api/IApiFactory.php',
'OCP\\Remote\\Api\\ICapabilitiesApi' => __DIR__ . '/../../..' . '/lib/public/Remote/Api/ICapabilitiesApi.php',
@@ -833,6 +835,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Contacts\\ContactsMenu\\Entry' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Entry.php',
'OC\\Contacts\\ContactsMenu\\Manager' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Manager.php',
'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php',
+ 'OC\\Contacts\\ContactsMenu\\Providers\\ProfileProvider' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php',
'OC\\Core\\Application' => __DIR__ . '/../../..' . '/core/Application.php',
'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php',
'OC\\Core\\BackgroundJobs\\CheckForUserCertificates' => __DIR__ . '/../../..' . '/core/BackgroundJobs/CheckForUserCertificates.php',
@@ -953,6 +956,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Controller\\OCJSController' => __DIR__ . '/../../..' . '/core/Controller/OCJSController.php',
'OC\\Core\\Controller\\OCSController' => __DIR__ . '/../../..' . '/core/Controller/OCSController.php',
'OC\\Core\\Controller\\PreviewController' => __DIR__ . '/../../..' . '/core/Controller/PreviewController.php',
+ 'OC\\Core\\Controller\\ProfileApiController' => __DIR__ . '/../../..' . '/core/Controller/ProfileApiController.php',
+ 'OC\\Core\\Controller\\ProfilePageController' => __DIR__ . '/../../..' . '/core/Controller/ProfilePageController.php',
'OC\\Core\\Controller\\RecommendedAppsController' => __DIR__ . '/../../..' . '/core/Controller/RecommendedAppsController.php',
'OC\\Core\\Controller\\SearchController' => __DIR__ . '/../../..' . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => __DIR__ . '/../../..' . '/core/Controller/SetupController.php',
@@ -969,6 +974,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Data\\LoginFlowV2Tokens' => __DIR__ . '/../../..' . '/core/Data/LoginFlowV2Tokens.php',
'OC\\Core\\Db\\LoginFlowV2' => __DIR__ . '/../../..' . '/core/Db/LoginFlowV2.php',
'OC\\Core\\Db\\LoginFlowV2Mapper' => __DIR__ . '/../../..' . '/core/Db/LoginFlowV2Mapper.php',
+ 'OC\\Core\\Db\\ProfileConfig' => __DIR__ . '/../../..' . '/core/Db/ProfileConfig.php',
+ 'OC\\Core\\Db\\ProfileConfigMapper' => __DIR__ . '/../../..' . '/core/Db/ProfileConfigMapper.php',
'OC\\Core\\Exception\\LoginFlowV2NotFoundException' => __DIR__ . '/../../..' . '/core/Exception/LoginFlowV2NotFoundException.php',
'OC\\Core\\Exception\\ResetPasswordException' => __DIR__ . '/../../..' . '/core/Exception/ResetPasswordException.php',
'OC\\Core\\Middleware\\TwoFactorMiddleware' => __DIR__ . '/../../..' . '/core/Middleware/TwoFactorMiddleware.php',
@@ -1009,6 +1016,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Migrations\\Version22000Date20210216080825' => __DIR__ . '/../../..' . '/core/Migrations/Version22000Date20210216080825.php',
'OC\\Core\\Migrations\\Version23000Date20210721100600' => __DIR__ . '/../../..' . '/core/Migrations/Version23000Date20210721100600.php',
'OC\\Core\\Migrations\\Version23000Date20210906132259' => __DIR__ . '/../../..' . '/core/Migrations/Version23000Date20210906132259.php',
+ 'OC\\Core\\Migrations\\Version23000Date20210930122352' => __DIR__ . '/../../..' . '/core/Migrations/Version23000Date20210930122352.php',
'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php',
'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php',
'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php',
@@ -1329,6 +1337,12 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Preview\\WatcherConnector' => __DIR__ . '/../../..' . '/lib/private/Preview/WatcherConnector.php',
'OC\\Preview\\WebP' => __DIR__ . '/../../..' . '/lib/private/Preview/WebP.php',
'OC\\Preview\\XBitmap' => __DIR__ . '/../../..' . '/lib/private/Preview/XBitmap.php',
+ 'OC\\Profile\\Actions\\EmailAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/EmailAction.php',
+ 'OC\\Profile\\Actions\\PhoneAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/PhoneAction.php',
+ 'OC\\Profile\\Actions\\TwitterAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/TwitterAction.php',
+ 'OC\\Profile\\Actions\\WebsiteAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/WebsiteAction.php',
+ 'OC\\Profile\\ProfileManager' => __DIR__ . '/../../..' . '/lib/private/Profile/ProfileManager.php',
+ 'OC\\Profile\\TProfileHelper' => __DIR__ . '/../../..' . '/lib/private/Profile/TProfileHelper.php',
'OC\\RedisFactory' => __DIR__ . '/../../..' . '/lib/private/RedisFactory.php',
'OC\\Remote\\Api\\ApiBase' => __DIR__ . '/../../..' . '/lib/private/Remote/Api/ApiBase.php',
'OC\\Remote\\Api\\ApiCollection' => __DIR__ . '/../../..' . '/lib/private/Remote/Api/ApiCollection.php',
diff --git a/lib/private/AppFramework/Bootstrap/Coordinator.php b/lib/private/AppFramework/Bootstrap/Coordinator.php
index 8ffe54a2575..6e05b7fdc88 100644
--- a/lib/private/AppFramework/Bootstrap/Coordinator.php
+++ b/lib/private/AppFramework/Bootstrap/Coordinator.php
@@ -27,10 +27,14 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OC\AppFramework\Bootstrap;
-use OC\Support\CrashReport\Registry;
+use function class_exists;
+use function class_implements;
+use function in_array;
use OC_App;
+use OC\Support\CrashReport\Registry;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\QueryException;
@@ -39,9 +43,6 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\IServerContainer;
use Psr\Log\LoggerInterface;
use Throwable;
-use function class_exists;
-use function class_implements;
-use function in_array;
class Coordinator {
@@ -66,11 +67,13 @@ class Coordinator {
/** @var string[] */
private $bootedApps = [];
- public function __construct(IServerContainer $container,
- Registry $registry,
- IManager $dashboardManager,
- IEventDispatcher $eventListener,
- LoggerInterface $logger) {
+ public function __construct(
+ IServerContainer $container,
+ Registry $registry,
+ IManager $dashboardManager,
+ IEventDispatcher $eventListener,
+ LoggerInterface $logger
+ ) {
$this->serverContainer = $container;
$this->registry = $registry;
$this->dashboardManager = $dashboardManager;
diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
index 8eed6a5bde4..c638af94c84 100644
--- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php
+++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php
@@ -26,9 +26,11 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OC\AppFramework\Bootstrap;
use Closure;
+use function array_shift;
use OC\Support\CrashReport\Registry;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
@@ -43,11 +45,11 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Template\ICustomTemplateProvider;
use OCP\Http\WellKnown\IHandler;
use OCP\Notification\INotifier;
+use OCP\Profile\ILinkAction;
use OCP\Search\IProvider;
use OCP\Support\CrashReport\IReporter;
use Psr\Log\LoggerInterface;
use Throwable;
-use function array_shift;
class RegistrationContext {
@@ -60,6 +62,9 @@ class RegistrationContext {
/** @var ServiceRegistration<IWidget>[] */
private $dashboardPanels = [];
+ /** @var ServiceRegistration<ILinkAction>[] */
+ private $profileActions = [];
+
/** @var ServiceFactoryRegistration[] */
private $services = [];
@@ -236,6 +241,13 @@ class RegistrationContext {
$class
);
}
+
+ public function registerProfileAction(string $actionClass): void {
+ $this->context->registerProfileAction(
+ $this->appId,
+ $actionClass
+ );
+ }
};
}
@@ -316,6 +328,13 @@ class RegistrationContext {
}
/**
+ * @psalm-param class-string<ILinkAction> $capability
+ */
+ public function registerProfileAction(string $appId, string $actionClass): void {
+ $this->profileActions[] = new ServiceRegistration($appId, $actionClass);
+ }
+
+ /**
* @param App[] $apps
*/
public function delegateCapabilityRegistrations(array $apps): void {
@@ -552,4 +571,11 @@ class RegistrationContext {
public function getCalendarProviders(): array {
return $this->calendarProviders;
}
+
+ /**
+ * @return ServiceRegistration<ILinkAction>[]
+ */
+ public function getProfileActions(): array {
+ return $this->profileActions;
+ }
}
diff --git a/lib/private/Contacts/ContactsMenu/ActionProviderStore.php b/lib/private/Contacts/ContactsMenu/ActionProviderStore.php
index a984f9d6dfb..1db99497a21 100644
--- a/lib/private/Contacts/ContactsMenu/ActionProviderStore.php
+++ b/lib/private/Contacts/ContactsMenu/ActionProviderStore.php
@@ -24,11 +24,13 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OC\Contacts\ContactsMenu;
use Exception;
use OC\App\AppManager;
use OC\Contacts\ContactsMenu\Providers\EMailProvider;
+use OC\Contacts\ContactsMenu\Providers\ProfileProvider;
use OCP\AppFramework\QueryException;
use OCP\Contacts\ContactsMenu\IProvider;
use OCP\IServerContainer;
@@ -67,7 +69,8 @@ class ActionProviderStore {
try {
$providers[] = $this->serverContainer->query($class);
} catch (QueryException $ex) {
- $this->logger->error('Could not load contacts menu action provider ' . $class,
+ $this->logger->error(
+ 'Could not load contacts menu action provider ' . $class,
[
'app' => 'core',
'exception' => $ex,
@@ -85,6 +88,7 @@ class ActionProviderStore {
*/
private function getServerProviderClasses(): array {
return [
+ ProfileProvider::class,
EMailProvider::class,
];
}
diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php
index 31e13bbe8f2..a4a53bf8774 100644
--- a/lib/private/Contacts/ContactsMenu/ContactsStore.php
+++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php
@@ -1,4 +1,5 @@
<?php
+
/**
* @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
* @copyright 2017 Lukas Reschke <lukas@statuscode.ch>
@@ -27,18 +28,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OC\Contacts\ContactsMenu;
use OC\KnownUser\KnownUserService;
+use OCP\Accounts\IAccountManager;
use OCP\Contacts\ContactsMenu\IContactsStore;
use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\IManager;
use OCP\IConfig;
use OCP\IGroupManager;
+use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\L10N\IFactory as IL10NFactory;
class ContactsStore implements IContactsStore {
+ use \OC\Profile\TProfileHelper;
+
+ /** @var IAccountManager */
+ private $accountManager;
/** @var IManager */
private $contactsManager;
@@ -49,22 +58,36 @@ class ContactsStore implements IContactsStore {
/** @var IUserManager */
private $userManager;
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
/** @var IGroupManager */
private $groupManager;
/** @var KnownUserService */
private $knownUserService;
- public function __construct(IManager $contactsManager,
- IConfig $config,
- IUserManager $userManager,
- IGroupManager $groupManager,
- KnownUserService $knownUserService) {
+ /** @var IL10NFactory */
+ private $l10nFactory;
+
+ public function __construct(
+ IAccountManager $accountManager,
+ IManager $contactsManager,
+ IConfig $config,
+ IUserManager $userManager,
+ IURLGenerator $urlGenerator,
+ IGroupManager $groupManager,
+ KnownUserService $knownUserService,
+ IL10NFactory $l10nFactory
+ ) {
+ $this->accountManager = $accountManager;
$this->contactsManager = $contactsManager;
$this->config = $config;
$this->userManager = $userManager;
+ $this->urlGenerator = $urlGenerator;
$this->groupManager = $groupManager;
$this->knownUserService = $knownUserService;
+ $this->l10nFactory = $l10nFactory;
}
/**
@@ -116,9 +139,11 @@ class ContactsStore implements IContactsStore {
* @param string $filter
* @return Entry[] the filtered contacts
*/
- private function filterContacts(IUser $self,
- array $entries,
- $filter) {
+ private function filterContacts(
+ IUser $self,
+ array $entries,
+ $filter
+ ) {
$disallowEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') !== 'yes';
$restrictEnumerationGroup = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$restrictEnumerationPhone = $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
@@ -302,6 +327,19 @@ class ContactsStore implements IContactsStore {
}
}
+ // Provide profile parameters for core/src/OC/contactsmenu/contact.handlebars template
+ if (isset($contact['UID']) && isset($contact['FN'])) {
+ $targetUserId = $contact['UID'];
+ $user = $this->userManager->get($targetUserId);
+ if (!empty($user)) {
+ $account = $this->accountManager->getAccount($user);
+ if ($this->isProfileEnabled($account)) {
+ $entry->setProfileTitle($this->l10nFactory->get('core')->t('View profile'));
+ $entry->setProfileUrl($this->urlGenerator->linkToRouteAbsolute('core.ProfilePage.index', ['targetUserId' => $targetUserId]));
+ }
+ }
+ }
+
// Attach all other properties to the entry too because some
// providers might make use of it.
$entry->setProperties($contact);
diff --git a/lib/private/Contacts/ContactsMenu/Entry.php b/lib/private/Contacts/ContactsMenu/Entry.php
index aea71df2968..915a0434cc8 100644
--- a/lib/private/Contacts/ContactsMenu/Entry.php
+++ b/lib/private/Contacts/ContactsMenu/Entry.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OC\Contacts\ContactsMenu;
use OCP\Contacts\ContactsMenu\IAction;
@@ -43,6 +44,12 @@ class Entry implements IEntry {
/** @var string|null */
private $avatar;
+ /** @var string|null */
+ private $profileTitle;
+
+ /** @var string|null */
+ private $profileUrl;
+
/** @var IAction[] */
private $actions = [];
@@ -99,6 +106,34 @@ class Entry implements IEntry {
}
/**
+ * @param string $profileTitle
+ */
+ public function setProfileTitle(string $profileTitle): void {
+ $this->profileTitle = $profileTitle;
+ }
+
+ /**
+ * @return string
+ */
+ public function getProfileTitle(): ?string {
+ return $this->profileTitle;
+ }
+
+ /**
+ * @param string $profileUrl
+ */
+ public function setProfileUrl(string $profileUrl): void {
+ $this->profileUrl = $profileUrl;
+ }
+
+ /**
+ * @return string
+ */
+ public function getProfileUrl(): ?string {
+ return $this->profileUrl;
+ }
+
+ /**
* @param IAction $action
*/
public function addAction(IAction $action): void {
@@ -166,6 +201,8 @@ class Entry implements IEntry {
'actions' => $otherActions,
'lastMessage' => '',
'emailAddresses' => $this->getEMailAddresses(),
+ 'profileTitle' => $this->profileTitle,
+ 'profileUrl' => $this->profileUrl,
];
}
}
diff --git a/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php b/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
new file mode 100644
index 00000000000..4882c0ac883
--- /dev/null
+++ b/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Contacts\ContactsMenu\Providers;
+
+use OCP\Accounts\IAccountManager;
+use OCP\Contacts\ContactsMenu\IActionFactory;
+use OCP\Contacts\ContactsMenu\IEntry;
+use OCP\Contacts\ContactsMenu\IProvider;
+use OCP\IURLGenerator;
+use OCP\IUserManager;
+use OCP\L10N\IFactory as IL10NFactory;
+
+class ProfileProvider implements IProvider {
+ use \OC\Profile\TProfileHelper;
+
+ /** @var IAccountManager */
+ private $accountManager;
+
+ /** @var IActionFactory */
+ private $actionFactory;
+
+ /** @var IL10NFactory */
+ private $l10nFactory;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ /** @var IUserManager */
+ private $userManager;
+
+ /**
+ * @param IAccountManager $accountManager
+ * @param IActionFactory $actionFactory
+ * @param IL10NFactory $l10nFactory
+ * @param IURLGenerator $urlGenerator
+ * @param IUserManager $userManager
+ */
+ public function __construct(
+ IAccountManager $accountManager,
+ IActionFactory $actionFactory,
+ IL10NFactory $l10nFactory,
+ IURLGenerator $urlGenerator,
+ IUserManager $userManager
+ ) {
+ $this->accountManager = $accountManager;
+ $this->actionFactory = $actionFactory;
+ $this->l10nFactory = $l10nFactory;
+ $this->urlGenerator = $urlGenerator;
+ $this->userManager = $userManager;
+ }
+
+ /**
+ * @param IEntry $entry
+ */
+ public function process(IEntry $entry) {
+ $targetUserId = $entry->getProperty('UID');
+ $targetUser = $this->userManager->get($targetUserId);
+ if (!empty($targetUser)) {
+ $account = $this->accountManager->getAccount($targetUser);
+ if ($this->isProfileEnabled($account)) {
+ $iconUrl = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/profile.svg'));
+ $profileActionText = $this->l10nFactory->get('core')->t('View profile');
+ $profileUrl = $this->urlGenerator->linkToRouteAbsolute('core.ProfilePage.index', ['targetUserId' => $targetUserId]);
+ $action = $this->actionFactory->newLinkAction($iconUrl, $profileActionText, $profileUrl);
+ // Set highest priority (by descending order), other actions have the default priority 10 as defined in lib/private/Contacts/ContactsMenu/Actions/LinkAction.php
+ $action->setPriority(20);
+ $entry->addAction($action);
+ }
+ }
+ }
+}
diff --git a/lib/private/Profile/Actions/EmailAction.php b/lib/private/Profile/Actions/EmailAction.php
new file mode 100644
index 00000000000..1eef1236630
--- /dev/null
+++ b/lib/private/Profile/Actions/EmailAction.php
@@ -0,0 +1,94 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Profile\Actions;
+
+use OCP\Accounts\IAccountManager;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\L10N\IFactory;
+use OCP\Profile\ILinkAction;
+
+class EmailAction implements ILinkAction {
+
+ /** @var string */
+ private $value;
+
+ /** @var IAccountManager */
+ private $accountManager;
+
+ /** @var IFactory */
+ private $l10nFactory;
+
+ /** @var IUrlGenerator */
+ private $urlGenerator;
+
+ public function __construct(
+ IAccountManager $accountManager,
+ IFactory $l10nFactory,
+ IURLGenerator $urlGenerator
+ ) {
+ $this->accountManager = $accountManager;
+ $this->l10nFactory = $l10nFactory;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ public function preload(IUser $targetUser): void {
+ $account = $this->accountManager->getAccount($targetUser);
+ $this->value = $account->getProperty(IAccountManager::PROPERTY_EMAIL)->getValue();
+ }
+
+ public function getAppId(): string {
+ return 'core';
+ }
+
+ public function getId(): string {
+ return IAccountManager::PROPERTY_EMAIL;
+ }
+
+ public function getDisplayId(): string {
+ return $this->l10nFactory->get('core')->t('Email');
+ }
+
+ public function getTitle(): string {
+ return $this->l10nFactory->get('core')->t('Mail %s', [$this->value]);
+ }
+
+ public function getPriority(): int {
+ return 20;
+ }
+
+ public function getIcon(): string {
+ return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/mail.svg'));
+ }
+
+ public function getTarget(): ?string {
+ if (empty($this->value)) {
+ return null;
+ }
+ return 'mailto:' . $this->value;
+ }
+}
diff --git a/lib/private/Profile/Actions/PhoneAction.php b/lib/private/Profile/Actions/PhoneAction.php
new file mode 100644
index 00000000000..df0e30cd277
--- /dev/null
+++ b/lib/private/Profile/Actions/PhoneAction.php
@@ -0,0 +1,94 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Profile\Actions;
+
+use OCP\Accounts\IAccountManager;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\L10N\IFactory;
+use OCP\Profile\ILinkAction;
+
+class PhoneAction implements ILinkAction {
+
+ /** @var string */
+ private $value;
+
+ /** @var IAccountManager */
+ private $accountManager;
+
+ /** @var IFactory */
+ private $l10nFactory;
+
+ /** @var IUrlGenerator */
+ private $urlGenerator;
+
+ public function __construct(
+ IAccountManager $accountManager,
+ IFactory $l10nFactory,
+ IURLGenerator $urlGenerator
+ ) {
+ $this->accountManager = $accountManager;
+ $this->l10nFactory = $l10nFactory;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ public function preload(IUser $targetUser): void {
+ $account = $this->accountManager->getAccount($targetUser);
+ $this->value = $account->getProperty(IAccountManager::PROPERTY_PHONE)->getValue();
+ }
+
+ public function getAppId(): string {
+ return 'core';
+ }
+
+ public function getId(): string {
+ return IAccountManager::PROPERTY_PHONE;
+ }
+
+ public function getDisplayId(): string {
+ return $this->l10nFactory->get('core')->t('Phone');
+ }
+
+ public function getTitle(): string {
+ return $this->l10nFactory->get('core')->t('Call %s', [$this->value]);
+ }
+
+ public function getPriority(): int {
+ return 30;
+ }
+
+ public function getIcon(): string {
+ return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/phone.svg'));
+ }
+
+ public function getTarget(): ?string {
+ if (empty($this->value)) {
+ return null;
+ }
+ return 'tel:' . $this->value;
+ }
+}
diff --git a/lib/private/Profile/Actions/TwitterAction.php b/lib/private/Profile/Actions/TwitterAction.php
new file mode 100644
index 00000000000..3dcfa8aaf12
--- /dev/null
+++ b/lib/private/Profile/Actions/TwitterAction.php
@@ -0,0 +1,97 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Profile\Actions;
+
+use function Safe\substr;
+use OCP\Accounts\IAccountManager;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\L10N\IFactory;
+use OCP\Profile\ILinkAction;
+
+class TwitterAction implements ILinkAction {
+
+ /** @var string */
+ private $value;
+
+ /** @var IAccountManager */
+ private $accountManager;
+
+ /** @var IFactory */
+ private $l10nFactory;
+
+ /** @var IUrlGenerator */
+ private $urlGenerator;
+
+ public function __construct(
+ IAccountManager $accountManager,
+ IFactory $l10nFactory,
+ IURLGenerator $urlGenerator
+ ) {
+ $this->accountManager = $accountManager;
+ $this->l10nFactory = $l10nFactory;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ public function preload(IUser $targetUser): void {
+ $account = $this->accountManager->getAccount($targetUser);
+ $this->value = $account->getProperty(IAccountManager::PROPERTY_TWITTER)->getValue();
+ }
+
+ public function getAppId(): string {
+ return 'core';
+ }
+
+ public function getId(): string {
+ return IAccountManager::PROPERTY_TWITTER;
+ }
+
+ public function getDisplayId(): string {
+ return $this->l10nFactory->get('core')->t('Twitter');
+ }
+
+ public function getTitle(): string {
+ $displayUsername = $this->value[0] === '@' ? $this->value : '@' . $this->value;
+ return $this->l10nFactory->get('core')->t('View %s on Twitter', [$displayUsername]);
+ }
+
+ public function getPriority(): int {
+ return 50;
+ }
+
+ public function getIcon(): string {
+ return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/twitter.svg'));
+ }
+
+ public function getTarget(): ?string {
+ if (empty($this->value)) {
+ return null;
+ }
+ $username = $this->value[0] === '@' ? substr($this->value, 1) : $this->value;
+ return 'https://twitter.com/' . $username;
+ }
+}
diff --git a/lib/private/Profile/Actions/WebsiteAction.php b/lib/private/Profile/Actions/WebsiteAction.php
new file mode 100644
index 00000000000..ea1daeee20e
--- /dev/null
+++ b/lib/private/Profile/Actions/WebsiteAction.php
@@ -0,0 +1,94 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Profile\Actions;
+
+use OCP\Accounts\IAccountManager;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\L10N\IFactory;
+use OCP\Profile\ILinkAction;
+
+class WebsiteAction implements ILinkAction {
+
+ /** @var string */
+ private $value;
+
+ /** @var IAccountManager */
+ private $accountManager;
+
+ /** @var IFactory */
+ private $l10nFactory;
+
+ /** @var IUrlGenerator */
+ private $urlGenerator;
+
+ public function __construct(
+ IAccountManager $accountManager,
+ IFactory $l10nFactory,
+ IURLGenerator $urlGenerator
+ ) {
+ $this->accountManager = $accountManager;
+ $this->l10nFactory = $l10nFactory;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ public function preload(IUser $targetUser): void {
+ $account = $this->accountManager->getAccount($targetUser);
+ $this->value = $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getValue();
+ }
+
+ public function getAppId(): string {
+ return 'core';
+ }
+
+ public function getId(): string {
+ return IAccountManager::PROPERTY_WEBSITE;
+ }
+
+ public function getDisplayId(): string {
+ return $this->l10nFactory->get('core')->t('Website');
+ }
+
+ public function getTitle(): string {
+ return $this->l10nFactory->get('core')->t('Visit %s', [$this->value]);
+ }
+
+ public function getPriority(): int {
+ return 40;
+ }
+
+ public function getIcon(): string {
+ return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/timezone.svg'));
+ }
+
+ public function getTarget(): ?string {
+ if (empty($this->value)) {
+ return null;
+ }
+ return $this->value;
+ }
+}
diff --git a/lib/private/Profile/ProfileManager.php b/lib/private/Profile/ProfileManager.php
new file mode 100644
index 00000000000..6a38f4ae16d
--- /dev/null
+++ b/lib/private/Profile/ProfileManager.php
@@ -0,0 +1,333 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Profile;
+
+use function Safe\usort;
+
+use OC\AppFramework\Bootstrap\Coordinator;
+use OC\Core\Db\ProfileConfig;
+use OC\Core\Db\ProfileConfigMapper;
+use OC\KnownUser\KnownUserService;
+use OC\Profile\Actions\EmailAction;
+use OC\Profile\Actions\PhoneAction;
+use OC\Profile\Actions\TwitterAction;
+use OC\Profile\Actions\WebsiteAction;
+use OCP\Accounts\IAccountManager;
+use OCP\Accounts\PropertyDoesNotExistException;
+use OCP\App\IAppManager;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\IUser;
+use OCP\L10N\IFactory;
+use OCP\Profile\ILinkAction;
+use Psr\Container\ContainerInterface;
+use Psr\Log\LoggerInterface;
+
+/**
+ * @inheritDoc
+ */
+class ProfileManager {
+
+ /** @var IAccountManager */
+ private $accountManager;
+
+ /** @var IAppManager */
+ private $appManager;
+
+ /** @var ProfileConfigMapper */
+ private $configMapper;
+
+ /** @var ContainerInterface */
+ private $container;
+
+ /** @var KnownUserService */
+ private $knownUserService;
+
+ /** @var IFactory */
+ private $l10nFactory;
+
+ /** @var LoggerInterface */
+ private $logger;
+
+ /** @var Coordinator */
+ private $coordinator;
+
+ /** @var ILinkAction[] */
+ private $actions = [];
+
+ private const ACCOUNT_PROPERTY_ACTIONS = [
+ EmailAction::class,
+ PhoneAction::class,
+ WebsiteAction::class,
+ TwitterAction::class,
+ ];
+
+ /**
+ * Array of account properties displayed on the profile
+ */
+ private const PROFILE_PROPERTIES = [
+ IAccountManager::PROPERTY_ADDRESS,
+ IAccountManager::PROPERTY_BIOGRAPHY,
+ IAccountManager::PROPERTY_DISPLAYNAME,
+ IAccountManager::PROPERTY_HEADLINE,
+ IAccountManager::PROPERTY_ORGANISATION,
+ IAccountManager::PROPERTY_ROLE,
+ ];
+
+ public function __construct(
+ IAccountManager $accountManager,
+ IAppManager $appManager,
+ ProfileConfigMapper $configMapper,
+ ContainerInterface $container,
+ KnownUserService $knownUserService,
+ IFactory $l10nFactory,
+ LoggerInterface $logger,
+ Coordinator $coordinator
+ ) {
+ $this->accountManager = $accountManager;
+ $this->appManager = $appManager;
+ $this->configMapper = $configMapper;
+ $this->container = $container;
+ $this->knownUserService = $knownUserService;
+ $this->l10nFactory = $l10nFactory;
+ $this->logger = $logger;
+ $this->coordinator = $coordinator;
+ }
+
+ /**
+ * Register an action for the user
+ */
+ private function registerAction(IUser $targetUser, ?IUser $visitingUser, ILinkAction $action): void {
+ $action->preload($targetUser);
+
+ if ($action->getTarget() === null) {
+ // Actions without a target are not registered
+ return;
+ }
+
+ if (isset($this->actions[$action->getId()])) {
+ $this->logger->error('Cannot register duplicate action: ' . $action->getId());
+ return;
+ }
+
+ if ($action->getAppId() !== 'core') {
+ if (!$this->appManager->isEnabledForUser($action->getAppId(), $targetUser)) {
+ $this->logger->notice('App: ' . $action->getAppId() . ' cannot register actions as it is not enabled for the user: ' . $targetUser->getUID());
+ return;
+ }
+ if ($visitingUser === null) {
+ $this->logger->notice('App: ' . $action->getAppId() . ' cannot register actions as it is not available to non logged in users');
+ return;
+ }
+ if (!$this->appManager->isEnabledForUser($action->getAppId(), $visitingUser)) {
+ $this->logger->notice('App: ' . $action->getAppId() . ' cannot register actions as it is not enabled for the visiting user: ' . $visitingUser->getUID());
+ return;
+ }
+ }
+
+ // Add action to associative array of actions
+ $this->actions[$action->getId()] = $action;
+ }
+
+ /**
+ * Return an array of registered profile actions for the user
+ *
+ * @return ILinkAction[]
+ */
+ private function getActions(IUser $targetUser, ?IUser $visitingUser): array {
+ $context = $this->coordinator->getRegistrationContext();
+ if ($context === null) {
+ return [];
+ }
+
+ foreach (self::ACCOUNT_PROPERTY_ACTIONS as $actionClass) {
+ /** @var ILinkAction $provider */
+ $provider = $this->container->get($actionClass);
+ $this->registerAction($targetUser, $visitingUser, $provider);
+ }
+
+ foreach ($context->getProfileActions() as $registration) {
+ /** @var ILinkAction $provider */
+ $provider = $this->container->get($registration->getService());
+ $this->registerAction($targetUser, $visitingUser, $provider);
+ }
+
+ $actionsClone = $this->actions;
+ // Sort associative array into indexed array in ascending order of priority
+ usort($actionsClone, function (ILinkAction $a, ILinkAction $b) {
+ return $a->getPriority() === $b->getPriority() ? 0 : ($a->getPriority() < $b->getPriority() ? -1 : 1);
+ });
+ return $actionsClone;
+ }
+
+ /**
+ * Return whether the profile parameter is visible to the visiting user
+ */
+ private function isParameterVisible(IUser $targetUser, ?IUser $visitingUser, string $paramId): bool {
+ try {
+ $account = $this->accountManager->getAccount($targetUser);
+ $scope = $account->getProperty($paramId)->getScope();
+ } catch (PropertyDoesNotExistException $e) {
+ // Allow the exception as not all profile parameters are account properties
+ }
+
+ $visibility = $this->getProfileConfig($targetUser, $visitingUser)[$paramId]['visibility'];
+ // Handle profile visibility and account property scope
+ switch ($visibility) {
+ case ProfileConfig::VISIBILITY_HIDE:
+ return false;
+ case ProfileConfig::VISIBILITY_SHOW_USERS_ONLY:
+ if (!empty($scope)) {
+ switch ($scope) {
+ case IAccountManager::SCOPE_PRIVATE:
+ return $visitingUser !== null && $this->knownUserService->isKnownToUser($targetUser->getUID(), $visitingUser->getUID());
+ case IAccountManager::SCOPE_LOCAL:
+ case IAccountManager::SCOPE_FEDERATED:
+ case IAccountManager::SCOPE_PUBLISHED:
+ return $visitingUser !== null;
+ default:
+ return false;
+ }
+ }
+ return $visitingUser !== null;
+ case ProfileConfig::VISIBILITY_SHOW:
+ if (!empty($scope)) {
+ switch ($scope) {
+ case IAccountManager::SCOPE_PRIVATE:
+ return $visitingUser !== null && $this->knownUserService->isKnownToUser($targetUser->getUID(), $visitingUser->getUID());
+ case IAccountManager::SCOPE_LOCAL:
+ case IAccountManager::SCOPE_FEDERATED:
+ case IAccountManager::SCOPE_PUBLISHED:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getProfileParams(IUser $targetUser, ?IUser $visitingUser): array {
+ $account = $this->accountManager->getAccount($targetUser);
+ // Initialize associative array of profile parameters
+ $profileParameters = [
+ 'userId' => $account->getUser()->getUID(),
+ ];
+
+ // Add account properties
+ foreach (self::PROFILE_PROPERTIES as $property) {
+ $profileParameters[$property] =
+ $this->isParameterVisible($targetUser, $visitingUser, $property)
+ // Explicitly set to null when value is empty string
+ ? ($account->getProperty($property)->getValue() ?: null)
+ : null;
+ }
+
+ // Add avatar visibility
+ $profileParameters['isUserAvatarVisible'] = $this->isParameterVisible($targetUser, $visitingUser, IAccountManager::PROPERTY_AVATAR);
+
+ // Add actions
+ $profileParameters['actions'] = array_map(
+ function (ILinkAction $action) {
+ return [
+ 'id' => $action->getId(),
+ 'icon' => $action->getIcon(),
+ 'title' => $action->getTitle(),
+ 'target' => $action->getTarget(),
+ ];
+ },
+ // This is needed to reindex the array after filtering
+ array_values(
+ array_filter(
+ $this->getActions($targetUser, $visitingUser),
+ function (ILinkAction $action) use ($targetUser, $visitingUser) {
+ return $this->isParameterVisible($targetUser, $visitingUser, $action->getId());
+ }
+ ),
+ )
+ );
+
+ return $profileParameters;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getProfileConfig(IUser $targetUser, ?IUser $visitingUser): array {
+ try {
+ $configArray = $this->configMapper->getArray($targetUser->getUID());
+ } catch (DoesNotExistException $e) {
+ $config = new ProfileConfig();
+ $config->setUserId($targetUser->getUID());
+
+ // Map of account properties to display IDs
+ $propertyDisplayMap = [
+ IAccountManager::PROPERTY_ADDRESS => $this->l10nFactory->get('core')->t('Address'),
+ IAccountManager::PROPERTY_AVATAR => $this->l10nFactory->get('core')->t('Avatar'),
+ IAccountManager::PROPERTY_BIOGRAPHY => $this->l10nFactory->get('core')->t('About'),
+ IAccountManager::PROPERTY_DISPLAYNAME => $this->l10nFactory->get('core')->t('Full name'),
+ IAccountManager::PROPERTY_HEADLINE => $this->l10nFactory->get('core')->t('Headline'),
+ IAccountManager::PROPERTY_ORGANISATION => $this->l10nFactory->get('core')->t('Organisation'),
+ IAccountManager::PROPERTY_ROLE => $this->l10nFactory->get('core')->t('Role'),
+ IAccountManager::PROPERTY_EMAIL => $this->l10nFactory->get('core')->t('Email'),
+ IAccountManager::PROPERTY_PHONE => $this->l10nFactory->get('core')->t('Phone'),
+ IAccountManager::PROPERTY_TWITTER => $this->l10nFactory->get('core')->t('Twitter'),
+ IAccountManager::PROPERTY_WEBSITE => $this->l10nFactory->get('core')->t('Website'),
+ ];
+
+ // Contruct the default config for account properties
+ $propertiesConfig = [];
+ foreach ($propertyDisplayMap as $property => $displayId) {
+ $propertiesConfig[$property] = [
+ 'displayId' => $displayId,
+ 'visibility' => ProfileConfig::DEFAULT_PROPERTY_VISIBILITY[$property] ?: ProfileConfig::DEFAULT_VISIBILITY,
+ ];
+ }
+
+ // Contruct the default config for actions
+ $actionsConfig = [];
+ /** @var ILinkAction $action */
+ foreach ($this->getActions($targetUser, $visitingUser) as $action) {
+ $actionsConfig[$action->getId()] = [
+ 'displayId' => $action->getDisplayId(),
+ 'visibility' => ProfileConfig::DEFAULT_VISIBILITY,
+ ];
+ }
+
+ // Set the default config
+ $config->setConfigArray(array_merge($propertiesConfig, $actionsConfig));
+ $this->configMapper->insert($config);
+ $configArray = $config->getConfigArray();
+ }
+
+ return $configArray;
+ }
+}
diff --git a/lib/private/Profile/TProfileHelper.php b/lib/private/Profile/TProfileHelper.php
new file mode 100644
index 00000000000..0d4b5c6286e
--- /dev/null
+++ b/lib/private/Profile/TProfileHelper.php
@@ -0,0 +1,46 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Profile;
+
+use OCP\Accounts\IAccount;
+use OCP\Accounts\IAccountManager;
+
+trait TProfileHelper {
+
+ /**
+ * Returns whether the profile is enabled for the account
+ *
+ * @since 23.0.0
+ */
+ protected function isProfileEnabled(IAccount $account): ?bool {
+ return filter_var(
+ $account->getProperty(IAccountManager::PROPERTY_PROFILE_ENABLED)->getValue(),
+ FILTER_VALIDATE_BOOLEAN,
+ FILTER_NULL_ON_FAILURE,
+ );
+ }
+}
diff --git a/lib/private/Setup.php b/lib/private/Setup.php
index c24d417f8cf..a7f0f190fa2 100644
--- a/lib/private/Setup.php
+++ b/lib/private/Setup.php
@@ -425,6 +425,9 @@ class Setup {
//and we are done
$config->setSystemValue('installed', true);
+ $bootstrapCoordinator = \OC::$server->query(\OC\AppFramework\Bootstrap\Coordinator::class);
+ $bootstrapCoordinator->runInitialRegistration();
+
// Create a session token for the newly created user
// The token provider requires a working db, so it's not injected on setup
/* @var $userSession User\Session */
diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php
index 0543427f997..c1bd556de60 100644
--- a/lib/private/Template/SCSSCacher.php
+++ b/lib/private/Template/SCSSCacher.php
@@ -32,6 +32,7 @@ namespace OC\Template;
use OC\AppConfig;
use OC\Files\AppData\Factory;
use OC\Memcache\NullCache;
+use OCA\Theming\ThemingDefaults;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
@@ -62,7 +63,7 @@ class SCSSCacher {
/** @var IConfig */
protected $config;
- /** @var \OC_Defaults */
+ /** @var ThemingDefaults */
private $defaults;
/** @var string */
@@ -96,7 +97,7 @@ class SCSSCacher {
* @param Factory $appDataFactory
* @param IURLGenerator $urlGenerator
* @param IConfig $config
- * @param \OC_Defaults $defaults
+ * @param ThemingDefaults $defaults
* @param string $serverRoot
* @param ICacheFactory $cacheFactory
* @param IconsCacher $iconsCacher
@@ -106,7 +107,7 @@ class SCSSCacher {
Factory $appDataFactory,
IURLGenerator $urlGenerator,
IConfig $config,
- \OC_Defaults $defaults,
+ ThemingDefaults $defaults,
$serverRoot,
ICacheFactory $cacheFactory,
IconsCacher $iconsCacher,
@@ -406,7 +407,7 @@ class SCSSCacher {
}
/**
- * @return string SCSS code for variables from OC_Defaults
+ * @return string SCSS code for variables from ThemingDefaults
*/
private function getInjectedVariables(string $cache = ''): string {
if ($this->injectedVariables !== null) {
diff --git a/lib/public/Accounts/IAccountManager.php b/lib/public/Accounts/IAccountManager.php
index 9418e07ec97..ae5f6b1e542 100644
--- a/lib/public/Accounts/IAccountManager.php
+++ b/lib/public/Accounts/IAccountManager.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCP\Accounts;
use OCP\IUser;
@@ -96,6 +97,31 @@ interface IAccountManager {
public const PROPERTY_ADDRESS = 'address';
public const PROPERTY_TWITTER = 'twitter';
+ /**
+ * @since 23.0.0
+ */
+ public const PROPERTY_ORGANISATION = 'organisation';
+
+ /**
+ * @since 23.0.0
+ */
+ public const PROPERTY_ROLE = 'role';
+
+ /**
+ * @since 23.0.0
+ */
+ public const PROPERTY_HEADLINE = 'headline';
+
+ /**
+ * @since 23.0.0
+ */
+ public const PROPERTY_BIOGRAPHY = 'biography';
+
+ /**
+ * @since 23.0.0
+ */
+ public const PROPERTY_PROFILE_ENABLED = 'profile_enabled';
+
public const COLLECTION_EMAIL = 'additional_mail';
public const NOT_VERIFIED = '0';
diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
index d396c619923..f75cdb18cfb 100644
--- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
+++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
namespace OCP\AppFramework\Bootstrap;
use OCP\AppFramework\IAppContainer;
@@ -74,6 +75,7 @@ interface IRegistrationContext {
* @since 20.0.0
*/
public function registerDashboardWidget(string $widgetClass): void;
+
/**
* Register a service
*
@@ -237,4 +239,15 @@ interface IRegistrationContext {
* @since 23.0.0
*/
public function registerCalendarProvider(string $class): void;
+
+ /**
+ * Register an implementation of \OCP\Profile\ILinkAction that
+ * will handle the implementation of a profile action
+ *
+ * @param string $actionClass
+ * @psalm-param class-string<\OCP\Profile\ILinkAction> $actionClass
+ * @return void
+ * @since 23.0.0
+ */
+ public function registerProfileAction(string $actionClass): void;
}
diff --git a/lib/public/Profile/ILinkAction.php b/lib/public/Profile/ILinkAction.php
new file mode 100644
index 00000000000..67e69a73d9c
--- /dev/null
+++ b/lib/public/Profile/ILinkAction.php
@@ -0,0 +1,115 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Profile;
+
+use OCP\IUser;
+
+/**
+ * @since 23.0.0
+ */
+interface ILinkAction {
+
+ /**
+ * Preload the user specific value required by the action
+ *
+ * e.g. the email is loaded for the email action and the userId for the Talk action
+ *
+ * @since 23.0.0
+ */
+ public function preload(IUser $targetUser): void;
+
+ /**
+ * Returns the app ID of the action
+ *
+ * e.g. 'spreed'
+ *
+ * @since 23.0.0
+ */
+ public function getAppId(): string;
+
+ /**
+ * Returns the unique ID of the action
+ *
+ * *For account properties this is the constant defined in lib/public/Accounts/IAccountManager.php*
+ *
+ * e.g. 'email'
+ *
+ * @since 23.0.0
+ */
+ public function getId(): string;
+
+ /**
+ * Returns the translated unique display ID of the action
+ *
+ * Should be something short and descriptive of the action
+ * as this is seen by the end-user when configuring actions
+ *
+ * e.g. 'Email'
+ *
+ * @since 23.0.0
+ */
+ public function getDisplayId(): string;
+
+ /**
+ * Returns the translated title
+ *
+ * e.g. 'Mail user@domain.com'
+ *
+ * Use the L10N service to translate it
+ *
+ * @since 23.0.0
+ */
+ public function getTitle(): string;
+
+ /**
+ * Returns the priority
+ *
+ * *Actions are sorted in ascending order*
+ *
+ * e.g. 60
+ *
+ * @since 23.0.0
+ */
+ public function getPriority(): int;
+
+ /**
+ * Returns the URL link to the 16*16 SVG icon
+ *
+ * @since 23.0.0
+ */
+ public function getIcon(): string;
+
+ /**
+ * Returns the target of the action,
+ * if null is returned the action won't be registered
+ *
+ * e.g. 'mailto:user@domain.com'
+ *
+ * @since 23.0.0
+ */
+ public function getTarget(): ?string;
+}
diff --git a/lib/public/Profile/ParameterDoesNotExistException.php b/lib/public/Profile/ParameterDoesNotExistException.php
new file mode 100644
index 00000000000..543a8edc17a
--- /dev/null
+++ b/lib/public/Profile/ParameterDoesNotExistException.php
@@ -0,0 +1,40 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Profile;
+
+/**
+ * @since 23.0.0
+ */
+class ParameterDoesNotExistException extends \Exception {
+
+ /**
+ * @since 23.0.0
+ */
+ public function __construct($parameter) {
+ parent::__construct("Parameter $parameter does not exist.");
+ }
+}