Skip to content

Commit

Permalink
Migrate to Matomo 4 & PHP7 (#10)
Browse files Browse the repository at this point in the history
* Bump version and requirements to PHP7

* Migrate tests to PHPUnit 8.x

* Migrate Translator to PHP7

* Migrate Validators to PHP7

* Add Github Actions for QA

* Add PHP-CS-Fixer, Infection, PHPStan & Psalm configs

* Require specific version of Infection

* Add timeout to Infection configuration

* Add xdebug to infection run step

* Remove infection for now

* Fix Psalm errors

* Fix PHP CS Fixer errors

* Fix PHP CS Fixer errors

* Fix PHPStan errors

* Fix PHPStan errors

* Turn off phpdoc_to_comment
  • Loading branch information
simivar authored Oct 11, 2020
1 parent 7fc65d9 commit 3d7bd90
Show file tree
Hide file tree
Showing 27 changed files with 341 additions and 140 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/quality-assurance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Quality Assurance

on: [push, pull_request]

jobs:
quality-assurance:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.2'
extensions: mbstring, intl
ini-values: post_max_size=256M, short_open_tag=On
coverage: xdebug
tools: php-cs-fixer, psalm, phpstan, infection:0.13.6, cs2pr

- name: Get composer cache directory
id: composercache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader

- name: Setup problem matchers for PHPUnit
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

- name: Run Tests
run: php vendor/bin/phpunit --coverage-text

- name: Run PHP CS Fixer
run: php-cs-fixer fix --dry-run --diff --allow-risky=yes --using-cache=no --config=.php_cs.dist --format=checkstyle | cs2pr

- name: Run PHPStan
run: phpstan analyse -c phpstan.neon

- name: Run Psalm
run: psalm --output-format=github
30 changes: 30 additions & 0 deletions .php_cs.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

$finder = PhpCsFixer\Finder::create()
->in(__DIR__);

return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules([
'@Symfony' => true,
'@PHP71Migration:risky' => true,
'concat_space' => ['spacing' => 'one'],
'psr0' => false,
'array_syntax' => ['syntax' => 'short'],
'class_definition' => ['multiLineExtendsEachSingleLine' => true],
'no_useless_else' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'phpdoc_add_missing_param_annotation' => ['only_untyped' => true],
'no_short_echo_tag' => true,
'list_syntax' => ['syntax' => 'short'],
'linebreak_after_opening_tag' => true,
'void_return' => false,
'phpdoc_summary' => false,
'multiline_whitespace_before_semicolons' => ['strategy' => 'new_line_for_chained_calls'],
'visibility_required' => ['property', 'method', 'const'],
'phpdoc_to_comment' => false,
])
->setCacheFile(__DIR__ . '/.php_cs.cache')
->setFinder($finder);
18 changes: 13 additions & 5 deletions PasswordPolicyEnforcer.php
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer;

use Piwik\Container\StaticContainer;
use Piwik\Plugin;
use Piwik\Plugins\PasswordPolicyEnforcer\Validators\ValidatorFactory;

/**
* @psalm-suppress UndefinedClass
* @phpstan-ignore-next-line
*/
class PasswordPolicyEnforcer extends Plugin
{
public function registerEvents() {
return array(
'UsersManager.checkPassword' => 'verifyPassword'
);
public function registerEvents(): array
{
return [
'UsersManager.checkPassword' => 'verifyPassword',
];
}

public function getFactory()
{
return StaticContainer::get(ValidatorFactory::class);
}

public function verifyPassword($password) {
public function verifyPassword($password): bool
{
$validators = $this->getFactory()->create(new SystemSettings());

return $validators->validate($password);
Expand Down
33 changes: 16 additions & 17 deletions SystemSettings.php
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer;

use Piwik\Piwik;
use Piwik\Settings\Setting;
use Piwik\Plugins\UsersManager\UsersManager;
use Piwik\Settings\FieldConfig;
use Piwik\Settings\Setting;
use Piwik\Validators\NumberRange;
use Piwik\Plugins\UsersManager\UsersManager;

/**
* Defines Settings for UserCountry.
*/
/** @psalm-suppress UndefinedClass **/
class SystemSettings extends \Piwik\Settings\Plugin\SystemSettings
{
/** @var Setting */
public $minLength;

/** @var Setting */
public $isOneUppercaseLetterRequired;

/** @var Setting */
public $isOneLowercaseLetterRequired;

/** @var Setting */
public $isOneNumberRequired;

/** @var Setting */
public $isOneSpecialCharacterRequired;

protected function init()
{
$this->title = Piwik::translate('PasswordPolicyEnforcer_PasswordPolicyConfiguration');

$this->minLength = $this->createMinLengthSetting();
$this->isOneUppercaseLetterRequired = $this->createRequireOneUppercaseLetterSetting();
$this->isOneLowercaseLetterRequired = $this->createRequireOneLowercaseLetterSetting();
$this->isOneNumberRequired = $this->createRequireOneNumberSetting();
$this->isOneSpecialCharacterRequired = $this->createRequireOneSpecialCharacterSetting();
}

private function createMinLengthSetting()
{
return $this->makeSetting('minLength', UsersManager::PASSWORD_MIN_LENGTH, FieldConfig::TYPE_INT, function (FieldConfig $field) {
Expand All @@ -48,7 +48,7 @@ private function createMinLengthSetting()
$field->validators[] = new NumberRange(UsersManager::PASSWORD_MIN_LENGTH, UsersManager::PASSWORD_MAX_LENGTH);
});
}

private function createRequireOneUppercaseLetterSetting()
{
return $this->makeSetting('requireOneUppercaseLetter', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
Expand All @@ -57,7 +57,7 @@ private function createRequireOneUppercaseLetterSetting()
$field->description = Piwik::translate('PasswordPolicyEnforcer_PasswordPolicyOneUppercaseLetterSettingDescription');
});
}

private function createRequireOneLowercaseLetterSetting()
{
return $this->makeSetting('requireOneLowercaseLetter', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
Expand All @@ -66,7 +66,7 @@ private function createRequireOneLowercaseLetterSetting()
$field->description = Piwik::translate('PasswordPolicyEnforcer_PasswordPolicyOneLowercaseLetterSettingDescription');
});
}

private function createRequireOneNumberSetting()
{
return $this->makeSetting('requireOneNumber', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
Expand All @@ -75,7 +75,7 @@ private function createRequireOneNumberSetting()
$field->description = Piwik::translate('PasswordPolicyEnforcer_PasswordPolicyOneNumberSettingDescription');
});
}

private function createRequireOneSpecialCharacterSetting()
{
return $this->makeSetting('requireOneSpecialCharacter', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
Expand All @@ -84,5 +84,4 @@ private function createRequireOneSpecialCharacterSetting()
$field->description = Piwik::translate('PasswordPolicyEnforcer_PasswordPolicyOneSpecialCharacterSettingDescription');
});
}

}
27 changes: 23 additions & 4 deletions Translator/Translator.php
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer;

use Piwik\Plugins\PasswordPolicyEnforcer\Translator\TranslatorInterface;
use Piwik\Translation\Translator as MatomoTranslator;

final class Translator implements TranslatorInterface
{
/** @var MatomoTranslator */
/**
* @psalm-suppress UndefinedDocblockClass
* @psalm-suppress PropertyNotSetInConstructor
* @phpstan-ignore-next-line
*
* @var MatomoTranslator
*/
private $translator;


/**
* @psalm-suppress UndefinedClass
* @phpstan-ignore-next-line
*/
public function __construct(MatomoTranslator $translator)
{
$this->translator = $translator;
}

public function translate($key, $params)
/**
* @param array<string|int> $params
*/
public function translate(string $key, array $params): string
{
/**
* @psalm-suppress UndefinedDocblockClass
* @phpstan-ignore-next-line
*/
return $this->translator->translate($key, $params);
}
}
}
7 changes: 6 additions & 1 deletion Translator/TranslatorInterface.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer\Translator;

