Quality of life things.
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Build and test / requirements (push) Failing after 3m48s
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Build and test / requirements (push) Failing after 3m48s
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ config.yml
|
||||
*.phar
|
||||
*.deb
|
||||
.phpunit.result.cache
|
||||
*cache/
|
51
.phpcs.xml
Normal file
51
.phpcs.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PHP_CodeSniffer" xsi:noNamespaceSchemaLocation="phpcs.xsd">
|
||||
<description>Coding standard</description>
|
||||
|
||||
<file>src/</file>
|
||||
<file>tests/</file>
|
||||
|
||||
<rule ref="PSR1">
|
||||
<exclude name="Generic.Files.LineLength"/>
|
||||
</rule>
|
||||
<rule ref="PSR2"></rule>
|
||||
<rule ref="PSR12"></rule>
|
||||
|
||||
<rule ref="Generic">
|
||||
<exclude name="Generic.WhiteSpace.DisallowSpaceIndent.SpacesUsed"/>
|
||||
<exclude name="Generic.Files.LowercasedFilename.NotFound"/>
|
||||
<exclude name="Generic.PHP.ClosingPHPTag.NotFound"/>
|
||||
<exclude name="Generic.Files.EndFileNoNewline.Found"/>
|
||||
<exclude name="Generic.Files.EndFileNoNewline.Found"/>
|
||||
<exclude name="Generic.Arrays.DisallowShortArraySyntax.Found"/>
|
||||
<exclude name="Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine"/>
|
||||
<exclude name="Generic.Classes.OpeningBraceSameLine.BraceOnNewLine"/>
|
||||
<exclude name="Generic.PHP.LowerCaseConstant.Found"/>
|
||||
<exclude name="Generic.Formatting.SpaceAfterCast"/>
|
||||
<exclude name="Generic.Formatting.MultipleStatementAlignment.NotSameWarning"/>
|
||||
<exclude name="Generic.Commenting.DocComment.MissingShort"/>
|
||||
<exclude name="Generic.NamingConventions.AbstractClassNamePrefix.Missing"/>
|
||||
<exclude name="Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed"/>
|
||||
<exclude name="Generic.NamingConventions.InterfaceNameSuffix.Missing"/>
|
||||
<exclude name="Generic.Commenting.Todo.TaskFound"/>
|
||||
<exclude name="Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceAfterLastUse"/>
|
||||
<exclude name="Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed"/>
|
||||
<exclude name="Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceAfterLastUsed"/>
|
||||
<exclude name="Generic.Formatting.SpaceBeforeCast.NoSpace"/>
|
||||
<exclude name="Generic.CodeAnalysis.UselessOverridingMethod.Found"/>
|
||||
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.NewlineBeforeOpenBrace"/>
|
||||
</rule>
|
||||
|
||||
<!-- Ban some functions -->
|
||||
<rule ref="Generic.PHP.ForbiddenFunctions">
|
||||
<properties>
|
||||
<property name="forbiddenFunctions" type="array">
|
||||
<element key="sizeof" value="count"/>
|
||||
<element key="delete" value="unset"/>
|
||||
<element key="print" value="echo"/>
|
||||
<element key="is_null" value="null"/>
|
||||
<element key="create_function" value="null"/>
|
||||
</property>
|
||||
</properties>
|
||||
</rule>
|
||||
</ruleset>
|
@ -23,10 +23,6 @@
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"squizlabs/php_codesniffer": "*",
|
||||
"phpstan/phpstan": "^1.10.37",
|
||||
"vimeo/psalm": "^5.15",
|
||||
"phpmd/phpmd": "^2.14.1",
|
||||
"phpunit/phpunit": "^10.3.5",
|
||||
"phpmetrics/phpmetrics": "^2.8.2"
|
||||
},
|
||||
@ -34,7 +30,7 @@
|
||||
"test": "vendor/bin/phpunit tests --display-warnings",
|
||||
"test-full": "vendor/bin/phpunit -c phpunit.full.xml",
|
||||
"metrics": "vendor/bin/phpmetrics --report-html=output/metrics --junit=output/test.xml src/",
|
||||
"docs": "./phpDocumentor.phar --setting=graphs.enabled=true",
|
||||
"docs": "phpDocumentor --setting=graphs.enabled=true",
|
||||
"analyze": [
|
||||
"@analyze-yaml",
|
||||
"@analyze-phpmd",
|
||||
@ -43,9 +39,9 @@
|
||||
"@analyze-phpcs"
|
||||
],
|
||||
"analyze-yaml": "vendor/bin/yaml-lint *.yml .*.yml *.json",
|
||||
"analyze-phpmd": "vendor/bin/phpmd src,tests text cleancode,codesize,controversial,design,naming,unusedcode",
|
||||
"analyze-phpstan":"vendor/bin/phpstan analyze --level=8 --error-format=raw src/ backup tests",
|
||||
"analyze-psalm": "vendor/bin/psalm --no-cache",
|
||||
"analyze-phpcs": "vendor/bin/phpcs src backup tests --report=emacs --standard=PSR12"
|
||||
"analyze-phpmd": "phpmd src,tests text cleancode,codesize,controversial,design,naming,unusedcode",
|
||||
"analyze-phpstan":"phpstan",
|
||||
"analyze-psalm": "psalm --no-cache",
|
||||
"analyze-phpcs": "phpcs"
|
||||
}
|
||||
}
|
||||
|
1871
composer.lock
generated
1871
composer.lock
generated
File diff suppressed because it is too large
Load Diff
5
phpstan.neon
Normal file
5
phpstan.neon
Normal file
@ -0,0 +1,5 @@
|
||||
parameters:
|
||||
level: 8
|
||||
paths:
|
||||
- src
|
||||
- tests
|
@ -1,36 +0,0 @@
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
|
||||
executionOrder="random"
|
||||
testdox="true"
|
||||
displayDetailsOnIncompleteTests="true"
|
||||
displayDetailsOnSkippedTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerErrors="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="All">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
<file>backup</file>
|
||||
</include>
|
||||
</source>
|
||||
<logging>
|
||||
<junit outputFile="output/test.xml"/>
|
||||
<testdoxHtml outputFile="output/test.html"/>
|
||||
<testdoxText outputFile="output/test.txt"/>
|
||||
</logging>
|
||||
<coverage includeUncoveredFiles="true"
|
||||
pathCoverage="true">
|
||||
<report>
|
||||
<html outputDirectory="output/coverage"/>
|
||||
<text outputFile="output/coverage.txt" showUncoveredFiles="true" showOnlySummary="true"/>
|
||||
</report>
|
||||
</coverage>
|
||||
</phpunit>
|
25
phpunit.xml
25
phpunit.xml
@ -1,11 +1,24 @@
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
|
||||
>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.2/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false" displayDetailsOnTestsThatTriggerWarnings="true">
|
||||
<testsuites>
|
||||
<testsuite name="All">
|
||||
<directory>tests</directory>
|
||||
<testsuite name="Backupscript Test Suite">
|
||||
<directory>./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory suffix=".php">src/</directory>
|
||||
</include>
|
||||
</source>
|
||||
<logging>
|
||||
<junit outputFile="output/test/junit.xml"/>
|
||||
<testdoxHtml outputFile="output/test/index.html"/>
|
||||
</logging>
|
||||
|
||||
<coverage>
|
||||
<report>
|
||||
<html outputDirectory="output/coverage" />
|
||||
<clover outputFile ="output/coverage/clover.xml" />
|
||||
</report>
|
||||
</coverage>
|
||||
</phpunit>
|
@ -6,7 +6,7 @@
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="true"
|
||||
findUnusedCode="false"
|
||||
strictBinaryOperands="true"
|
||||
checkForThrowsInGlobalScope="true"
|
||||
ignoreInternalFunctionFalseReturn="false"
|
||||
@ -18,5 +18,9 @@
|
||||
<projectFiles>
|
||||
<directory name="src/" />
|
||||
<file name="backup" />
|
||||
<directory name="tests" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
</psalm>
|
||||
|
10
src/App.php
10
src/App.php
@ -26,6 +26,7 @@ class App
|
||||
* Create a new instance providing a config file.
|
||||
*
|
||||
* @param string $configFile Relative or full path to YML config.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.StaticAccess)
|
||||
*/
|
||||
public function __construct(string $configFile)
|
||||
@ -60,7 +61,9 @@ class App
|
||||
]);
|
||||
|
||||
$parser = new Yaml();
|
||||
/** @var array<string, mixed> */
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
$parsedConfig = $parser->parseFile($configFile);
|
||||
|
||||
// Merge those values into the configuration schema:
|
||||
@ -80,11 +83,14 @@ class App
|
||||
* Get configuration from key
|
||||
*
|
||||
* @param non-empty-string $key Key to fetch
|
||||
*
|
||||
* @return mixed Configuration value
|
||||
*/
|
||||
public function getConfig(string $key): mixed
|
||||
{
|
||||
/** @var string|array<string, string> */
|
||||
/**
|
||||
* @var string|array<string, string>
|
||||
*/
|
||||
$ret = $this->config->get($key);
|
||||
$this->logger->debug("Fetching configuration key", [$key, $ret]);
|
||||
return $ret;
|
||||
|
@ -65,19 +65,25 @@ class CommandBackup extends Command
|
||||
$rclone = new Rclone($app->getLogger()->withName('rclone'), (string)$app->getConfig('rclone.path'));
|
||||
|
||||
$notification = new Notification();
|
||||
/** @var array<array-key,array<string,string>> */
|
||||
/**
|
||||
* @var array<array-key,array<string,string>>
|
||||
*/
|
||||
$notificationConfig = $app->getConfig('notification');
|
||||
$notification->loadMany($notificationConfig);
|
||||
|
||||
/** @var array<string,string> */
|
||||
/**
|
||||
* @var array<string,string>
|
||||
*/
|
||||
$templateConfig = $app->getConfig('templates');
|
||||
$render = new Twig($templateConfig);
|
||||
|
||||
/** @var array{title: string, source: string, destination: string}[] */
|
||||
/**
|
||||
* @var array{title: string, source: string, destination: string}[]
|
||||
*/
|
||||
$backupElements = $app->getConfig('backup');
|
||||
foreach ($sioProgressbar->progressIterate($backupElements) as $conf) {
|
||||
$title = $conf['title'];
|
||||
$template = array();
|
||||
$template = [];
|
||||
$template['config'] = $conf;
|
||||
try {
|
||||
$template['start'] = new DateTime();
|
||||
@ -85,7 +91,9 @@ class CommandBackup extends Command
|
||||
$template['rclone_version'] = $rclone->getVersion();
|
||||
$template['destination_size_before'] = $rclone->getSize($conf['destination']);
|
||||
|
||||
/** @var array<array-key, string> */
|
||||
/**
|
||||
* @var array<array-key, string>
|
||||
*/
|
||||
$rcloneOptions = $app->getConfig('rclone.options');
|
||||
$rclone->copy($conf['source'], $conf['destination'], $rcloneOptions);
|
||||
|
||||
|
@ -42,7 +42,9 @@ class CommandShow extends Command
|
||||
$sio->error('Configuration error: ' . $e->getMessage());
|
||||
return Command::FAILURE;
|
||||
}
|
||||
/** @var array{title: string, source: string, destination: string}[] */
|
||||
/**
|
||||
* @var array{title: string, source: string, destination: string}[]
|
||||
*/
|
||||
$backupElements = $app->getConfig('backup');
|
||||
$sio->table(
|
||||
['Description', 'Source', 'Destination'],
|
||||
|
@ -12,7 +12,7 @@ class Notification
|
||||
/**
|
||||
* @var NotificationInterface[] $notifiers
|
||||
*/
|
||||
private array $notifiers = array();
|
||||
private array $notifiers = [];
|
||||
|
||||
public function __construct(private NullLogger $logger = new NullLogger())
|
||||
{
|
||||
@ -35,6 +35,7 @@ class Notification
|
||||
*
|
||||
* @param string $key Notification class
|
||||
* @param string[] $config Implementation specific configuration
|
||||
*
|
||||
* @SuppressWarnings(PHPMD)
|
||||
*/
|
||||
public function loadSingle(string $key, array $config): void
|
||||
|
@ -35,9 +35,6 @@ class Ntfy implements NotificationInterface
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo The constructor should be private but static code analysis complains.
|
||||
*/
|
||||
public function __construct(private Client $client)
|
||||
{
|
||||
}
|
||||
|
@ -70,8 +70,10 @@ class Rclone
|
||||
throw new Exception($process->getErrorOutput());
|
||||
}
|
||||
|
||||
/** @var array{bytes: int} */
|
||||
$output = json_decode($process->getOutput(), true);
|
||||
/**
|
||||
* @var array{bytes: int}
|
||||
*/
|
||||
$output = json_decode($process->getOutput(), TRUE);
|
||||
return $output['bytes'];
|
||||
}
|
||||
|
||||
@ -82,9 +84,9 @@ class Rclone
|
||||
* @param $dest Destination mount and path
|
||||
* @param string[] $additionalOptions Additional options
|
||||
*/
|
||||
public function copy(string $src, string $dest, array $additionalOptions = array()): void
|
||||
public function copy(string $src, string $dest, array $additionalOptions = []): void
|
||||
{
|
||||
$options = array();
|
||||
$options = [];
|
||||
|
||||
$options[] = $src;
|
||||
$options[] = $dest;
|
||||
@ -108,7 +110,7 @@ class Rclone
|
||||
*
|
||||
* @return Process Instance.
|
||||
*/
|
||||
private function exec(string $command, array $options = array()): Process
|
||||
private function exec(string $command, array $options = []): Process
|
||||
{
|
||||
$process = new Process(
|
||||
array_merge(
|
||||
|
@ -22,9 +22,9 @@ class TwigExtension extends AbstractExtension
|
||||
*/
|
||||
public function getFilters(): array
|
||||
{
|
||||
return array(
|
||||
new TwigFilter('formatBytes', array($this, 'formatBytes')),
|
||||
);
|
||||
return [
|
||||
new TwigFilter('formatBytes', [$this, 'formatBytes']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,9 @@ use Exception;
|
||||
|
||||
final class NotificationTest extends TestCase
|
||||
{
|
||||
/** @var array<string, string> */
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private static array $config = ['type' => 'ntfy', 'domain' => 'https://test.com', 'topic' => 'testing'];
|
||||
|
||||
public function testloadSingle(): void
|
||||
|
@ -16,6 +16,12 @@ final class NtfyTest extends TestCase
|
||||
private Ntfy $instance;
|
||||
private MockObject $client;
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
parent::__construct($name);
|
||||
$this->setUp();
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->client = $this->createMock(Client::class);
|
||||
@ -45,7 +51,9 @@ final class NtfyTest extends TestCase
|
||||
$this->instance->send(str_repeat("t", Ntfy::TITLE_MAX_LENGTH), str_repeat("t", Ntfy::MESSAGE_MAX_LENGTH));
|
||||
}
|
||||
|
||||
/** @return array<int, array<int, string>> */
|
||||
/**
|
||||
* @return array<int, array<int, string>>
|
||||
*/
|
||||
public static function sendBadParameterProvider(): array
|
||||
{
|
||||
return [
|
||||
@ -75,7 +83,9 @@ final class NtfyTest extends TestCase
|
||||
$this->assertEquals($topic, $this->instance->getTopic());
|
||||
}
|
||||
|
||||
/** @return array<int, array<int, string>> */
|
||||
/**
|
||||
* @return array<int, array<int, string>>
|
||||
*/
|
||||
public static function topicBadParameterProvider(): array
|
||||
{
|
||||
return [
|
||||
|
Reference in New Issue
Block a user