From 0b49dc10486f1444de5892f4bf902eb8c860117a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Sun, 23 Apr 2017 14:24:20 +0200 Subject: Allow apps to define custom bug report details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Detail.php | 55 ++++++++ lib/DetailManager.php | 114 +++++++++++++++++ lib/IDetail.php | 51 ++++++++ lib/ISection.php | 53 ++++++++ lib/Section.php | 77 +++++++++++ lib/Sections/ClientSection.php | 70 ++++++++++ lib/Sections/LogSection.php | 43 +++++++ lib/Sections/ServerSection.php | 244 +++++++++++++++++++++++++++++++++++ lib/Settings/Admin.php | 281 +++++++++++------------------------------ lib/Settings/Section.php | 6 +- 10 files changed, 787 insertions(+), 207 deletions(-) create mode 100644 lib/Detail.php create mode 100644 lib/DetailManager.php create mode 100644 lib/IDetail.php create mode 100644 lib/ISection.php create mode 100644 lib/Section.php create mode 100644 lib/Sections/ClientSection.php create mode 100644 lib/Sections/LogSection.php create mode 100644 lib/Sections/ServerSection.php (limited to 'lib') diff --git a/lib/Detail.php b/lib/Detail.php new file mode 100644 index 0000000..23b2555 --- /dev/null +++ b/lib/Detail.php @@ -0,0 +1,55 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\IssueTemplate; + +class Detail implements IDetail { + + private $section; + private $title; + private $information; + private $type; + + public function __construct($section, $title, $information, $type) { + $this->section = $section; + $this->title = $title; + $this->information = $information; + $this->type = $type; + } + + public function getTitle() { + return $this->title; + } + + public function getType() { + return $this->type; + } + + public function getInformation() { + return $this->information; + } + + public function getSection() { + return $this->section; + } +} \ No newline at end of file diff --git a/lib/DetailManager.php b/lib/DetailManager.php new file mode 100644 index 0000000..85e301c --- /dev/null +++ b/lib/DetailManager.php @@ -0,0 +1,114 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\IssueTemplate; + +class DetailManager { + + private $sections = []; + + public function __construct($AppName) { + \OC::$server->getLogger()->error($AppName); + } + + public function createSection($identifier, $title, $order=0) { + $section = new Section($identifier, $title, $order); + $this->addSection($section); + } + + public function addSection(ISection $section) { + if(array_key_exists($section->getIdentifier(), $this->sections)) { + /** @var ISection $existing */ + $existing = $this->sections[$section->getIdentifier()]; + foreach ($section->getDetails() as $detail) { + $existing->addDetail($detail); + } + return; + } + $this->sections[$section->getIdentifier()] = $section; + } + + public function removeSection($section) { + unset($this->sections[$section]); + } + + /** + * @param string $sectionIdentifier + * @param string $title + * @param string $information + * @param int $type + */ + public function createDetail($sectionIdentifier, $title, $information, $type = IDetail::TYPE_MULTI_LINE_PREFORMAT) { + $detail = new Detail($sectionIdentifier, $title, $information, $type); + /** @var ISection $sectionObject */ + $sectionObject = $this->sections[$sectionIdentifier]; + $sectionObject->addDetail($detail); + } + + /** + * @return ISection[] + */ + public function getSections() { + return $this->sections; + } + + public function getRenderedDetails() { + $result = ''; + /** @var ISection $section */ + foreach ($this->sections as $section) { + $result .= $this->renderSectionHeader($section); + /** @var IDetail $detail */ + foreach ($section->getDetails() as $detail) { + $result .= $this->renderDetail($detail); + } + } + return $result; + } + + private function renderSectionHeader(ISection $section) { + return '## ' . $section->getTitle() . "\n\n"; + } + + private function renderDetail(IDetail $detail) { + switch ($detail->getType()) { + case IDetail::TYPE_SINGLE_LINE: + return '**' . $detail->getTitle() . ':** ' . $detail->getInformation() . "\n\n"; + break; + case IDetail::TYPE_MULTI_LINE: + return '**' . $detail->getTitle() . ":** \n\n" . $detail->getInformation() . "\n\n"; + break; + case IDetail::TYPE_MULTI_LINE_PREFORMAT: + return '**' . $detail->getTitle() . ":** \n\n``` \n" . $detail->getInformation() . "\n```\n\n"; + break; + case IDetail::TYPE_COLLAPSIBLE: + return '
' . $detail->getTitle() . "\n\n" . $detail->getInformation() . "\n
\n\n"; + break; + case IDetail::TYPE_COLLAPSIBLE_PREFORMAT: + return '
' . $detail->getTitle() . "\n\n```\n" . $detail->getInformation() . "\n```\n
\n\n"; + break; + default: + return '**' . $detail->getTitle() . ':** ' . $detail->getInformation() . "\n\n"; + break; + } + } +} \ No newline at end of file diff --git a/lib/IDetail.php b/lib/IDetail.php new file mode 100644 index 0000000..d250c33 --- /dev/null +++ b/lib/IDetail.php @@ -0,0 +1,51 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ +namespace OCA\IssueTemplate; + +interface IDetail { + + const TYPE_SINGLE_LINE = 0; + const TYPE_MULTI_LINE = 1; + const TYPE_MULTI_LINE_PREFORMAT = 2; + const TYPE_COLLAPSIBLE = 3; + const TYPE_COLLAPSIBLE_PREFORMAT = 4; + + /** + * @return string + */ + public function getTitle(); + /** + * @return string + */ + public function getType(); + + /** + * @return string + */ + public function getInformation(); + + /** + * @return int + */ + public function getSection(); +} \ No newline at end of file diff --git a/lib/ISection.php b/lib/ISection.php new file mode 100644 index 0000000..9c5a247 --- /dev/null +++ b/lib/ISection.php @@ -0,0 +1,53 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\IssueTemplate; + +/** + * Interface ISection + * + * @package OCA\IssueTemplate + */ +interface ISection { + + /** + * @return string + */ + public function getIdentifier(); + + /** + * @return string + */ + public function getTitle(); + + /** + * @param IDetail $details + * @return void + */ + public function addDetail(IDetail $details); + + /** + * @return IDetail[] + */ + public function getDetails(); +} \ No newline at end of file diff --git a/lib/Section.php b/lib/Section.php new file mode 100644 index 0000000..10c0201 --- /dev/null +++ b/lib/Section.php @@ -0,0 +1,77 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\IssueTemplate; + +class Section implements ISection { + + /** @var string */ + private $identifier; + /** @var string */ + private $title; + /** @var IDetail[] */ + private $details = []; + + public function __construct($identifier, $title, $order = 0) { + $this->identifier = $identifier; + $this->title = $title; + } + + /** + * @inheritdoc + */ + public function getIdentifier() { + return $this->identifier; + } + + /** + * @inheritdoc + */ + public function getTitle() { + return $this->title; + } + + /** + * @inheritdoc + */ + public function addDetail(IDetail $details) { + $this->details[] = $details; + } + + /** + * @inheritdoc + */ + public function getDetails() { + return $this->details; + } + + /** + * @inheritdoc + */ + public function createDetail($title, $information, $type = IDetail::TYPE_SINGLE_LINE) { + $detail = new Detail($this->getIdentifier(), $title, $information, $type); + $this->addDetail($detail); + return $detail; + } + +} \ No newline at end of file diff --git a/lib/Sections/ClientSection.php b/lib/Sections/ClientSection.php new file mode 100644 index 0000000..7463096 --- /dev/null +++ b/lib/Sections/ClientSection.php @@ -0,0 +1,70 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\IssueTemplate\Sections; + +use OCP\IRequest; +use OCA\IssueTemplate\Section; + +class ClientSection extends Section { + + public function __construct(IRequest $request) { + parent::__construct('client-detail', 'Client configuration'); + + $app = $request->getParam('app'); + + if($app !== 'ios' && $app !== 'android') { + $this->createDetail('Browser', $this->getBrowser()); + $this->createDetail('Operating system', ''); + } + + if($app === 'android') { + $this->createDetail('Android version', ''); + $this->createDetail('Device model', ''); + $this->createDetail('Stock or customized system:', ''); + $this->createDetail('Nextcloud app version:', ''); + $this->createDetail('Nextcloud server version:', ''); + } + } + + private function getBrowser() { + $browser = @get_browser(null, true); + $browserString = ''; + if($browser) { + if(array_key_exists('browser', $browser)) { + $browserString .= $browser['browser'] . ' '; + } + if(array_key_exists('version', $browser)) { + $browserString .= $browser['version'] . ' '; + } + if(array_key_exists('plattform', $browser)) { + $browserString .= $browser['plattform'] . ' '; + } + } + if(empty($browserString)) { + return $_SERVER['HTTP_USER_AGENT']; + } + return $browserString; + } + +} \ No newline at end of file diff --git a/lib/Sections/LogSection.php b/lib/Sections/LogSection.php new file mode 100644 index 0000000..53ed2a2 --- /dev/null +++ b/lib/Sections/LogSection.php @@ -0,0 +1,43 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\IssueTemplate\Sections; + + +use OCA\IssueTemplate\IDetail; +use OCA\IssueTemplate\Section; + +class LogSection extends Section { + + public function __construct() { + parent::__construct('log-detail', 'Logs'); + $this->createDetail('Browser log', 'Insert your webserver log here ', IDetail::TYPE_COLLAPSIBLE_PREFORMAT); + $this->createDetail('Nextcloud log', 'Insert your Nextcloud log here', IDetail::TYPE_COLLAPSIBLE_PREFORMAT); + $this->createDetail('Browser log', 'Insert your browser log here, this could for example include: + + a) The javascript console log + b) The network log + c) ...', IDetail::TYPE_COLLAPSIBLE); + } + +} \ No newline at end of file diff --git a/lib/Sections/ServerSection.php b/lib/Sections/ServerSection.php new file mode 100644 index 0000000..573a6ba --- /dev/null +++ b/lib/Sections/ServerSection.php @@ -0,0 +1,244 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\IssueTemplate\Sections; + +use OC\SystemConfig; +use OCA\IssueTemplate\IDetail; +use OCP\IConfig; +use OC\IntegrityCheck\Checker; +use OCP\App\IAppManager; +use OCP\IDBConnection; +use OCA\IssueTemplate\Section; +use OCA\Files_External\Service\BackendService; + +class ServerSection extends Section { + + /** @var IConfig */ + private $config; + /** @var Checker */ + private $checker; + /** @var IAppManager */ + private $appManager; + /** @var SystemConfig */ + private $systemConfig; + /** @var IDBConnection */ + private $connection; + + public function __construct(IConfig $config, + Checker $checker, + IAppManager $appManager, + IDBConnection $connection) { + parent::__construct('server-detail', 'Server configuration detail'); + $this->config = $config; + $this->checker = $checker; + $this->appManager = $appManager; + $this->systemConfig = \OC::$server->query('SystemConfig'); + $this->connection = $connection; + $this->createDetail('Operating system', $this->getOsVersion()); + $this->createDetail('Webserver', $this->getWebserver()); + $this->createDetail('Database', $this->getDatabaseInfo()); + $this->createDetail('PHP version', $this->getPhpVersion()); + $this->createDetail('Nextcloud version', $this->getNextcloudVersion()); + $this->createDetail('Updated from an older Nextcloud/ownCloud or fresh install', ''); + $this->createDetail('Where did you install Nextcloud from', $this->getInstallMethod()); + $this->createDetail('Signing status', $this->getIntegrityResults(), IDetail::TYPE_COLLAPSIBLE); + $this->createDetail('List of activated apps', $this->renderAppList(), IDetail::TYPE_COLLAPSIBLE_PREFORMAT); + + $this->createDetail('Configuration (config/config.php)', print_r(json_encode($this->getConfig(), JSON_PRETTY_PRINT), true), IDetail::TYPE_COLLAPSIBLE_PREFORMAT); + + $this->createDetail('Are you using external storage, if yes which one', 'local/smb/sftp/...'); + $this->createDetail('Are you using encryption', $this->getEncryptionInfo()); + $this->createDetail('Are you using an external user-backend, if yes which one', 'LDAP/ActiveDirectory/Webdav/...'); + + $this->createDetail('LDAP configuration (delete this part if not used)', 'With access to your command line run e.g.: +sudo -u www-data php occ ldap:show-config +from within your Nextcloud installation folder + +Without access to your command line download the data/owncloud.db to your local +computer or access your SQL server remotely and run the select query: +SELECT * FROM `oc_appconfig` WHERE `appid` = \'user_ldap\'; + + +Eventually replace sensitive data as the name/IP-address of your LDAP server or groups.', IDetail::TYPE_COLLAPSIBLE_PREFORMAT); + } + private function getWebserver() { + return $_SERVER['SERVER_SOFTWARE'] . ' (' . PHP_SAPI . ')'; + } + + private function getNextcloudVersion() { + return \OC_Util::getHumanVersion() . ' - ' . $this->config->getSystemValue('version'); + } + private function getOsVersion() { + return PHP_OS; + } + private function getPhpVersion() { + return PHP_VERSION . "\nModules loaded: " . implode(', ', get_loaded_extensions()); + } + + protected function getDatabaseInfo() { + return $this->config->getSystemValue('dbtype') . ' ' . $this->getDatabaseVersion(); + } + + /** + * original source from nextcloud/survey_client + * @link https://github.com/nextcloud/survey_client/blob/master/lib/Categories/Database.php#L80-L107 + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @author Joas Schilling + * @license AGPL-3.0 + */ + private function getDatabaseVersion() { + 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'; + } + + /** + * Try to strip away additional information + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @author Joas Schilling + * @license AGPL-3.0 + * + * @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; + } + + private function getIntegrityResults() { + if(!$this->checker->isCodeCheckEnforced()) { + return 'Integrity checker has been disabled. Integrity cannot be verified.'; + } + return $this->checker->getResults(); + } + + private function getInstallMethod() { + $base = \OC::$SERVERROOT; + if(file_exists($base . '/.git')) { + return 'git'; + } + return 'unknown'; + } + + private function renderAppList() { + $apps = $this->getAppList(); + $result = "Enabled:\n"; + foreach ($apps['enabled'] as $name => $version) { + $result .= ' - ' . $name . ': ' . $version . "\n"; + } + + $result .= "Disabled:\n"; + foreach ($apps['disabled'] as $name => $version) { + $result .= ' - ' . $name . "\n"; + } + return $result; + } + + /** + * @return string[][] + */ + private function getAppList() { + $apps = \OC_App::getAllApps(); + $enabledApps = $disabledApps = []; + $versions = \OC_App::getAppVersions(); + + //sort enabled apps above disabled apps + foreach ($apps as $app) { + if ($this->appManager->isInstalled($app)) { + $enabledApps[] = $app; + } else { + $disabledApps[] = $app; + } + } + $apps = ['enabled' => [], 'disabled' => []]; + sort($enabledApps); + foreach ($enabledApps as $app) { + $apps['enabled'][$app] = isset($versions[$app]) ? $versions[$app] : true; + } + sort($disabledApps); + foreach ($disabledApps as $app) { + $apps['disabled'][$app] = null; + } + return $apps; + } + + protected function getEncryptionInfo() { + return $this->config->getAppValue('core', 'encryption_enabled', 'no'); + } + + protected function getExternalStorageInfo() { + if(\OC::$server->getAppManager()->isEnabledForUser('files_external')) { + // $mounts = $this->globalService->getStorageForAllUsers(); + // Global storage services + // https://github.com/nextcloud/server/blob/8c7d7d7746e76b77ad86cee3aae5dbd4d1bcd896/apps/files_external/lib/Command/ListCommand.php + /** @var BackendService $backendService */ + $backendService = \OC::$server->query(BackendService::class); + $result = array(); + foreach ($backendService->getAvailableBackends() as $backend) { + $result[] = $backend->getStorageClass(); + } + return $result; + } + return 'files_external is disabled'; + } + + private function getConfig() { + + $keys = $this->systemConfig->getKeys(); + $configs = []; + foreach ($keys as $key) { + $value = $this->systemConfig->getFilteredValue($key, serialize(null)); + if ($value !== 'N;') { + $configs[$key] = $value; + } + } + return $configs; + } + +} \ No newline at end of file diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 012e3b9..7a8ce12 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -23,71 +23,87 @@ namespace OCA\IssueTemplate\Settings; +use OCA\IssueTemplate\DetailManager; +use OCA\IssueTemplate\Sections\ClientSection; +use OCA\IssueTemplate\Sections\LogSection; +use OCA\IssueTemplate\Sections\ServerSection; use OCP\AppFramework\Http\TemplateResponse; use OCP\IConfig; use OCP\IL10N; -use OCP\IURLGenerator; +use OCP\IRequest; use OCP\Settings\ISettings; -use OC\IntegrityCheck\Checker; use OCP\App\IAppManager; -use OC\SystemConfig; -use OCP\IDBConnection; - +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\GenericEvent; class Admin implements ISettings { /** @var IConfig */ private $config; /** @var IL10N */ - private $l; - /** @var IURLGenerator */ - private $urlGenerator; - /** @var Checker */ - private $checker; + private $l10n; /** @var IAppManager */ private $appManager; - /** @var SystemConfig */ - private $systemConfig; - /** @var IDBConnection */ - private $connection; + /** @var DetailManager */ + private $detailManager; + /** @var ServerSection */ + private $serverSection; + /** @var ClientSection */ + private $clientSection; + /** @var LogSection */ + private $logSection; + /** @var EventDispatcher */ + private $eventDispatcher; + /** @var IRequest */ + private $request; public function __construct( - IConfig $config, - IL10N $l, - IURLGenerator $urlGenerator, - Checker $checker, - IAppManager $appManager, - IDBConnection $connection -) { + IConfig $config, + IL10N $l10n, + IAppManager $appManager, + EventDispatcher $eventDispatcher, + DetailManager $detailManager, + ServerSection $serverSection, + ClientSection $clientSection, + LogSection $logSection, + IRequest $request + ) { $this->config = $config; - $this->l = $l; - $this->urlGenerator = $urlGenerator; - $this->checker = $checker; + $this->l10n = $l10n; $this->appManager = $appManager; - $this->systemConfig = \OC::$server->query("SystemConfig"); - $this->connection = $connection; + $this->detailManager = $detailManager; + $this->serverSection = $serverSection; + $this->clientSection = $clientSection; + $this->logSection = $logSection; + $this->eventDispatcher = $eventDispatcher; + $this->request = $request; + + // Register core details that are used in every report + $this->detailManager->addSection($this->serverSection); + $this->detailManager->addSection($this->clientSection); + $this->detailManager->addSection($this->logSection); + + } + + public function queryAppDetails($app) { + $event = new GenericEvent($this->detailManager, [$app]); + $this->eventDispatcher->dispatch('\OCA\IssueTemplate::requestInformation', $event); } public function getForm() { + + $app = $this->request->getParam('app'); + $this->queryAppDetails($app); + $data = array( - 'version' => $this->getNextcloudVersion(), - 'os' => $this->getOsVersion(), - 'php' => $this->getPhpVersion(), - 'dbserver' => $this->getDatabaseInfo(), - 'webserver' => $_SERVER['SERVER_SOFTWARE'] . " (" . php_sapi_name() . ")", - 'installMethod' => $this->getInstallMethod(), - 'integrity' => $this->getIntegrityResults(), - 'apps' => $this->getAppList(), - 'config' => $this->getConfig(), - 'encryption' => $this->getEncryptionInfo(), - 'external' => $this->getExternalStorageInfo(), - 'browser' => $this->getBrowser() + 'details' => $this->detailManager->getRenderedDetails() ); $issueTemplate = new TemplateResponse('issuetemplate', 'issuetemplate', $data, ''); $parameters = [ 'issueTemplate' => $issueTemplate->render(), 'repos' => $this->getAppRepos(), + 'app' => $app ]; \OC_Util::addScript('issuetemplate','script'); \OC_Util::addStyle('issuetemplate','style'); @@ -102,184 +118,41 @@ class Admin implements ISettings { return 10; } - private function getNextcloudVersion() { - return \OC_Util::getHumanVersion() . " - " . $this->config->getSystemValue('version'); - } - private function getOsVersion() { - return php_uname(); - } - private function getPhpVersion() { - return PHP_VERSION . "\nModules loaded: " . implode(", ", get_loaded_extensions()); - } - - protected function getDatabaseInfo() { - return $this->config->getSystemValue('dbtype') ." " . $this->getDatabaseVersion(); - } - - /** - * original source from nextcloud/survey_client - * @link https://github.com/nextcloud/survey_client/blob/master/lib/Categories/Database.php#L80-L107 - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @author Joas Schilling - * @license AGPL-3.0 - */ - private function getDatabaseVersion() { - 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'; - } - - /** - * Try to strip away additional information - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @author Joas Schilling - * @license AGPL-3.0 - * - * @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; - } - - private function getIntegrityResults() { - if(!$this->checker->isCodeCheckEnforced()) { - return 'Integrity checker has been disabled. Integrity cannot be verified.'; - } - return $this->checker->getResults(); - } - - private function getInstallMethod() { - $base = \OC::$SERVERROOT; - if(file_exists($base . '/.git')) { - return "git"; - } - } - - private function getAppList() { - $apps = \OC_App::getAllApps(); - $enabledApps = $disabledApps = []; - $versions = \OC_App::getAppVersions(); - - //sort enabled apps above disabled apps - foreach ($apps as $app) { - if ($this->appManager->isInstalled($app)) { - $enabledApps[] = $app; - } else { - $disabledApps[] = $app; - } - } - $apps = ['enabled' => [], 'disabled' => []]; - sort($enabledApps); - foreach ($enabledApps as $app) { - $apps['enabled'][$app] = (isset($versions[$app])) ? $versions[$app] : true; - } - sort($disabledApps); - foreach ($disabledApps as $app) { - $apps['disabled'][$app] = null; - } - return $apps; - } - public function getAppRepos() { $apps = \OC_App::getAllApps(); $repos = array( - $this->l->t('Nextcloud server repository') => 'https://github.com/nextcloud/server/issues', - $this->l->t('Nextcloud Android app repository') => 'https://github.com/nextcloud/android/issues', - $this->l->t('Nextcloud iOS app repository') => 'https://github.com/nextcloud/ios/issues' + 'core' => [ + 'name' => $this->l10n->t('Nextcloud server repository'), + 'bugs' => 'https://github.com/nextcloud/server/issues' + ], + 'android' => [ + 'name' => $this->l10n->t('Nextcloud Android app repository'), + 'bugs' => 'https://github.com/nextcloud/android/issues' + ], + 'ios' => [ + 'name' => $this->l10n->t('Nextcloud iOS app repository'), + 'bugs' => 'https://github.com/nextcloud/ios/issues' + ] ); foreach ($apps as $app) { if ($this->appManager->isInstalled($app)) { $appinfo = \OC_App::getAppInfo($app); - if (array_key_exists('bugs', $appinfo) && preg_match("/https:\/\/(www.)?github.com\/(.*)\/issues/i", $appinfo['bugs'])) { - $appTitle = $appinfo['name']; - $repos[$appTitle] = $appinfo['bugs']; + if (array_key_exists('name', $appinfo) + && array_key_exists('bugs', $appinfo) + && preg_match("/https:\/\/(www.)?github.com\/(.*)\/issues/i", $appinfo['bugs'])) { + $appId = $appinfo['id']; + if(is_array($appinfo['name'])) { + $appTitle = $appinfo['name'][0]; + } else { + $appTitle = $appinfo['name']; + } + $repos[$appId] = $appinfo; + $repos[$appId]['name'] = $appTitle; } } } return $repos; - - } - - protected function getEncryptionInfo() { - return $this->config->getAppValue('core', 'encryption_enabled', 'no'); - } - - protected function getExternalStorageInfo() { - if(\OC::$server->getAppManager()->isEnabledForUser('files_external')) { - // $mounts = $this->globalService->getStorageForAllUsers(); - // Global storage services - // https://github.com/nextcloud/server/blob/8c7d7d7746e76b77ad86cee3aae5dbd4d1bcd896/apps/files_external/lib/Command/ListCommand.php - $backendService = \OC::$server->query('OCA\Files_External\Service\BackendService'); - $result = array(); - foreach ($backendService->getAvailableBackends() as $backend) { - $result[] = $backend->getStorageClass(); - } - return $result; - } - return "files_external is disabled"; - } - private function getConfig() { - - $keys = $this->systemConfig->getKeys(); - $configs = []; - foreach ($keys as $key) { - if (true) { - $value = $this->systemConfig->getFilteredValue($key, serialize(null)); - } else { - $value = $this->systemConfig->getValue($key, serialize(null)); - } - if ($value !== 'N;') { - $configs[$key] = $value; - } - } - return $configs; - } - - private function getBrowser() { - $browser = @get_browser(null, true); - $browserString = ''; - if($browser) { - if(array_key_exists('browser', $browser)) { - $browserString .= $browser['browser'] . ' '; - } - if(array_key_exists('version', $browser)) { - $browserString .= $browser['version'] . ' '; - } - if(array_key_exists('plattform', $browser)) { - $browserString .= $browser['plattform'] . ' '; - } - } - if(empty($browserString)) { - return $_SERVER['HTTP_USER_AGENT']; - } - return $browserString; } } diff --git a/lib/Settings/Section.php b/lib/Settings/Section.php index 744862d..09f2988 100644 --- a/lib/Settings/Section.php +++ b/lib/Settings/Section.php @@ -30,12 +30,12 @@ use OCP\Settings\IIconSection; class Section implements IIconSection { /** @var IL10N */ - private $l; + private $l10n; /** @var IURLGenerator */ private $urlGenerator; public function __construct(IL10N $l, IURLGenerator $urlGenerator) { - $this->l = $l; + $this->l10n = $l; $this->urlGenerator = $urlGenerator; } @@ -44,7 +44,7 @@ class Section implements IIconSection { } public function getName() { - return $this->l->t('Issue reporting'); + return $this->l10n->t('Issue reporting'); } public function getPriority() { -- cgit v1.2.3