Add IBAN validator with QA workflows
PHP_CodeSniffer / PHP_CodeSniffer (push) Successful in 1m34s
PHPStan / PHPStan with PHP 8.5 prefer-lowest (push) Successful in 1m42s
PHPStan / PHPStan with PHP 8.1 prefer-stable (push) Successful in 1m56s
PHPStan / PHPStan with PHP 8.1 prefer-lowest (push) Successful in 1m56s
PHPStan / PHPStan with PHP 8.5 prefer-stable (push) Successful in 55s
PHPStan / PHPStan with PHP 8.6 prefer-source (push) Successful in 1m0s
PHPUnit / PHPUnit with PHP 8.1 prefer-lowest (push) Successful in 1m19s
PHPUnit / PHPUnit with PHP 8.1 prefer-stable (push) Successful in 1m23s
PHPUnit / PHPUnit with PHP 8.5 prefer-lowest (push) Successful in 55s
Smoke / Produce an output (push) Successful in 17s
PHPUnit / PHPUnit with PHP 8.5 prefer-stable (push) Successful in 57s
Smoke / Consume the output (push) Successful in 13s
PHPUnit / PHPUnit with PHP 8.6 prefer-source (push) Successful in 53s

This commit is contained in:
Christian Todt
2026-09-16 14:22:55 +02:00
commit 1295f234e4
15 changed files with 900 additions and 0 deletions
+262
View File
@@ -0,0 +1,262 @@
# Do not search in parent directories.
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120
tab_width = 2
ij_continuation_indent_size = 2
ij_visual_guides = 80,120
[composer.{json,lock}]
indent_size = 4
[{*.php}]
ij_php_align_assignments = false
ij_php_align_class_constants = false
ij_php_align_enum_cases = false
ij_php_align_group_field_declarations = false
ij_php_align_inline_comments = false
ij_php_align_key_value_pairs = false
ij_php_align_match_arm_bodies = false
ij_php_align_multiline_array_initializer_expression = false
ij_php_align_multiline_binary_operation = false
ij_php_align_multiline_chained_methods = false
ij_php_align_multiline_extends_list = false
ij_php_align_multiline_for = true
ij_php_align_multiline_parameters = false
ij_php_align_multiline_parameters_in_calls = false
ij_php_align_multiline_ternary_operation = false
ij_php_align_named_arguments = false
ij_php_align_phpdoc_comments = false
ij_php_align_phpdoc_param_names = false
ij_php_anonymous_brace_style = end_of_line
ij_php_api_weight = 28
ij_php_array_initializer_new_line_after_left_brace = true
ij_php_array_initializer_right_brace_on_new_line = true
ij_php_array_initializer_wrap = on_every_item
ij_php_assignment_wrap = normal
ij_php_attributes_wrap = normal
ij_php_author_weight = 28
ij_php_binary_operation_sign_on_next_line = false
ij_php_binary_operation_wrap = normal
ij_php_blank_lines_after_class_header = 1
ij_php_blank_lines_after_function = 1
ij_php_blank_lines_after_imports = 1
ij_php_blank_lines_after_opening_tag = 0
ij_php_blank_lines_after_package = 1
ij_php_blank_lines_around_class = 1
ij_php_blank_lines_around_constants = 1
ij_php_blank_lines_around_enum_cases = 0
ij_php_blank_lines_around_field = 1
ij_php_blank_lines_around_method = 1
ij_php_blank_lines_before_class_end = 1
ij_php_blank_lines_before_imports = 1
ij_php_blank_lines_before_method_body = 0
ij_php_blank_lines_before_package = 1
ij_php_blank_lines_before_return_statement = 1
ij_php_blank_lines_between_imports = 0
ij_php_block_brace_style = end_of_line
ij_php_call_parameters_new_line_after_left_paren = true
ij_php_call_parameters_right_paren_on_new_line = true
ij_php_call_parameters_wrap = on_every_item
ij_php_catch_on_new_line = true
ij_php_category_weight = 28
ij_php_class_brace_style = end_of_line
ij_php_comma_after_last_argument = false
ij_php_comma_after_last_array_element = true
ij_php_comma_after_last_closure_use_var = false
ij_php_comma_after_last_match_arm = false
ij_php_comma_after_last_parameter = false
ij_php_concat_spaces = true
ij_php_copyright_weight = 28
ij_php_deprecated_weight = 4
ij_php_do_while_brace_force = always
ij_php_else_if_style = as_is
ij_php_else_on_new_line = true
ij_php_example_weight = 28
ij_php_extends_keyword_wrap = off
ij_php_extends_list_wrap = off
ij_php_fields_default_visibility = private
ij_php_filesource_weight = 28
ij_php_finally_on_new_line = true
ij_php_for_brace_force = always
ij_php_for_statement_new_line_after_left_paren = false
ij_php_for_statement_right_paren_on_new_line = false
ij_php_for_statement_wrap = off
ij_php_force_empty_methods_in_one_line = false
ij_php_force_short_declaration_array_style = true
ij_php_getters_setters_naming_style = camel_case
ij_php_getters_setters_order_style = getters_first
ij_php_global_weight = 28
ij_php_group_use_wrap = on_every_item
ij_php_if_brace_force = always
ij_php_if_lparen_on_next_line = false
ij_php_if_rparen_on_next_line = false
ij_php_ignore_weight = 28
ij_php_import_sorting = alphabetic
ij_php_indent_break_from_case = true
ij_php_indent_case_from_switch = true
ij_php_indent_code_in_php_tags = false
ij_php_internal_weight = 28
ij_php_keep_blank_lines_after_lbrace = 1
ij_php_keep_blank_lines_before_right_brace = 1
ij_php_keep_blank_lines_in_code = 1
ij_php_keep_blank_lines_in_declarations = 1
ij_php_keep_control_statement_in_one_line = false
ij_php_keep_first_column_comment = false
ij_php_keep_indents_on_empty_lines = false
ij_php_keep_line_breaks = false
ij_php_keep_rparen_and_lbrace_on_one_line = true
ij_php_keep_simple_classes_in_one_line = false
ij_php_keep_simple_methods_in_one_line = false
ij_php_lambda_brace_style = end_of_line
ij_php_license_weight = 28
ij_php_line_comment_add_space = false
ij_php_line_comment_at_first_column = true
ij_php_link_weight = 28
ij_php_lower_case_boolean_const = false
ij_php_lower_case_keywords = true
ij_php_lower_case_null_const = false
ij_php_method_brace_style = end_of_line
ij_php_method_call_chain_wrap = on_every_item
ij_php_method_parameters_new_line_after_left_paren = true
ij_php_method_parameters_right_paren_on_new_line = true
ij_php_method_parameters_wrap = on_every_item
ij_php_method_weight = 28
ij_php_modifier_list_wrap = false
ij_php_multiline_chained_calls_semicolon_on_new_line = true
ij_php_namespace_brace_style = 1
ij_php_new_line_after_php_opening_tag = true
ij_php_null_type_position = in_the_end
ij_php_package_weight = 28
ij_php_param_weight = 1
ij_php_parameters_attributes_wrap = normal
ij_php_parentheses_expression_new_line_after_left_paren = false
ij_php_parentheses_expression_right_paren_on_new_line = false
ij_php_phpdoc_blank_line_before_tags = true
ij_php_phpdoc_blank_lines_around_parameters = true
ij_php_phpdoc_keep_blank_lines = true
ij_php_phpdoc_param_spaces_between_name_and_description = 1
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
ij_php_phpdoc_param_spaces_between_type_and_name = 1
ij_php_phpdoc_use_fqcn = true
ij_php_phpdoc_wrap_long_lines = true
ij_php_place_assignment_sign_on_next_line = false
ij_php_place_parens_for_constructor = 1
ij_php_property_read_weight = 28
ij_php_property_weight = 28
ij_php_property_write_weight = 28
ij_php_return_type_on_new_line = false
ij_php_return_weight = 2
ij_php_see_weight = 5
ij_php_since_weight = 28
ij_php_sort_phpdoc_elements = true
ij_php_space_after_colon = true
ij_php_space_after_colon_in_enum_backed_type = true
ij_php_space_after_colon_in_named_argument = true
ij_php_space_after_colon_in_return_type = true
ij_php_space_after_comma = true
ij_php_space_after_for_semicolon = true
ij_php_space_after_quest = true
ij_php_space_after_type_cast = true
ij_php_space_after_unary_not = false
ij_php_space_before_array_initializer_left_brace = false
ij_php_space_before_catch_keyword = true
ij_php_space_before_catch_left_brace = true
ij_php_space_before_catch_parentheses = true
ij_php_space_before_class_left_brace = true
ij_php_space_before_closure_left_parenthesis = true
ij_php_space_before_colon = true
ij_php_space_before_colon_in_enum_backed_type = false
ij_php_space_before_colon_in_named_argument = false
ij_php_space_before_colon_in_return_type = false
ij_php_space_before_comma = false
ij_php_space_before_do_left_brace = true
ij_php_space_before_else_keyword = true
ij_php_space_before_else_left_brace = true
ij_php_space_before_finally_keyword = true
ij_php_space_before_finally_left_brace = true
ij_php_space_before_for_left_brace = true
ij_php_space_before_for_parentheses = true
ij_php_space_before_for_semicolon = false
ij_php_space_before_if_left_brace = true
ij_php_space_before_if_parentheses = true
ij_php_space_before_method_call_parentheses = false
ij_php_space_before_method_left_brace = true
ij_php_space_before_method_parentheses = false
ij_php_space_before_quest = true
ij_php_space_before_short_closure_left_parenthesis = false
ij_php_space_before_switch_left_brace = true
ij_php_space_before_switch_parentheses = true
ij_php_space_before_try_left_brace = true
ij_php_space_before_unary_not = false
ij_php_space_before_while_keyword = true
ij_php_space_before_while_left_brace = true
ij_php_space_before_while_parentheses = true
ij_php_space_between_ternary_quest_and_colon = false
ij_php_spaces_around_additive_operators = true
ij_php_spaces_around_arrow = false
ij_php_spaces_around_assignment_in_declare = true
ij_php_spaces_around_assignment_operators = true
ij_php_spaces_around_bitwise_operators = true
ij_php_spaces_around_equality_operators = true
ij_php_spaces_around_logical_operators = true
ij_php_spaces_around_multiplicative_operators = true
ij_php_spaces_around_null_coalesce_operator = true
ij_php_spaces_around_pipe_in_union_type = false
ij_php_spaces_around_relational_operators = true
ij_php_spaces_around_shift_operators = true
ij_php_spaces_around_unary_operator = false
ij_php_spaces_around_var_within_brackets = false
ij_php_spaces_within_array_initializer_braces = false
ij_php_spaces_within_brackets = false
ij_php_spaces_within_catch_parentheses = false
ij_php_spaces_within_for_parentheses = false
ij_php_spaces_within_if_parentheses = false
ij_php_spaces_within_method_call_parentheses = false
ij_php_spaces_within_method_parentheses = false
ij_php_spaces_within_parentheses = false
ij_php_spaces_within_short_echo_tags = true
ij_php_spaces_within_switch_parentheses = false
ij_php_spaces_within_while_parentheses = false
ij_php_special_else_if_treatment = false
ij_php_subpackage_weight = 28
ij_php_ternary_operation_signs_on_next_line = true
ij_php_ternary_operation_wrap = on_every_item
ij_php_throws_weight = 3
ij_php_todo_weight = 6
ij_php_treat_multiline_arrays_and_lambdas_multiline = false
ij_php_unknown_tag_weight = 28
ij_php_upper_case_boolean_const = true
ij_php_upper_case_null_const = true
ij_php_uses_weight = 28
ij_php_var_weight = 0
ij_php_variable_naming_style = camel_case
ij_php_version_weight = 28
ij_php_while_brace_force = always
ij_php_while_on_new_line = false
[{*.neon,*.neon.dist,*neon.template}]
indent_style = tab
tab_width = 4
[{*.yaml,*.yml}]
ij_yaml_align_values_properties = do_not_align
ij_yaml_autoinsert_sequence_marker = true
ij_yaml_block_mapping_on_new_line = false
ij_yaml_indent_sequence_value = true
ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true
ij_yaml_line_comment_add_space = false
ij_yaml_line_comment_add_space_on_reformat = false
ij_yaml_line_comment_at_first_column = false
ij_yaml_sequence_on_new_line = false
ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true
+55
View File
@@ -0,0 +1,55 @@
name: PHP_CodeSniffer
permissions: {}
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
paths:
- '**.php'
- tools/phpcs/composer.json
- phpcs.xml.dist
- .github/workflows/phpcs.yml
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
phpcs:
runs-on: ubuntu-latest
name: PHP_CodeSniffer
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: 8.5
coverage: none
tools: cs2pr
env:
fail-fast: true
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('tools/phpcs/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer composer-phpcs -- update --no-progress --prefer-dist
- name: Run PHP_CodeSniffer
run: composer phpcs -- -q --report=checkstyle | cs2pr
+83
View File
@@ -0,0 +1,83 @@
name: PHPStan
permissions: {}
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
paths:
- '**.php'
- composer.json
- tools/phpstan/composer.json
- phpstan.neon.dist
- .github/workflows/phpstan.yml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
phpstan:
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
php-versions: ['8.1', '8.5']
prefer: ['prefer-stable', 'prefer-lowest']
experimental: [false]
include:
- php-versions: 8.6
prefer: prefer-source
experimental: true
name: PHPStan with PHP ${{ matrix.php-versions }} ${{ matrix.prefer }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: ${{ matrix.php-versions }}
coverage: none
env:
fail-fast: true
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.prefer }}-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-${{ matrix.prefer }}-
- name: Install dependencies
env:
MATRIX_EXPERIMENTAL: ${{ matrix.experimental }}
MATRIX_PREFER: ${{ matrix.prefer }}
run: |
if [ "${MATRIX_PREFER}" = "prefer-lowest" ]; then
export COMPOSER_NO_BLOCKING=1
fi
if [ "${MATRIX_EXPERIMENTAL}" == "true" ]; then
sed -E -i composer.json \
-e 's/"minimum-stability":[^,]*/"minimum-stability": "dev"/' \
-e 's/"prefer-stable":[^,]*/"prefer-stable": false/'
export COMPOSER_IGNORE_PLATFORM_REQ="php+"
fi
composer update --no-progress --${MATRIX_PREFER} --optimize-autoloader
composer composer-phpunit -- update --no-progress --optimize-autoloader
composer composer-phpstan -- update --no-progress --optimize-autoloader
- name: Run PHPStan
run: composer phpstan -- analyse
+93
View File
@@ -0,0 +1,93 @@
name: PHPUnit
permissions: {}
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
paths:
- '**.php'
- composer.json
- tools/phpunit/composer.json
- phpunit.xml.dist
- .github/workflows/phpunit.yml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
phpunit:
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
php-versions: ['8.1', '8.5']
prefer: ['prefer-stable', 'prefer-lowest']
experimental: [false]
include:
- php-versions: 8.6
prefer: prefer-source
experimental: true
name: PHPUnit with PHP ${{ matrix.php-versions }} ${{ matrix.prefer }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: ${{ matrix.php-versions }}
extensions: bcmath, curl, fileinfo, gd, intl, mbstring, mysqli, xml, zip
coverage: pcov
env:
fail-fast: true
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.prefer }}-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-${{ matrix.prefer }}-
- name: Install dependencies
env:
MATRIX_EXPERIMENTAL: ${{ matrix.experimental }}
MATRIX_PREFER: ${{ matrix.prefer }}
run: |
if [ "${MATRIX_PREFER}" = "prefer-lowest" ]; then
export COMPOSER_NO_BLOCKING=1
fi
if [ "${MATRIX_EXPERIMENTAL}" == "true" ]; then
sed -E -i composer.json \
-e 's/"minimum-stability":[^,]*/"minimum-stability": "dev"/' \
-e 's/"prefer-stable":[^,]*/"prefer-stable": false/'
export COMPOSER_IGNORE_PLATFORM_REQ="php+"
fi
composer update --no-progress --${MATRIX_PREFER} --optimize-autoloader
composer composer-phpunit -- update --no-progress --optimize-autoloader
- name: Setup problem matchers for PHP
env:
RUNNER_TOOL_CACHE: ${{ runner.tool_cache }}
run: echo "::add-matcher::${RUNNER_TOOL_CACHE}/php.json"
- name: Setup problem matchers for PHPUnit
env:
RUNNER_TOOL_CACHE: ${{ runner.tool_cache }}
run: echo "::add-matcher::${RUNNER_TOOL_CACHE}/phpunit.json"
- name: Run PHPUnit
run: composer phpunit
+54
View File
@@ -0,0 +1,54 @@
name: Smoke
permissions: {}
on:
workflow_dispatch:
inputs:
greeting:
description: 'Text passed from the first job to the second'
required: false
type: string
default: hello
push:
branches:
- main
jobs:
produce:
runs-on: ubuntu-latest
name: Produce an output
outputs:
greeting: ${{ steps.greeting.outputs.value }}
steps:
- name: Show the runner
run: |
uname -a
cat /etc/os-release
id
echo "event=${GITHUB_EVENT_NAME} ref=${GITHUB_REF} sha=${GITHUB_SHA}"
echo "server=${GITHUB_SERVER_URL} repository=${GITHUB_REPOSITORY}"
command -v sudo docker node php composer || true
- name: Set the output
id: greeting
env:
INPUTS_GREETING: ${{ inputs.greeting || 'hello' }}
run: echo "value=${INPUTS_GREETING} from ${GITHUB_REPOSITORY}" >> $GITHUB_OUTPUT
- name: Write the step summary
run: echo "### Smoke test ran on ${RUNNER_OS}" >> $GITHUB_STEP_SUMMARY
consume:
runs-on: ubuntu-latest
name: Consume the output
needs: produce
steps:
- name: Print the output of the first job
env:
GREETING: ${{ needs.produce.outputs.greeting }}
run: |
test -n "${GREETING}"
echo "${GREETING}"
+8
View File
@@ -0,0 +1,8 @@
/.phpcs.cache
/.phpunit.result.cache
/.phpstan/
/composer.lock
/phpstan.neon
/tools/*/vendor/
/tools/*/composer.lock
/vendor/
+64
View File
@@ -0,0 +1,64 @@
{
"name": "systopia/pipelinetest",
"description": "Test project for GitHub workflows on Gitea Actions",
"type": "library",
"license": "AGPL-3.0-or-later",
"authors": [
{
"name": "SYSTOPIA GmbH",
"email": "info@systopia.de",
"homepage": "https://www.systopia.de"
}
],
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"sort-packages": true
},
"require": {
"php": "^8.1"
},
"autoload": {
"psr-4": {
"Systopia\\PipelineTest\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Systopia\\PipelineTest\\": "tests/"
}
},
"scripts": {
"composer-phpcs": [
"@composer --working-dir=tools/phpcs"
],
"composer-phpstan": [
"@composer --working-dir=tools/phpstan"
],
"composer-phpunit": [
"@composer --working-dir=tools/phpunit"
],
"composer-tools": [
"@composer-phpcs",
"@composer-phpstan",
"@composer-phpunit"
],
"phpcs": [
"@php tools/phpcs/vendor/bin/phpcs"
],
"phpcbf": [
"@php tools/phpcs/vendor/bin/phpcbf"
],
"phpstan": [
"@php tools/phpstan/vendor/bin/phpstan -v"
],
"phpunit": [
"@php tools/phpunit/vendor/bin/simple-phpunit --coverage-text"
],
"test": [
"@phpcs",
"@phpstan",
"@phpunit"
]
}
}
+78
View File
@@ -0,0 +1,78 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="CiviCRM - Modified"
xsi:noNamespaceSchemaLocation="tools/phpcs/vendor/squizlabs/php_codesniffer/phpcs.xsd">
<description>CiviCRM coding standard with some additional changes</description>
<file>src</file>
<file>tests</file>
<arg name="extensions" value="php"/>
<arg name="cache" value=".phpcs.cache"/>
<arg name="colors"/>
<arg value="sp"/>
<!-- Exit with code 0 if warnings, but no error occurred -->
<config name="ignore_warnings_on_exit" value="true"/>
<rule ref="tools/phpcs/vendor/drupal/coder/coder_sniffer/Drupal">
<!-- Conflicts with PHPStan type hints -->
<exclude name="Drupal.Commenting.VariableComment.IncorrectVarType"/>
<exclude name="Drupal.Commenting.FunctionComment.ParamTypeSpaces"/>
<exclude name="Drupal.Commenting.FunctionComment.ReturnTypeSpaces"/>
<!-- Don't enforce phpdoc type hint because it (might) only duplicate a PHP type hint -->
<exclude name="Drupal.Commenting.VariableComment.MissingVar"/>
<!-- Don't enforce phpdoc type hint because it (might) only duplicate a PHP type hint -->
<exclude name="Drupal.Commenting.FunctionComment.ParamMissingDefinition"/>
<!-- False positive when license header is set and variable has no comment -->
<exclude name="Drupal.Commenting.VariableComment.WrongStyle"/>
</rule>
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
<rule ref="Generic.CodeAnalysis.EmptyStatement">
<exclude name="Generic.CodeAnalysis.EmptyStatement.DetectedCatch"/>
</rule>
<rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
<rule ref="Generic.Files.OneClassPerFile"/>
<rule ref="Generic.Files.OneInterfacePerFile"/>
<rule ref="Generic.Files.OneObjectStructurePerFile"/>
<rule ref="Generic.Files.OneTraitPerFile"/>
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
<rule ref="Generic.Metrics.CyclomaticComplexity"/>
<rule ref="Generic.Metrics.NestingLevel"/>
<rule ref="Generic.NamingConventions.AbstractClassNamePrefix"/>
<rule ref="Generic.NamingConventions.InterfaceNameSuffix"/>
<rule ref="Generic.NamingConventions.TraitNameSuffix"/>
<rule ref="Generic.PHP.RequireStrictTypes"/>
<rule ref="PSR1.Files.SideEffects"/>
<rule ref="PSR12.Classes.ClassInstantiation"/>
<rule ref="PSR12.Properties.ConstantVisibility"/>
<rule ref="Squiz.PHP.CommentedOutCode"/>
<rule ref="Squiz.PHP.GlobalKeyword"/>
<rule ref="Squiz.Strings.DoubleQuoteUsage">
<exclude name="Squiz.Strings.DoubleQuoteUsage.ContainsVar"/>
</rule>
<!-- Lines can be 120 chars long, but never show errors -->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="120"/>
<property name="absoluteLineLimit" value="0"/>
</properties>
</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>
+24
View File
@@ -0,0 +1,24 @@
parameters:
paths:
- src
- tests
scanFiles:
- tools/phpunit/vendor/bin/.phpunit/phpunit/src/Framework/TestCase.php
scanDirectories:
- tools/phpunit/vendor/bin/.phpunit/phpunit/src/Framework
bootstrapFiles:
- tools/phpunit/vendor/bin/.phpunit/phpunit/vendor/autoload.php
- vendor/autoload.php
level: 9
checkTooWideReturnTypesInProtectedAndPublicMethods: true
checkUninitializedProperties: true
checkMissingCallableSignature: true
treatPhpDocTypesAsCertain: false
exceptions:
check:
missingCheckedExceptionInThrows: true
tooWideThrowType: true
checkedExceptionClasses:
- \Webmozart\Assert\InvalidArgumentException
implicitThrows: false
tmpDir: .phpstan
+27
View File
@@ -0,0 +1,27 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
colors="true"
failOnRisky="true"
failOnWarning="true"
forceCoversAnnotation="true"
bootstrap="vendor/autoload.php">
<php>
<ini name="error_reporting" value="-1"/>
<env name="SYMFONY_DEPRECATIONS_HELPER" value="max[direct]=0"/>
</php>
<testsuites>
<testsuite name="pipelinetest Test Suite">
<directory>./tests</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
</phpunit>
+51
View File
@@ -0,0 +1,51 @@
<?php
declare(strict_types = 1);
namespace Systopia\PipelineTest;
final class IbanValidator {
private const LENGTHS = [
'AT' => 20,
'BE' => 16,
'CH' => 21,
'DE' => 22,
'ES' => 24,
'FR' => 27,
'IT' => 27,
'LU' => 20,
'NL' => 18,
];
public function isValid(string $iban): bool {
$normalized = $this->normalize($iban);
if (1 !== preg_match('/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/', $normalized)) {
return FALSE;
}
if (strlen($normalized) !== (self::LENGTHS[substr($normalized, 0, 2)] ?? NULL)) {
return FALSE;
}
return 1 === $this->mod97(substr($normalized, 4) . substr($normalized, 0, 4));
}
public function normalize(string $iban): string {
return strtoupper(str_replace([' ', '-'], '', $iban));
}
private function mod97(string $rearranged): int {
$remainder = 0;
foreach (str_split($rearranged) as $character) {
$digits = ctype_digit($character) ? $character : (string) (ord($character) - 55);
foreach (str_split($digits) as $digit) {
$remainder = ($remainder * 10 + (int) $digit) % 97;
}
}
return $remainder;
}
}
+58
View File
@@ -0,0 +1,58 @@
<?php
declare(strict_types = 1);
namespace Systopia\PipelineTest;
use PHPUnit\Framework\TestCase;
/**
* @covers \Systopia\PipelineTest\IbanValidator
*/
final class IbanValidatorTest extends TestCase {
/**
* @dataProvider validIbans
*/
public function testAValidIban(string $iban): void {
static::assertTrue((new IbanValidator())->isValid($iban));
}
/**
* @return array<string, array{0: string}>
*/
public static function validIbans(): array {
return [
'germany' => ['DE89370400440532013000'],
'grouped' => ['DE89 3704 0044 0532 0130 00'],
'lowercase' => ['de89370400440532013000'],
'austria' => ['AT611904300234573201'],
'netherlands with letters' => ['NL91ABNA0417164300'],
];
}
/**
* @dataProvider invalidIbans
*/
public function testAnInvalidIban(string $iban): void {
static::assertFalse((new IbanValidator())->isValid($iban));
}
/**
* @return array<string, array{0: string}>
*/
public static function invalidIbans(): array {
return [
'wrong checksum' => ['DE88370400440532013000'],
'too short' => ['DE8937040044053201300'],
'unknown country' => ['XX89370400440532013000'],
'invalid character' => ['DE89370400440532013!00'],
'empty' => [''],
];
}
public function testNormalizeStripsSeparatorsAndUppercases(): void {
static::assertSame('DE89370400440532013000', (new IbanValidator())->normalize(' de89 3704-0044 0532 0130 00 '));
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"repositories": [
{
"type": "git",
"url": "https://github.com/civicrm/coder.git"
}
],
"require": {
"drupal/coder": "dev-8.x-2.x-civi"
}
}
+19
View File
@@ -0,0 +1,19 @@
{
"require": {
"kcs/phpstan-strict-rules": "^2",
"phpstan/extension-installer": "^1.4",
"phpstan/phpstan": "^2",
"phpstan/phpstan-beberlei-assert": "^2",
"phpstan/phpstan-deprecation-rules": "^2",
"phpstan/phpstan-phpunit": "^2",
"phpstan/phpstan-strict-rules": "^2",
"phpstan/phpstan-webmozart-assert": "^2",
"voku/phpstan-rules": "^3.6"
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
},
"sort-packages": true
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"require": {
"symfony/phpunit-bridge": "^7"
},
"scripts": {
"post-install-cmd": [
"@php vendor/bin/simple-phpunit install --configuration ../../phpunit.xml.dist"
],
"post-update-cmd": [
"@php vendor/bin/simple-phpunit install --configuration ../../phpunit.xml.dist"
]
}
}