summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Roach <greg@subaqua.co.uk>2025-02-21 10:43:31 +0000
committerGreg Roach <greg@subaqua.co.uk>2025-02-23 23:29:09 +0000
commite0538ffc67674cbbbc260472873fce2f8f8c1937 (patch)
tree0397e94e6a316a2b6c9316cf42e2668baf91bd12
parent950f8552b0998c1722344a2fa0ced927b0764c50 (diff)
downloadwebtrees-e0538ffc67674cbbbc260472873fce2f8f8c1937.tar.gz
webtrees-e0538ffc67674cbbbc260472873fce2f8f8c1937.tar.bz2
webtrees-e0538ffc67674cbbbc260472873fce2f8f8c1937.zip
CodeStyle
-rw-r--r--app/Cli/Commands/AbstractCommand.php63
-rw-r--r--app/Cli/Commands/CompilePoFiles.php9
-rw-r--r--app/Cli/Commands/ConfigIni.php45
-rw-r--r--app/Cli/Commands/SiteOffline.php10
-rw-r--r--app/Cli/Commands/SiteOnline.php5
-rw-r--r--app/Cli/Commands/SiteSetting.php29
-rw-r--r--app/Cli/Commands/TreeCreate.php14
-rw-r--r--app/Cli/Commands/TreeExport.php11
-rw-r--r--app/Cli/Commands/TreeList.php13
-rw-r--r--app/Cli/Commands/TreeSetting.php31
-rw-r--r--app/Cli/Commands/UserCreate.php48
-rw-r--r--app/Cli/Commands/UserList.php9
-rw-r--r--app/Cli/Commands/UserSetting.php54
-rw-r--r--app/Cli/Commands/UserTreeSetting.php33
-rw-r--r--phpstan-baseline.neon108
-rw-r--r--resources/lang/en-US/messages.php3
16 files changed, 209 insertions, 276 deletions
diff --git a/app/Cli/Commands/AbstractCommand.php b/app/Cli/Commands/AbstractCommand.php
new file mode 100644
index 0000000000..28c0028492
--- /dev/null
+++ b/app/Cli/Commands/AbstractCommand.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2025 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Cli\Commands;
+
+use InvalidArgumentException;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+
+use function is_bool;
+use function is_string;
+
+abstract class AbstractCommand extends Command
+{
+ protected function boolOption(InputInterface $input, string $name): bool
+ {
+ $value = $input->getOption(name: $name);
+
+ if ($value === null || is_bool($value)) {
+ return (bool) $value;
+ }
+
+ throw new InvalidArgumentException(message: 'Argument must be bool : ' . $name);
+ }
+
+ protected function stringArgument(InputInterface $input, string $name): string
+ {
+ $value = $input->getArgument(name: $name);
+
+ if ($value === null || is_string($value)) {
+ return (string) $value;
+ }
+
+ throw new InvalidArgumentException(message: 'Argument must be string: ' . $name);
+ }
+
+ protected function stringOption(InputInterface $input, string $name): string
+ {
+ $value = $input->getOption(name: $name);
+
+ if ($value === null || is_string($value)) {
+ return (string) $value;
+ }
+
+ throw new InvalidArgumentException(message: 'Argument must be string : ' . $name);
+ }
+}
diff --git a/app/Cli/Commands/CompilePoFiles.php b/app/Cli/Commands/CompilePoFiles.php
index af84eda843..c61470b5e2 100644
--- a/app/Cli/Commands/CompilePoFiles.php
+++ b/app/Cli/Commands/CompilePoFiles.php
@@ -21,7 +21,6 @@ namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Localization\Translation;
use Fisharebest\Webtrees\Webtrees;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -31,10 +30,9 @@ use function count;
use function dirname;
use function file_put_contents;
use function glob;
-use function realpath;
use function var_export;
-final class CompilePoFiles extends Command
+final class CompilePoFiles extends AbstractCommand
{
private const string PO_FILE_PATTERN = Webtrees::ROOT_DIR . 'resources/lang/*/*.po';
@@ -54,13 +52,12 @@ final class CompilePoFiles extends Command
if ($po_files === false || $po_files === []) {
$io->error('Failed to find any PO files matching ' . self::PO_FILE_PATTERN);
- return Command::FAILURE;
+ return self::FAILURE;
}
$error = false;
foreach ($po_files as $po_file) {
- $po_file = realpath($po_file);
$translation = new Translation(filename: $po_file);
$translations = $translation->asArray();
$php_file = dirname(path: $po_file) . '/' . basename(path: $po_file, suffix: '.po') . '.php';
@@ -75,6 +72,6 @@ final class CompilePoFiles extends Command
}
}
- return $error ? Command::FAILURE : Command::SUCCESS;
+ return $error ? self::FAILURE : self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/ConfigIni.php b/app/Cli/Commands/ConfigIni.php
index 357535579c..4a032e3095 100644
--- a/app/Cli/Commands/ConfigIni.php
+++ b/app/Cli/Commands/ConfigIni.php
@@ -21,7 +21,6 @@ namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\DB;
use Fisharebest\Webtrees\Webtrees;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -32,7 +31,7 @@ use function file_exists;
use function file_put_contents;
use function parse_ini_file;
-final class ConfigIni extends Command
+final class ConfigIni extends AbstractCommand
{
protected function configure(): void
{
@@ -62,42 +61,40 @@ final class ConfigIni extends Command
->addOption(name: 'tblpfx', mode: InputOption::VALUE_OPTIONAL, description: 'Table prefix', default: $config['tblpfx'] ?? '')
->addOption(name: 'base-url', mode: InputOption::VALUE_OPTIONAL, description: 'Base URL', default: $config['base_url'] ?? '')
->addOption(name: 'rewrite-urls', mode: InputOption::VALUE_NEGATABLE, description: 'Use pretty URLs', default: (bool) ($config['rewrite_urls'] ?? false))
- ->addOption(name: 'block-asn', mode: InputOption::VALUE_OPTIONAL, description: 'List of ASNs to block', default: $config['block_asn'] ?? '')
- ;
+ ->addOption(name: 'block-asn', mode: InputOption::VALUE_OPTIONAL, description: 'List of ASNs to block', default: $config['block_asn'] ?? '');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle(input: $input, output: $output);
- $data =
- '; <?php return; ?> DO NOT DELETE THIS LINE' . PHP_EOL;
+ $data = '; <?php return; ?> DO NOT DELETE THIS LINE' . PHP_EOL;
$config = [
- 'dbtype' => $input->getOption(name: 'dbtype'),
- 'dbhost' => $input->getOption(name: 'dbhost'),
- 'dbport' => $input->getOption(name: 'dbport'),
- 'dbuser' => $input->getOption(name: 'dbuser'),
- 'dbpass' => $input->getOption(name: 'dbpass'),
- 'dbname' => $input->getOption(name: 'dbname'),
- 'dbkey' => $input->getOption(name: 'dbkey'),
- 'dbcert' => $input->getOption(name: 'dbcert'),
- 'dbca' => $input->getOption(name: 'dbca'),
- 'dbverify' => (int) (bool) $input->getOption(name: 'dbverify'),
- 'tblpfx' => $input->getOption(name: 'tblpfx'),
- 'base_url' => rtrim(string: $input->getOption(name: 'base-url'), characters: '/'),
- 'rewrite_urls' => (int) (bool) $input->getOption(name: 'rewrite-urls'),
- 'block_asn' => $input->getOption(name: 'block-asn'),
+ 'dbtype' => $this->stringOption(input: $input, name: 'dbtype'),
+ 'dbhost' => $this->stringOption(input: $input, name: 'dbhost'),
+ 'dbport' => $this->stringOption(input: $input, name: 'dbport'),
+ 'dbuser' => $this->stringOption(input: $input, name: 'dbuser'),
+ 'dbpass' => $this->stringOption(input: $input, name: 'dbpass'),
+ 'dbname' => $this->stringOption(input: $input, name: 'dbname'),
+ 'dbkey' => $this->stringOption(input: $input, name: 'dbkey'),
+ 'dbcert' => $this->stringOption(input: $input, name: 'dbcert'),
+ 'dbca' => $this->stringOption(input: $input, name: 'dbca'),
+ 'dbverify' => $this->boolOption(input: $input, name: 'dbverify') ? '1' : '0',
+ 'tblpfx' => $this->stringOption(input: $input, name: 'tblpfx'),
+ 'base_url' => rtrim(string: $this->stringOption(input: $input, name: 'base-url'), characters: '/'),
+ 'rewrite_urls' => $this->boolOption(input: $input, name: 'rewrite-urls') ? '1' : '0',
+ 'block_asn' => $this->stringOption(input: $input, name: 'block-asn'),
];
foreach ($config as $key => $value) {
- $data .= $key . ' = "' . addcslashes(string: (string) $value, characters: '"') . '"' . PHP_EOL;
+ $data .= $key . ' = "' . addcslashes(string: $value, characters: '"') . '"' . PHP_EOL;
}
$io->info(message: $data);
file_put_contents(filename: Webtrees::CONFIG_FILE, data: $data);
- if ($input->getOption(name: 'base-url') === '') {
+ if ($config['base_url'] === '') {
$io->warning(message: 'You must set the base URL');
}
@@ -122,9 +119,9 @@ final class ConfigIni extends Command
} catch (Throwable $ex) {
$io->error(message: 'Database connection failed: ' . $ex->getMessage());
- return Command::FAILURE;
+ return self::FAILURE;
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/SiteOffline.php b/app/Cli/Commands/SiteOffline.php
index 238a9a0458..be5d01e5bb 100644
--- a/app/Cli/Commands/SiteOffline.php
+++ b/app/Cli/Commands/SiteOffline.php
@@ -20,7 +20,6 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\Webtrees;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -30,7 +29,7 @@ use Throwable;
use function file_exists;
use function file_put_contents;
-final class SiteOffline extends Command
+final class SiteOffline extends AbstractCommand
{
protected function configure(): void
{
@@ -42,8 +41,7 @@ final class SiteOffline extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
- /** @var string $message */
- $message = $input->getArgument(name: 'message') ?? '';
+ $message = $this->stringArgument(input: $input, name: 'message');
$io = new SymfonyStyle(input: $input, output: $output);
@@ -55,7 +53,7 @@ final class SiteOffline extends Command
$io->error(message: 'Failed to write file ' . Webtrees::OFFLINE_FILE);
$io->error(message: $ex->getMessage());
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($file_exists) {
@@ -64,6 +62,6 @@ final class SiteOffline extends Command
$io->success(message: Webtrees::OFFLINE_FILE . ' created. Site is offline.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/SiteOnline.php b/app/Cli/Commands/SiteOnline.php
index 9323543a69..36c357c6cb 100644
--- a/app/Cli/Commands/SiteOnline.php
+++ b/app/Cli/Commands/SiteOnline.php
@@ -20,7 +20,6 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\Webtrees;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -28,7 +27,7 @@ use Throwable;
use function file_exists;
-final class SiteOnline extends Command
+final class SiteOnline extends AbstractCommand
{
protected function configure(): void
{
@@ -54,6 +53,6 @@ final class SiteOnline extends Command
$io->error(message: 'Unable to delete ' . Webtrees::OFFLINE_FILE . ' - ' . $ex->getMessage());
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/SiteSetting.php b/app/Cli/Commands/SiteSetting.php
index beb0fcd869..dd4f8277b6 100644
--- a/app/Cli/Commands/SiteSetting.php
+++ b/app/Cli/Commands/SiteSetting.php
@@ -20,7 +20,6 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\DB;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -28,7 +27,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-final class SiteSetting extends Command
+final class SiteSetting extends AbstractCommand
{
protected function configure(): void
{
@@ -43,9 +42,9 @@ final class SiteSetting extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
- $quiet = (bool) $input->getOption(name: 'quiet');
- $list = (bool) $input->getOption(name: 'list');
- $delete = (bool) $input->getOption(name: 'delete');
+ $quiet = $this->boolOption(input: $input, name: 'quiet');
+ $list = $this->boolOption(input: $input, name: 'list');
+ $delete = $this->boolOption(input: $input, name: 'delete');
/** @var string|null $setting_name */
$setting_name = $input->getArgument(name: 'setting-name');
@@ -59,13 +58,13 @@ final class SiteSetting extends Command
if ($delete) {
$io->error(message: 'Cannot specify --list and --delete together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value !== null) {
$io->error(message: 'Cannot specify --list and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$table = new Table(output: $output);
@@ -86,7 +85,7 @@ final class SiteSetting extends Command
$table->render();
- return Command::SUCCESS;
+ return self::SUCCESS;
}
/** @var string|null $old_setting_value */
@@ -98,13 +97,13 @@ final class SiteSetting extends Command
if ($setting_name === null) {
$io->error(message: 'Setting name must be specified for --delete.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value !== null) {
$io->error(message: 'Cannot specify --delete and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($old_setting_value === null) {
@@ -117,14 +116,14 @@ final class SiteSetting extends Command
$io->success(message: 'Site setting ‘' . $setting_name . '’ deleted. Previous value was ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($setting_name === null) {
$io->error(message: 'A setting name is required, unless the --list option is used.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value === null) {
@@ -139,13 +138,13 @@ final class SiteSetting extends Command
$io->info(message: 'Site setting ‘' . $setting_name . '’ is currently set to ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === $setting_value) {
$io->warning(message: 'Site setting ' . $setting_name . ' is already set to ' . $setting_value);
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === null) {
@@ -164,6 +163,6 @@ final class SiteSetting extends Command
$io->success(message: 'Site setting ‘' . $setting_name . '’ was changed from ‘' . $old_setting_value . '’ to ‘' . $setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/TreeCreate.php b/app/Cli/Commands/TreeCreate.php
index 06c0f453a7..965f09e51c 100644
--- a/app/Cli/Commands/TreeCreate.php
+++ b/app/Cli/Commands/TreeCreate.php
@@ -28,7 +28,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-final class TreeCreate extends Command
+final class TreeCreate extends AbstractCommand
{
public function __construct(private readonly TreeService $tree_service)
{
@@ -48,17 +48,17 @@ final class TreeCreate extends Command
{
$io = new SymfonyStyle(input: $input, output: $output);
- $name = $input->getOption(name: 'name');
- $title = $input->getOption(name: 'title');
+ $name = $this->stringOption(input: $input, name: 'name');
+ $title = $this->stringOption(input: $input, name: 'title');
$missing = false;
- if ($name === null) {
+ if ($name === '') {
$io->error(message: 'Missing required option: --name');
$missing = true;
}
- if ($title === null) {
+ if ($title === '') {
$io->error(message: 'Missing required option: --title');
$missing = true;
}
@@ -72,13 +72,13 @@ final class TreeCreate extends Command
if ($tree !== null) {
$io->error(message: 'A tree with the name "' . $name . '" already exists.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$tree = $this->tree_service->create(name: $name, title: $title);
DB::exec(sql: 'COMMIT');
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/TreeExport.php b/app/Cli/Commands/TreeExport.php
index b1e1ef88b9..b058e9adcd 100644
--- a/app/Cli/Commands/TreeExport.php
+++ b/app/Cli/Commands/TreeExport.php
@@ -24,7 +24,6 @@ use Fisharebest\Webtrees\DB;
use Fisharebest\Webtrees\Encodings\UTF8;
use Fisharebest\Webtrees\Services\GedcomExportService;
use Fisharebest\Webtrees\Services\TreeService;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -35,7 +34,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
use function addcslashes;
use function stream_get_contents;
-final class TreeExport extends Command
+final class TreeExport extends AbstractCommand
{
public function __construct(
private readonly GedcomExportService $gedcom_export_service,
@@ -70,15 +69,15 @@ final class TreeExport extends Command
$io = new SymfonyStyle(input: $input, output: $output);
$tree_name = $input->getArgument(name: 'tree_name');
- $format = $input->getOption(name: 'format');
- $filename = $input->getOption(name: 'filename');
+ $format = $this->stringOption(input: $input, name: 'format');
+ $filename = $this->stringOption(input: $input, name: 'filename');
$tree = $this->tree_service->all()[$tree_name] ?? null;
if ($tree === null) {
$io->error(message: 'Tree "' . $tree_name . '" not found.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$stream = $this->gedcom_export_service->export(
@@ -96,6 +95,6 @@ final class TreeExport extends Command
$io->success('File exported successfully.');
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/TreeList.php b/app/Cli/Commands/TreeList.php
index 33f7a28680..922669861e 100644
--- a/app/Cli/Commands/TreeList.php
+++ b/app/Cli/Commands/TreeList.php
@@ -21,7 +21,6 @@ namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\Services\TreeService;
use Fisharebest\Webtrees\Tree;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -32,7 +31,7 @@ use function addcslashes;
use function array_map;
use function implode;
-final class TreeList extends Command
+final class TreeList extends AbstractCommand
{
public function __construct(private readonly TreeService $tree_service)
{
@@ -55,7 +54,7 @@ final class TreeList extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
- $format = $input->getOption(name: 'format');
+ $format = $this->stringOption(input: $input, name: 'format');
$io = new SymfonyStyle(input: $input, output: $output);
@@ -70,8 +69,8 @@ final class TreeList extends Command
'media_directory' => $tree->getPreference(setting_name: 'MEDIA_DIRECTORY'),
'imported' => $tree->getPreference(setting_name: 'imported') ? 'yes' : 'no',
])
- ->values()
- ->all();
+ ->values()
+ ->all();
switch ($format) {
case 'table':
@@ -96,10 +95,10 @@ final class TreeList extends Command
default:
$io->error(message: 'Invalid format: ‘' . $format . '’');
- return Command::FAILURE;
+ return self::FAILURE;
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
/**
diff --git a/app/Cli/Commands/TreeSetting.php b/app/Cli/Commands/TreeSetting.php
index 6d2708f3c9..68700c55ce 100644
--- a/app/Cli/Commands/TreeSetting.php
+++ b/app/Cli/Commands/TreeSetting.php
@@ -20,7 +20,6 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\DB;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -28,7 +27,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-final class TreeSetting extends Command
+final class TreeSetting extends AbstractCommand
{
protected function configure(): void
{
@@ -44,9 +43,9 @@ final class TreeSetting extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
- $quiet = (bool) $input->getOption(name: 'quiet');
- $list = (bool) $input->getOption(name: 'list');
- $delete = (bool) $input->getOption(name: 'delete');
+ $quiet = $this->boolOption(input: $input, name: 'quiet');
+ $list = $this->boolOption(input: $input, name: 'list');
+ $delete = $this->boolOption(input: $input, name: 'delete');
/** @var string $tree_name */
$tree_name = $input->getArgument(name: 'tree-name');
@@ -66,20 +65,20 @@ final class TreeSetting extends Command
if ($tree_id === null) {
$io->error(message: 'Tree ‘' . $tree_name . '’ not found.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($list) {
if ($delete) {
$io->error(message: 'Cannot specify --list and --delete together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value !== null) {
$io->error(message: 'Cannot specify --list and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$table = new Table(output: $output);
@@ -101,7 +100,7 @@ final class TreeSetting extends Command
$table->render();
- return Command::SUCCESS;
+ return self::SUCCESS;
}
/** @var string|null $old_setting_value */
@@ -114,13 +113,13 @@ final class TreeSetting extends Command
if ($setting_name === null) {
$io->error(message: 'Setting name must be specified for --delete.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value !== null) {
$io->error(message: 'Cannot specify --delete and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($old_setting_value === null) {
@@ -134,14 +133,14 @@ final class TreeSetting extends Command
$io->success(message: 'Tree setting ‘' . $setting_name . '’ deleted. Previous value was ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($setting_name === null) {
$io->error(message: 'A setting name is required, unless the --list option is used.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value === null) {
@@ -156,13 +155,13 @@ final class TreeSetting extends Command
$io->info(message: 'Tree setting ‘' . $setting_name . '’ is currently set to ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === $setting_value) {
$io->warning(message: 'Tree setting ' . $setting_name . ' is already set to ' . $setting_value);
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === null) {
@@ -183,6 +182,6 @@ final class TreeSetting extends Command
$io->success(message: 'Tree setting ‘' . $setting_name . '’ was changed from ‘' . $old_setting_value . '’ to ‘' . $setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/UserCreate.php b/app/Cli/Commands/UserCreate.php
index 334d24dcb8..ce59f279d9 100644
--- a/app/Cli/Commands/UserCreate.php
+++ b/app/Cli/Commands/UserCreate.php
@@ -31,7 +31,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
use function bin2hex;
use function random_bytes;
-final class UserCreate extends Command
+final class UserCreate extends AbstractCommand
{
public function __construct(private readonly UserService $user_service)
{
@@ -43,45 +43,45 @@ final class UserCreate extends Command
$this
->setName(name: 'user-create')
->setDescription(description: 'Create a new user')
- ->addOption(name: 'username', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'The username of the new user')
- ->addOption(name: 'realname', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'The real name of the new user')
- ->addOption(name: 'email', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'The email of the new user')
- ->addOption(name: 'password', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'The password of the new user')
- ->addOption(name: 'timezone', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'Set the timezone', default: 'UTC')
- ->addOption(name: 'language', shortcut: null, mode: InputOption::VALUE_REQUIRED, description: 'Set the language', default: 'en-US')
- ->addOption(name: 'admin', shortcut: null, mode: InputOption::VALUE_NONE, description: 'Make the new user an administrator');
+ ->addOption(name: 'username', mode: InputOption::VALUE_REQUIRED, description: 'The username of the new user')
+ ->addOption(name: 'realname', mode: InputOption::VALUE_REQUIRED, description: 'The real name of the new user')
+ ->addOption(name: 'email', mode: InputOption::VALUE_REQUIRED, description: 'The email of the new user')
+ ->addOption(name: 'password', mode: InputOption::VALUE_REQUIRED, description: 'The password of the new user')
+ ->addOption(name: 'timezone', mode: InputOption::VALUE_REQUIRED, description: 'Set the timezone', default: 'UTC')
+ ->addOption(name: 'language', mode: InputOption::VALUE_REQUIRED, description: 'Set the language', default: 'en-US')
+ ->addOption(name: 'admin', mode: InputOption::VALUE_NONE, description: 'Make the new user an administrator');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle(input: $input, output: $output);
- $username = $input->getOption(name: 'username');
- $realname = $input->getOption(name: 'realname');
- $email = $input->getOption(name: 'email');
- $password = $input->getOption(name: 'password');
- $admin = (bool) $input->getOption(name: 'admin');
- $timezone = $input->getOption(name: 'timezone');
- $language = $input->getOption(name: 'language');
+ $username = $this->stringOption(input: $input, name: 'username');
+ $realname = $this->stringOption(input: $input, name: 'realname');
+ $email = $this->stringOption(input: $input, name: 'email');
+ $password = $this->stringOption(input: $input, name: 'password');
+ $admin = $this->boolOption(input: $input, name: 'admin');
+ $timezone = $this->stringOption(input: $input, name: 'timezone');
+ $language = $this->stringOption(input: $input, name: 'language');
$errors = false;
- if ($username === null) {
+ if ($username === '') {
$io->error(message: 'Missing required option: --username');
$errors = true;
}
- if ($realname === null) {
+ if ($realname === '') {
$io->error(message: 'Missing required option: --realname');
$errors = true;
}
- if ($email === null) {
+ if ($email === '') {
$io->error(message: 'Missing required option: --email');
$errors = true;
}
- if ($timezone === null) {
+ if ($timezone === '') {
$io->error(message: 'Missing required option: --timezone');
$errors = true;
}
@@ -95,7 +95,7 @@ final class UserCreate extends Command
if ($user !== null) {
$io->error(message: 'A user with the username "' . $username . '" already exists.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$user = $this->user_service->findByEmail(email: $email);
@@ -103,11 +103,11 @@ final class UserCreate extends Command
if ($user !== null) {
$io->error(message: 'A user with the email "' . $email . '" already exists');
- return Command::FAILURE;
+ return self::FAILURE;
}
- if ($password === null) {
- $password = bin2hex(string: random_bytes(length: 8));
+ if ($password === '') {
+ $password = bin2hex(string: random_bytes(length: 12));
$io->info(message: 'Generated password: ' . $password);
}
@@ -126,6 +126,6 @@ final class UserCreate extends Command
DB::exec(sql: 'COMMIT');
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/UserList.php b/app/Cli/Commands/UserList.php
index cea58c779e..17f299cc19 100644
--- a/app/Cli/Commands/UserList.php
+++ b/app/Cli/Commands/UserList.php
@@ -23,7 +23,6 @@ use Fisharebest\Webtrees\Contracts\UserInterface;
use Fisharebest\Webtrees\Registry;
use Fisharebest\Webtrees\Services\UserService;
use Fisharebest\Webtrees\User;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -34,7 +33,7 @@ use function addcslashes;
use function array_map;
use function implode;
-final class UserList extends Command
+final class UserList extends AbstractCommand
{
public function __construct(private readonly UserService $user_service)
{
@@ -57,7 +56,7 @@ final class UserList extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
- $format = $input->getOption(name: 'format');
+ $format = $this->stringOption(input: $input, name: 'format');
$io = new SymfonyStyle(input: $input, output: $output);
@@ -105,10 +104,10 @@ final class UserList extends Command
default:
$io->error(message: 'Invalid format: ‘' . $format . '’');
- return Command::FAILURE;
+ return self::FAILURE;
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
private function formatTimestamp(int $timestamp): string
diff --git a/app/Cli/Commands/UserSetting.php b/app/Cli/Commands/UserSetting.php
index 7df92d8ea4..3b6f6f9457 100644
--- a/app/Cli/Commands/UserSetting.php
+++ b/app/Cli/Commands/UserSetting.php
@@ -20,7 +20,6 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\DB;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -28,7 +27,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-final class UserSetting extends Command
+final class UserSetting extends AbstractCommand
{
protected function configure(): void
{
@@ -44,18 +43,13 @@ final class UserSetting extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
- $quiet = (bool) $input->getOption(name: 'quiet');
- $list = (bool) $input->getOption(name: 'list');
- $delete = (bool) $input->getOption(name: 'delete');
+ $quiet = $this->boolOption(input: $input, name: 'quiet');
+ $list = $this->boolOption(input: $input, name: 'list');
+ $delete = $this->boolOption(input: $input, name: 'delete');
- /** @var string $user_name */
- $user_name = $input->getArgument(name: 'user-name');
-
- /** @var string|null $setting_name */
- $setting_name = $input->getArgument(name: 'setting-name');
-
- /** @var string|null $setting_value */
- $setting_value = $input->getArgument(name: 'setting-value');
+ $user_name = $this->stringArgument(input: $input, name: 'user-name');
+ $setting_name = $this->stringArgument(input: $input, name: 'setting-name');
+ $setting_value = $this->stringArgument(input: $input, name: 'setting-value');
$io = new SymfonyStyle(input: $input, output: $output);
@@ -66,20 +60,20 @@ final class UserSetting extends Command
if ($user_id === null) {
$io->error(message: 'User ‘' . $user_name . '’ not found.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($list) {
if ($delete) {
$io->error(message: 'Cannot specify --list and --delete together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
- if ($setting_value !== null) {
+ if ($setting_value !== '') {
$io->error(message: 'Cannot specify --list and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$table = new Table(output: $output);
@@ -94,14 +88,14 @@ final class UserSetting extends Command
->all();
foreach ($settings as $setting) {
- if ($setting_name === null || str_contains(haystack: $setting->setting_name, needle: $setting_name)) {
+ if (str_contains(haystack: $setting->setting_name, needle: $setting_name)) {
$table->addRow(row: [$setting->setting_name, $setting->setting_value]);
}
}
$table->render();
- return Command::SUCCESS;
+ return self::SUCCESS;
}
/** @var string|null $old_setting_value */
@@ -111,16 +105,16 @@ final class UserSetting extends Command
->value(column: 'setting_value');
if ($delete) {
- if ($setting_name === null) {
+ if ($setting_name === '') {
$io->error(message: 'Setting name must be specified for --delete.');
- return Command::FAILURE;
+ return self::FAILURE;
}
- if ($setting_value !== null) {
+ if ($setting_value !== '') {
$io->error(message: 'Cannot specify --delete and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($old_setting_value === null) {
@@ -134,17 +128,17 @@ final class UserSetting extends Command
$io->success(message: 'User setting ‘' . $setting_name . '’ deleted. Previous value was ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
- if ($setting_name === null) {
+ if ($setting_name === '') {
$io->error(message: 'A setting name is required, unless the --list option is used.');
- return Command::FAILURE;
+ return self::FAILURE;
}
- if ($setting_value === null) {
+ if ($setting_value === '') {
if ($old_setting_value === null) {
$io->info(message: 'User setting ‘' . $setting_name . '’ is not currently set.');
} elseif ($quiet) {
@@ -156,13 +150,13 @@ final class UserSetting extends Command
$io->info(message: 'User setting ‘' . $setting_name . '’ is currently set to ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === $setting_value) {
$io->warning(message: 'User setting ' . $setting_name . ' is already set to ' . $setting_value);
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === null) {
@@ -183,6 +177,6 @@ final class UserSetting extends Command
$io->success(message: 'User setting ‘' . $setting_name . '’ was changed from ‘' . $old_setting_value . '’ to ‘' . $setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/app/Cli/Commands/UserTreeSetting.php b/app/Cli/Commands/UserTreeSetting.php
index eaed1f26ba..2c0a527077 100644
--- a/app/Cli/Commands/UserTreeSetting.php
+++ b/app/Cli/Commands/UserTreeSetting.php
@@ -20,7 +20,6 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees\Cli\Commands;
use Fisharebest\Webtrees\DB;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -28,7 +27,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
-final class UserTreeSetting extends Command
+final class UserTreeSetting extends AbstractCommand
{
protected function configure(): void
{
@@ -45,9 +44,9 @@ final class UserTreeSetting extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
- $quiet = (bool) $input->getOption(name: 'quiet');
- $list = (bool) $input->getOption(name: 'list');
- $delete = (bool) $input->getOption(name: 'delete');
+ $quiet = $this->boolOption(input: $input, name: 'quiet');
+ $list = $this->boolOption(input: $input, name: 'list');
+ $delete = $this->boolOption(input: $input, name: 'delete');
/** @var string $user_name */
$user_name = $input->getArgument(name: 'user-name');
@@ -70,7 +69,7 @@ final class UserTreeSetting extends Command
if ($user_id === null) {
$io->error(message: 'User ‘' . $user_name . '’ not found.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$tree_id = DB::table('gedcom')
@@ -80,20 +79,20 @@ final class UserTreeSetting extends Command
if ($tree_id === null) {
$io->error(message: 'Tree ‘' . $tree_name . '’ not found.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($list) {
if ($delete) {
$io->error(message: 'Cannot specify --list and --delete together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value !== null) {
$io->error(message: 'Cannot specify --list and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
$table = new Table(output: $output);
@@ -116,7 +115,7 @@ final class UserTreeSetting extends Command
$table->render();
- return Command::SUCCESS;
+ return self::SUCCESS;
}
/** @var string|null $old_setting_value */
@@ -130,13 +129,13 @@ final class UserTreeSetting extends Command
if ($setting_name === null) {
$io->error(message: 'Setting name must be specified for --delete.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value !== null) {
$io->error(message: 'Cannot specify --delete and a new value together.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($old_setting_value === null) {
@@ -151,14 +150,14 @@ final class UserTreeSetting extends Command
$io->success(message: 'User-tree setting ‘' . $setting_name . '’ deleted. Previous value was ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($setting_name === null) {
$io->error(message: 'A setting name is required, unless the --list option is used.');
- return Command::FAILURE;
+ return self::FAILURE;
}
if ($setting_value === null) {
@@ -173,13 +172,13 @@ final class UserTreeSetting extends Command
$io->info(message: 'User-tree setting ‘' . $setting_name . '’ is currently set to ‘' . $old_setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === $setting_value) {
$io->warning(message: 'User-tree setting ' . $setting_name . ' is already set to ' . $setting_value);
- return Command::SUCCESS;
+ return self::SUCCESS;
}
if ($old_setting_value === null) {
@@ -202,6 +201,6 @@ final class UserTreeSetting extends Command
$io->success(message: 'User-tree setting ‘' . $setting_name . '’ was changed from ‘' . $old_setting_value . '’ to ‘' . $setting_value . '’.');
}
- return Command::SUCCESS;
+ return self::SUCCESS;
}
}
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index e4d64e3f09..152d2babd7 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -25,24 +25,6 @@ parameters:
path: app/Census/CensusColumnRelationToHead.php
-
- message: '#^Parameter \$filename of class Fisharebest\\Localization\\Translation constructor expects string, string\|false given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/CompilePoFiles.php
-
- -
- message: '#^Parameter \$path of function basename expects string, string\|false given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/CompilePoFiles.php
-
- -
- message: '#^Parameter \$path of function dirname expects string, string\|false given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/CompilePoFiles.php
-
- -
message: '#^Cannot access offset ''dbca'' on array\|false\.$#'
identifier: offsetAccess.nonOffsetAccessible
count: 1
@@ -109,12 +91,6 @@ parameters:
path: app/Cli/Commands/ConfigIni.php
-
- message: '#^Cannot cast mixed to string\.$#'
- identifier: cast.string
- count: 1
- path: app/Cli/Commands/ConfigIni.php
-
- -
message: '#^Parameter \$ca of static method Fisharebest\\Webtrees\\DB\:\:connect\(\) expects string, mixed given\.$#'
identifier: argument.type
count: 1
@@ -169,36 +145,12 @@ parameters:
path: app/Cli/Commands/ConfigIni.php
-
- message: '#^Parameter \$string of function rtrim expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/ConfigIni.php
-
- -
message: '#^Parameter \$username of static method Fisharebest\\Webtrees\\DB\:\:connect\(\) expects string, mixed given\.$#'
identifier: argument.type
count: 1
path: app/Cli/Commands/ConfigIni.php
-
- message: '#^Binary operation "\." between ''A tree with the…'' and mixed results in an error\.$#'
- identifier: binaryOp.invalid
- count: 1
- path: app/Cli/Commands/TreeCreate.php
-
- -
- message: '#^Parameter \$name of method Fisharebest\\Webtrees\\Services\\TreeService\:\:create\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/TreeCreate.php
-
- -
- message: '#^Parameter \$title of method Fisharebest\\Webtrees\\Services\\TreeService\:\:create\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/TreeCreate.php
-
- -
message: '#^Binary operation "\." between ''Tree "'' and mixed results in an error\.$#'
identifier: binaryOp.invalid
count: 1
@@ -217,66 +169,6 @@ parameters:
path: app/Cli/Commands/TreeExport.php
-
- message: '#^Binary operation "\." between ''Invalid format\: ‘'' and mixed results in an error\.$#'
- identifier: binaryOp.invalid
- count: 1
- path: app/Cli/Commands/TreeList.php
-
- -
- message: '#^Binary operation "\." between ''A user with the…'' and mixed results in an error\.$#'
- identifier: binaryOp.invalid
- count: 2
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Parameter \$email of method Fisharebest\\Webtrees\\Services\\UserService\:\:create\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Parameter \$email of method Fisharebest\\Webtrees\\Services\\UserService\:\:findByEmail\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Parameter \$password of method Fisharebest\\Webtrees\\Services\\UserService\:\:create\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Parameter \$real_name of method Fisharebest\\Webtrees\\Services\\UserService\:\:create\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Parameter \$setting_value of method Fisharebest\\Webtrees\\User\:\:setPreference\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 2
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Parameter \$user_name of method Fisharebest\\Webtrees\\Services\\UserService\:\:create\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Parameter \$user_name of method Fisharebest\\Webtrees\\Services\\UserService\:\:findByUserName\(\) expects string, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: app/Cli/Commands/UserCreate.php
-
- -
- message: '#^Binary operation "\." between ''Invalid format\: ‘'' and mixed results in an error\.$#'
- identifier: binaryOp.invalid
- count: 1
- path: app/Cli/Commands/UserList.php
-
- -
message: '#^Parameter \#1 \$command of method Symfony\\Component\\Console\\Application\:\:add\(\) expects Symfony\\Component\\Console\\Command\\Command, mixed given\.$#'
identifier: argument.type
count: 1
diff --git a/resources/lang/en-US/messages.php b/resources/lang/en-US/messages.php
index 857cb41080..1f671c6193 100644
--- a/resources/lang/en-US/messages.php
+++ b/resources/lang/en-US/messages.php
@@ -1,8 +1,7 @@
<?php
-declare(strict_types=1);
-
return array (
+ ' but the details are unknown' => ' but the details are unknown',
'%H:%i:%s' => '%g:%i:%s %a',
'%j %F %Y' => '%F %j, %Y',
'Asunción, Paraguay' => 'Asuncion, Paraguay',