interface TranslatorInterface
{
public function translate($key, $params);
/**
* @param array<string|int> $params
*/
public function translate(string $key, array $params): string;
}
5 changes: 3 additions & 2 deletions Validators/LowercaseLetterValidator.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<?php

namespace Piwik\Plugins\PasswordPolicyEnforcer\Validators;
declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer\Validators;

class LowercaseLetterValidator implements ValidatorInterface
{
public function validate($value)
public function validate(string $value): bool
{
if (!preg_match('/[a-z]/', $value)) {
throw new ValidationException('PasswordPolicyEnforcer_ExceptionInvalidPasswordLowercaseLetterRequired');
Expand Down
8 changes: 5 additions & 3 deletions Validators/MinimumLengthValidator.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer\Validators;

class MinimumLengthValidator implements ValidatorInterface
{
/** @var int */
private $minLength;

public function __construct($minLength = 6)
public function __construct(int $minLength = 6)
{
$this->minLength = (int) $minLength;
$this->minLength = $minLength;
}

public function validate($value)
public function validate(string $value): bool
{
if (mb_strlen($value) < $this->minLength) {
throw new ValidationException('UsersManager_ExceptionInvalidPassword', [$this->minLength]);
Expand Down
4 changes: 3 additions & 1 deletion Validators/NumberValidator.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer\Validators;

class NumberValidator implements ValidatorInterface
{
public function validate($value)
public function validate(string $value): bool
{
if (!preg_match('/[0-9]/', $value)) {
throw new ValidationException('PasswordPolicyEnforcer_ExceptionInvalidPasswordNumberRequired');
Expand Down
21 changes: 6 additions & 15 deletions Validators/PasswordValidator.php
Original file line number Diff line number Diff line change
@@ -1,40 +1,32 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer\Validators;

use Piwik\Plugins\PasswordPolicyEnforcer\Translator\TranslatorInterface;

class PasswordValidator implements ValidatorInterface
{
/** @var ValidatorInterface[] */
private $validators;
private $validators = [];

/** @var TranslatorInterface */
private $translator;

/**
* @param TranslatorInterface $translator
*/
public function __construct(TranslatorInterface $translator)
{
$this->translator = $translator;
}

/**
* @param ValidatorInterface $validator
*/
public function addValidator($validator)
public function addValidator(ValidatorInterface $validator): void
{
if (!($validator instanceof ValidatorInterface)) {
return;
}

$this->validators[get_class($validator)] = $validator;
}

public function validate($value)
public function validate(string $value): bool
{
$violations = array();
$violations = [];

foreach ($this->validators as $validator) {
try {
Expand All @@ -53,5 +45,4 @@ public function validate($value)

return true;
}

}
4 changes: 3 additions & 1 deletion Validators/SpecialCharacterValidator.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<?php

declare(strict_types=1);

namespace Piwik\Plugins\PasswordPolicyEnforcer\Validators;

class SpecialCharacterValidator implements ValidatorInterface
{
public function validate($value)
public function validate(string $value): bool
{
if (!preg_match('/[^a-zA-Z0-9]/', $value)) {
throw new ValidationException('PasswordPolicyEnforcer_ExceptionInvalidPasswordSpecialCharacterRequired');
Expand Down
Loading

0 comments on commit 3d7bd90

Please sign in to comment.