Обновление клиента

This commit is contained in:
root
2026-03-05 13:40:40 +00:00
parent 34bcd34979
commit b8905de237
4147 changed files with 748711 additions and 7 deletions
@@ -0,0 +1,28 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\AppInfo;
use OCA\Survey_Client\Notifier;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
class Application extends App implements IBootstrap {
public function __construct(array $urlParams = []) {
parent::__construct('survey_client', $urlParams);
}
public function register(IRegistrationContext $context): void {
}
public function boot(IBootContext $context): void {
$notificationManager = $context->getServerContainer()->getNotificationManager();
$notificationManager->registerNotifierService(Notifier::class);
}
}
@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\BackgroundJobs;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\QueuedJob;
use OCP\IGroupManager;
use OCP\Notification\IManager;
class AdminNotification extends QueuedJob {
public function __construct(
ITimeFactory $time,
protected IManager $manager,
protected IGroupManager $groupManager,
) {
parent::__construct($time);
}
protected function run($argument): void {
$notification = $this->manager->createNotification();
$notification->setApp('survey_client')
->setDateTime($this->time->getDateTime())
->setSubject('updated')
->setObject('dummy', '23');
$adminGroup = $this->groupManager->get('admin');
foreach ($adminGroup->getUsers() as $admin) {
$notification->setUser($admin->getUID());
$this->manager->notify($notification);
}
}
}
@@ -0,0 +1,40 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\BackgroundJobs;
use OCA\Survey_Client\Collector;
use OCP\AppFramework\Http;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJob;
use OCP\BackgroundJob\TimedJob;
use Psr\Log\LoggerInterface;
class MonthlyReport extends TimedJob {
protected Collector $collector;
protected LoggerInterface $logger;
public function __construct(ITimeFactory $time,
Collector $collector,
LoggerInterface $logger) {
parent::__construct($time);
$this->collector = $collector;
$this->logger = $logger;
// Run all 28 days
$this->setInterval(28 * 24 * 60 * 60);
// keeping time sensitive to not overload the target server at a single specific time of the day
$this->setTimeSensitivity(IJob::TIME_SENSITIVE);
}
protected function run($argument) {
$result = $this->collector->sendReport();
if ($result->getStatus() !== Http::STATUS_OK) {
$this->logger->info('Error while sending usage statistic');
}
}
}
@@ -0,0 +1,76 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IL10N;
/**
* Class Apps
*
* @package OCA\Survey_Client\Categories
*/
class Apps implements ICategory {
/** @var IDBConnection */
protected $connection;
/** @var \OCP\IL10N */
protected $l;
/**
* @param IDBConnection $connection
* @param IL10N $l
*/
public function __construct(IDBConnection $connection, IL10N $l) {
$this->connection = $connection;
$this->l = $l;
}
/**
* @return string
*/
public function getCategory() {
return 'apps';
}
/**
* @return string
*/
public function getDisplayName() {
return $this->l->t('App list <em>(for each app: name, version, enabled status)</em>');
}
/**
* @return array (string => string|int)
*/
public function getData() {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('appconfig')
->where($query->expr()->in('configkey', $query->createNamedParameter(
['enabled', 'installed_version'],
IQueryBuilder::PARAM_STR_ARRAY
)));
$result = $query->execute();
$data = [];
while ($row = $result->fetch()) {
if ($row['configkey'] === 'enabled' && $row['configvalue'] === 'no') {
$data[$row['appid']] = 'disabled';
}
if ($row['configkey'] === 'installed_version' && !isset($data[$row['appid']])) {
$data[$row['appid']] = $row['configvalue'];
}
}
$result->closeCursor();
return $data;
}
}
@@ -0,0 +1,183 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IL10N;
/**
* Class Database
*
* @package OCA\Survey_Client\Categories
*/
class Database implements ICategory {
/** @var IConfig */
protected $config;
/** @var IDBConnection */
protected $connection;
/** @var IL10N */
protected $l;
public function __construct(IConfig $config, IDBConnection $connection, IL10N $l) {
$this->config = $config;
$this->connection = $connection;
$this->l = $l;
}
/**
* @return string
*/
public function getCategory() {
return 'database';
}
/**
* @return string
*/
public function getDisplayName() {
return $this->l->t('Database environment <em>(type, version, database size)</em>');
}
/**
* @return array (string => string|int)
*/
public function getData() {
return [
'type' => $this->config->getSystemValue('dbtype'),
'version' => $this->databaseVersion(),
'size' => $this->databaseSize(),
];
}
protected function databaseVersion() {
switch ($this->config->getSystemValue('dbtype')) {
case 'sqlite':
case 'sqlite3':
$sql = 'SELECT sqlite_version() AS version';
break;
case 'oci':
$sql = 'SELECT version FROM v$instance';
break;
case 'mysql':
case 'pgsql':
default:
$sql = 'SELECT VERSION() AS version';
break;
}
$result = $this->connection->executeQuery($sql);
$row = $result->fetch();
$result->closeCursor();
if ($row) {
return $this->cleanVersion($row['version']);
}
return 'N/A';
}
/**
* Copy of phpBB's get_database_size()
* @link https://github.com/phpbb/phpbb/blob/release-3.1.6/phpBB/includes/functions_admin.php#L2908-L3043
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* @return int|string
*/
protected function databaseSize() {
$database_size = false;
// This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0
switch ($this->config->getSystemValue('dbtype')) {
case 'mysql':
$db_name = $this->config->getSystemValue('dbname');
$sql = 'SHOW TABLE STATUS FROM `' . $db_name . '`';
$result = $this->connection->executeQuery($sql);
$database_size = 0;
while ($row = $result->fetch()) {
if ((isset($row['Type']) && $row['Type'] !== 'MRG_MyISAM') || (isset($row['Engine']) && ($row['Engine'] === 'MyISAM' || $row['Engine'] === 'InnoDB'))) {
$database_size += $row['Data_length'] + $row['Index_length'];
}
}
$result->closeCursor();
break;
case 'sqlite':
case 'sqlite3':
if (file_exists($this->config->getSystemValue('dbhost'))) {
$database_size = filesize($this->config->getSystemValue('dbhost'));
} else {
/** @psalm-suppress UndefinedInterfaceMethod */
$params = $this->connection->getInner()->getParams();
if (file_exists($params['path'])) {
$database_size = filesize($params['path']);
}
}
break;
case 'pgsql':
$sql = "SELECT proname
FROM pg_proc
WHERE proname = 'pg_database_size'";
$result = $this->connection->executeQuery($sql);
$row = $result->fetch();
$result->closeCursor();
if ($row['proname'] === 'pg_database_size') {
$database = $this->config->getSystemValue('dbname');
if (strpos($database, '.') !== false) {
[$database, ] = explode('.', $database);
}
$sql = "SELECT oid
FROM pg_database
WHERE datname = '$database'";
$result = $this->connection->executeQuery($sql);
$row = $result->fetch();
$result->closeCursor();
$oid = $row['oid'];
$sql = 'SELECT pg_database_size(' . $oid . ') as size';
$result = $this->connection->executeQuery($sql);
$row = $result->fetch();
$result->closeCursor();
$database_size = $row['size'];
}
break;
case 'oci':
$sql = 'SELECT SUM(bytes) as dbsize
FROM user_segments';
$result = $this->connection->executeQuery($sql);
$database_size = ($row = $result->fetch()) ? $row['dbsize'] : false;
$result->closeCursor();
break;
}
return ($database_size !== false) ? $database_size : 'N/A';
}
/**
* Try to strip away additional information
*
* @param string $version E.g. `5.6.27-0ubuntu0.14.04.1`
* @return string `5.6.27`
*/
protected function cleanVersion($version) {
$matches = [];
preg_match('/^(\d+)(\.\d+)(\.\d+)/', $version, $matches);
if (isset($matches[0])) {
return $matches[0];
}
return $version;
}
}
@@ -0,0 +1,63 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
use OCP\IConfig;
use OCP\IL10N;
/**
* Class Encryption
*
* @package OCA\Survey_Client\Categories
*/
class Encryption implements ICategory {
/** @var \OCP\IConfig */
protected $config;
/** @var \OCP\IL10N */
protected $l;
/**
* @param IConfig $config
* @param IL10N $l
*/
public function __construct(IConfig $config, IL10N $l) {
$this->config = $config;
$this->l = $l;
}
/**
* @return string
*/
public function getCategory() {
return 'encryption';
}
/**
* @return string
*/
public function getDisplayName() {
return $this->l->t('Encryption information <em>(is it enabled?, what is the default module)</em>');
}
/**
* @return array (string => string|int)
*/
public function getData() {
$data = [
'enabled' => $this->config->getAppValue('core', 'encryption_enabled', 'no') === 'yes' ? 'yes' : 'no',
'default_module' => $this->config->getAppValue('core', 'default_encryption_module') === 'OC_DEFAULT_MODULE' ? 'yes' : 'no',
];
if ($data['enabled'] === 'yes') {
unset($data['default_module']);
}
return $data;
}
}
@@ -0,0 +1,113 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
use OCP\IDBConnection;
use OCP\IL10N;
/**
* Class FilesSharing
*
* @package OCA\Survey_Client\Categories
*/
class FilesSharing implements ICategory {
/** @var IDBConnection */
protected $connection;
/** @var \OCP\IL10N */
protected $l;
/**
* @param IDBConnection $connection
* @param IL10N $l
*/
public function __construct(IDBConnection $connection, IL10N $l) {
$this->connection = $connection;
$this->l = $l;
}
/**
* @return string
*/
public function getCategory() {
return 'files_sharing';
}
/**
* @return string
*/
public function getDisplayName() {
return $this->l->t('Number of shares <em>(per type and permission setting)</em>');
}
/**
* @return array (string => string|int)
*/
public function getData() {
$query = $this->connection->getQueryBuilder();
$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
->addSelect(['permissions', 'share_type'])
->from('share')
->addGroupBy('permissions')
->addGroupBy('share_type');
$result = $query->execute();
$data = [
'num_shares' => $this->countEntries('share'),
'num_shares_user' => $this->countShares(0),
'num_shares_groups' => $this->countShares(1),
'num_shares_link' => $this->countShares(3),
'num_shares_link_no_password' => $this->countShares(3, true),
'num_fed_shares_sent' => $this->countShares(6),
'num_fed_shares_received' => $this->countEntries('share_external'),
];
while ($row = $result->fetch()) {
$data['permissions_' . $row['share_type'] . '_' . $row['permissions']] = $row['num_entries'];
}
$result->closeCursor();
return $data;
}
/**
* @param string $tableName
* @return int
*/
protected function countEntries($tableName) {
$query = $this->connection->getQueryBuilder();
$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
->from($tableName);
$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();
return (int)$row['num_entries'];
}
/**
* @param int $type
* @param bool $noShareWith
* @return int
*/
protected function countShares($type, $noShareWith = false) {
$query = $this->connection->getQueryBuilder();
$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
->from('share')
->where($query->expr()->eq('share_type', $query->createNamedParameter($type)));
if ($noShareWith) {
$query->andWhere($query->expr()->isNull('share_with'));
}
$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();
return (int)$row['num_entries'];
}
}
@@ -0,0 +1,32 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
/**
* Interface ICategory
*
* TODO Move to core public API?
*
* @package OCA\Survey_Client\Categories
*/
interface ICategory {
/**
* @return string
*/
public function getCategory();
/**
* @return string
*/
public function getDisplayName();
/**
* @return array (string => string|int)
*/
public function getData();
}
+75
View File
@@ -0,0 +1,75 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
use bantu\IniGetWrapper\IniGetWrapper;
use OCP\IL10N;
/**
* Class php
*
* @package OCA\Survey_Client\Categories
*/
class Php implements ICategory {
/** @var IniGetWrapper */
protected $phpIni;
/** @var \OCP\IL10N */
protected $l;
/**
* @param IniGetWrapper $phpIni
* @param IL10N $l
*/
public function __construct(IniGetWrapper $phpIni, IL10N $l) {
$this->phpIni = $phpIni;
$this->l = $l;
}
/**
* @return string
*/
public function getCategory() {
return 'php';
}
/**
* @return string
*/
public function getDisplayName() {
return $this->l->t('PHP environment <em>(version, memory limit, max. execution time, max. file size)</em>');
}
/**
* @return array (string => string|int)
*/
public function getData() {
return [
'version' => $this->cleanVersion(PHP_VERSION),
'memory_limit' => $this->phpIni->getBytes('memory_limit'),
'max_execution_time' => $this->phpIni->getNumeric('max_execution_time'),
'upload_max_filesize' => $this->phpIni->getBytes('upload_max_filesize'),
];
}
/**
* Try to strip away additional information
*
* @param string $version E.g. `5.5.30-1+deb.sury.org~trusty+1`
* @return string `5.5.30`
*/
protected function cleanVersion($version) {
$matches = [];
preg_match('/^(\d+)(\.\d+)(\.\d+)/', $version, $matches);
if (isset($matches[0])) {
return $matches[0];
}
return $version;
}
}
@@ -0,0 +1,73 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
use OCP\IConfig;
use OCP\IL10N;
/**
* Class Server
*
* @package OCA\Survey_Client\Categories
*/
class Server implements ICategory {
/** @var \OCP\IConfig */
protected $config;
/** @var \OCP\IL10N */
protected $l;
/**
* @param IConfig $config
* @param IL10N $l
*/
public function __construct(IConfig $config, IL10N $l) {
$this->config = $config;
$this->l = $l;
}
/**
* @return string
*/
public function getCategory() {
return 'server';
}
/**
* @return string
*/
public function getDisplayName() {
return $this->l->t('Server instance details <em>(version, memcache used, status of locking/previews/avatars)</em>');
}
/**
* @return array (string => string|int)
*/
public function getData() {
return [
'version' => $this->config->getSystemValue('version'),
'code' => $this->codeLocation(),
'enable_avatars' => $this->config->getSystemValue('enable_avatars', true) ? 'yes' : 'no',
'enable_previews' => $this->config->getSystemValue('enable_previews', true) ? 'yes' : 'no',
'memcache.local' => $this->config->getSystemValue('memcache.local', 'none'),
'memcache.distributed' => $this->config->getSystemValue('memcache.distributed', 'none'),
'asset-pipeline.enabled' => $this->config->getSystemValue('asset-pipeline.enabled') ? 'yes' : 'no',
'filelocking.enabled' => $this->config->getSystemValue('filelocking.enabled', true) ? 'yes' : 'no',
'memcache.locking' => $this->config->getSystemValue('memcache.locking', 'none'),
'debug' => $this->config->getSystemValue('debug', false) ? 'yes' : 'no',
'cron' => $this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax'),
];
}
protected function codeLocation() {
if (file_exists(\OC::$SERVERROOT . '/.git') && is_dir(\OC::$SERVERROOT . '/.git')) {
return 'git';
}
return 'other';
}
}
+126
View File
@@ -0,0 +1,126 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Categories;
use OCP\IDBConnection;
use OCP\IL10N;
/**
* Class Stats
*
* @package OCA\Survey_Client\Categories
*/
class Stats implements ICategory {
/** @var IDBConnection */
protected $connection;
/** @var \OCP\IL10N */
protected $l;
/**
* @param IDBConnection $connection
* @param IL10N $l
*/
public function __construct(IDBConnection $connection, IL10N $l) {
$this->connection = $connection;
$this->l = $l;
}
/**
* @return string
*/
public function getCategory() {
return 'stats';
}
/**
* @return string
*/
public function getDisplayName() {
return $this->l->t('Statistic <em>(number of files, users, storages per type, comments and tags)</em>');
}
/**
* @return array (string => string|int)
*/
public function getData() {
return [
'num_files' => $this->countEntries('filecache'),
'num_users' => $this->countUserEntries(),
'num_storages' => $this->countEntries('storages'),
'num_storages_local' => $this->countStorages('local'),
'num_storages_home' => $this->countStorages('home'),
'num_storages_other' => $this->countStorages('other'),
'num_comments' => $this->countEntries('comments'),
'num_comment_markers' => $this->countEntries('comments_read_markers', 'user_id'),
'num_systemtags' => $this->countEntries('systemtag'),
'num_systemtags_mappings' => $this->countEntries('systemtag_object_mapping'),
];
}
/**
* @return int
*/
protected function countUserEntries() {
$query = $this->connection->getQueryBuilder();
$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
->from('preferences')
->where($query->expr()->eq('configkey', $query->createNamedParameter('lastLogin')));
$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();
return (int)$row['num_entries'];
}
/**
* @param string $type
* @return int
*/
protected function countStorages($type) {
$query = $this->connection->getQueryBuilder();
$query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries')
->from('storages');
if ($type === 'home') {
$query->where($query->expr()->like('id', $query->createNamedParameter('home::%')));
} elseif ($type === 'local') {
$query->where($query->expr()->like('id', $query->createNamedParameter('local::%')));
} elseif ($type === 'other') {
$query->where($query->expr()->notLike('id', $query->createNamedParameter('home::%')));
$query->andWhere($query->expr()->notLike('id', $query->createNamedParameter('local::%')));
}
$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();
return (int)$row['num_entries'];
}
/**
* @param string $tableName
* @param string $column
* @return int
*/
protected function countEntries($tableName, $column = '*') {
$query = $this->connection->getQueryBuilder();
if ($column !== '*') {
$column = 'DISTINCT(' . $query->getColumnName($column) . ')';
}
$query->selectAlias($query->createFunction('COUNT(' . $column . ')'), 'num_entries')
->from($tableName);
$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();
return (int)$row['num_entries'];
}
}
+155
View File
@@ -0,0 +1,155 @@
<?php
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client;
use bantu\IniGetWrapper\IniGetWrapper;
use OCA\Survey_Client\Categories\Apps;
use OCA\Survey_Client\Categories\Database;
use OCA\Survey_Client\Categories\Encryption;
use OCA\Survey_Client\Categories\FilesSharing;
use OCA\Survey_Client\Categories\ICategory;
use OCA\Survey_Client\Categories\Php;
use OCA\Survey_Client\Categories\Server;
use OCA\Survey_Client\Categories\Stats;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IL10N;
class Collector {
public const SURVEY_SERVER_URL = 'https://surveyserver.nextcloud.com/';
/** @var ICategory[] */
protected array $categories;
public function __construct(
protected IClientService $clientService,
protected IConfig $config,
protected IAppConfig $appConfig,
protected IDBConnection $connection,
protected IniGetWrapper $phpIni,
protected IL10N $l,
protected ITimeFactory $timeFactory,
) {
}
protected function registerCategories(): void {
$this->categories[] = new Server(
$this->config,
$this->l
);
$this->categories[] = new Php(
$this->phpIni,
$this->l
);
$this->categories[] = new Database(
$this->config,
$this->connection,
$this->l
);
$this->categories[] = new Apps(
$this->connection,
$this->l
);
$this->categories[] = new Stats(
$this->connection,
$this->l
);
$this->categories[] = new FilesSharing(
$this->connection,
$this->l
);
$this->categories[] = new Encryption(
$this->config,
$this->l
);
}
/**
* @return array<string, array{displayName: string, enabled: bool}>
*/
public function getCategories(): array {
$this->registerCategories();
$categories = [];
foreach ($this->categories as $category) {
$categories[$category->getCategory()] = [
'displayName' => $category->getDisplayName(),
'enabled' => $this->appConfig->getAppValueBool($category->getCategory(), true),
];
}
return $categories;
}
/**
* @return array{id: string, items: array}
*/
public function getReport() {
$this->registerCategories();
$tuples = [];
foreach ($this->categories as $category) {
if ($this->appConfig->getAppValueBool($category->getCategory(), true)) {
foreach ($category->getData() as $key => $value) {
$tuples[] = [
$category->getCategory(),
$key,
$value
];
}
}
}
return [
'id' => $this->config->getSystemValue('instanceid'),
'items' => $tuples,
];
}
/**
* @return DataResponse
*/
public function sendReport(): DataResponse {
$report = $this->getReport();
$client = $this->clientService->newClient();
try {
$response = $client->post(self::SURVEY_SERVER_URL . 'ocs/v2.php/apps/survey_server/api/v1/survey', [
'timeout' => 5,
'query' => [
'data' => json_encode($report),
],
]);
} catch (\Exception $e) {
return new DataResponse(
$report,
Http::STATUS_INTERNAL_SERVER_ERROR
);
}
if ($response->getStatusCode() === Http::STATUS_OK) {
$this->appConfig->setAppValueInt('last_sent', $this->timeFactory->getTime());
$this->appConfig->setAppValueString('last_report', json_encode($report), true);
return new DataResponse(
$report
);
}
return new DataResponse(
$report,
Http::STATUS_INTERNAL_SERVER_ERROR
);
}
}
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client\Controller;
use OCA\Survey_Client\BackgroundJobs\MonthlyReport;
use OCA\Survey_Client\Collector;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\BackgroundJob\IJobList;
use OCP\IRequest;
use OCP\Notification\IManager;
class EndpointController extends OCSController {
/** @var Collector */
protected $collector;
/** @var IJobList */
protected $jobList;
/** @var IManager */
protected $manager;
/**
* @param string $appName
* @param IRequest $request
* @param Collector $collector
* @param IJobList $jobList
* @param IManager $manager
*/
public function __construct(string $appName,
IRequest $request,
Collector $collector,
IJobList $jobList,
IManager $manager) {
parent::__construct($appName, $request);
$this->collector = $collector;
$this->jobList = $jobList;
$this->manager = $manager;
}
/**
* @return DataResponse
*/
public function enableMonthly(): DataResponse {
$this->jobList->add(MonthlyReport::class);
$notification = $this->manager->createNotification();
$notification->setApp('survey_client');
$this->manager->markProcessed($notification);
return new DataResponse();
}
/**
* @return DataResponse
*/
public function disableMonthly(): DataResponse {
$this->jobList->remove(MonthlyReport::class);
$notification = $this->manager->createNotification();
$notification->setApp('survey_client');
$this->manager->markProcessed($notification);
return new DataResponse();
}
/**
* @return DataResponse
*/
public function sendReport(): DataResponse {
return $this->collector->sendReport();
}
}
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Survey_Client\Migration;
use OCA\Survey_Client\BackgroundJobs\AdminNotification;
use OCA\Survey_Client\BackgroundJobs\MonthlyReport;
use OCP\BackgroundJob\IJobList;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
class SendAdminNotification implements IRepairStep {
/** @var IJobList */
private $jobList;
public function __construct(IJobList $jobList) {
$this->jobList = $jobList;
}
public function getName(): string {
return 'Send an admin notification if monthly report is disabled';
}
public function run(IOutput $output): void {
if (!$this->jobList->has(MonthlyReport::class, null)) {
$this->jobList->add(AdminNotification::class);
}
}
}
+82
View File
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Survey_Client;
use OCP\IURLGenerator;
use OCP\L10N\IFactory;
use OCP\Notification\INotification;
use OCP\Notification\INotifier;
use OCP\Notification\UnknownNotificationException;
class Notifier implements INotifier {
public function __construct(
protected IFactory $l10nFactory,
protected IURLGenerator $url,
) {
}
/**
* Identifier of the notifier, only use [a-z0-9_]
*
* @return string
* @since 17.0.0
*/
public function getID(): string {
return 'survey_client';
}
/**
* Human-readable name describing the notifier
*
* @return string
* @since 17.0.0
*/
public function getName(): string {
return $this->l10nFactory->get('survey_client')->t('Usage survey');
}
/**
* @param INotification $notification
* @param string $languageCode The code of the language that should be used to prepare the notification
* @return INotification
* @throws UnknownNotificationException When the notification was not prepared by a notifier
*/
public function prepare(INotification $notification, string $languageCode): INotification {
if ($notification->getApp() !== 'survey_client') {
// Not my app => throw
throw new UnknownNotificationException();
}
// Read the language from the notification
$l = $this->l10nFactory->get('survey_client', $languageCode);
$notification->setParsedSubject($l->t('Help improve Nextcloud'))
->setParsedMessage($l->t('Do you want to help us to improve Nextcloud by providing some anonymized data about your setup and usage? You can disable it at any time in the admin settings again.'))
->setLink($this->url->linkToRouteAbsolute('settings.AdminSettings.index', ['section' => 'survey_client']))
->setIcon($this->url->getAbsoluteURL($this->url->imagePath('survey_client', 'app-dark.svg')));
$enableAction = $notification->createAction();
$enableAction->setLabel('enable')
->setParsedLabel($l->t('Send usage'))
->setLink($this->url->linkToOCSRouteAbsolute('survey_client.Endpoint.enableMonthly'), 'POST')
->setPrimary(true);
$notification->addParsedAction($enableAction);
$disableAction = $notification->createAction();
$disableAction->setLabel('disable')
->setParsedLabel($l->t('Not now'))
->setLink($this->url->linkToOCSRouteAbsolute('survey_client.Endpoint.disableMonthly'), 'DELETE')
->setPrimary(false);
$notification->addParsedAction($disableAction);
return $notification;
}
}
@@ -0,0 +1,60 @@
<?php
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Survey_Client\Settings;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Settings\IIconSection;
class AdminSection implements IIconSection {
/** @var IL10N */
private $l;
/** @var IURLGenerator */
private $url;
public function __construct(IL10N $l, IURLGenerator $url) {
$this->l = $l;
$this->url = $url;
}
/**
* returns the ID of the section. It is supposed to be a lower case string
*
* @returns string
*/
public function getID() {
return 'survey_client';
}
/**
* returns the translated name as it should be displayed, e.g. 'LDAP / AD
* integration'. Use the L10N service to translate it.
*
* @return string
*/
public function getName() {
return $this->l->t('Usage survey');
}
/**
* @return int whether the form should be rather on the top or bottom of
* the settings navigation. The sections are arranged in ascending order of
* the priority values. It is required to return a value between 0 and 99.
*/
public function getPriority() {
return 80;
}
/**
* {@inheritdoc}
*/
public function getIcon() {
return $this->url->imagePath('survey_client', 'app-dark.svg');
}
}
@@ -0,0 +1,72 @@
<?php
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Survey_Client\Settings;
use OCA\Survey_Client\BackgroundJobs\MonthlyReport;
use OCA\Survey_Client\Collector;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IAppConfig;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IDateTimeFormatter;
use OCP\IL10N;
use OCP\Settings\ISettings;
class AdminSettings implements ISettings {
public function __construct(
protected Collector $collector,
protected IConfig $config,
protected IAppConfig $appConfig,
protected IL10N $l,
protected IDateTimeFormatter $dateTimeFormatter,
protected IJobList $jobList,
) {
}
/**
* @return TemplateResponse
*/
public function getForm(): TemplateResponse {
$lastSentReportTime = $this->appConfig->getAppValueInt('last_sent');
if ($lastSentReportTime === 0) {
$lastSentReportDate = $this->l->t('Never');
} else {
$lastSentReportDate = $this->dateTimeFormatter->formatDate($lastSentReportTime);
}
$lastReport = $this->appConfig->getAppValueString('last_report', lazy: true);
if ($lastReport !== '') {
$lastReport = json_encode(json_decode($lastReport, true), JSON_PRETTY_PRINT);
}
$parameters = [
'is_enabled' => $this->jobList->has(MonthlyReport::class, null),
'last_sent' => $lastSentReportDate,
'last_report' => $lastReport,
'categories' => $this->collector->getCategories()
];
return new TemplateResponse('survey_client', 'admin', $parameters);
}
/**
* @return string the section ID, e.g. 'sharing'
*/
public function getSection(): string {
return 'survey_client';
}
/**
* @return int whether the form should be rather on the top or bottom of
* the admin section. The forms are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
*/
public function getPriority(): int {
return 50;
}
}