mirror of
https://github.com/ivuorinen/business-data-fetcher.git
synced 2026-03-17 22:00:49 +00:00
Compare commits
23 Commits
v1.0.0
...
faf0354967
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faf0354967 | ||
|
|
13b64a77fb | ||
|
|
5ed216871e | ||
|
|
ea3daeb23f | ||
| 150c466368 | |||
|
|
f025e1202d | ||
|
|
a03878345c | ||
|
|
ed7ed02359 | ||
|
|
f41ca45f8d | ||
|
|
2b3a8ddf5f | ||
|
|
9e3b051e29 | ||
| 889361eef4 | |||
|
|
57159e0678 | ||
|
|
f002004a04 | ||
|
|
687c21fa65 | ||
| e06f28ae2a | |||
| 2e08598832 | |||
| 344b130197 | |||
| 3e38a0ddac | |||
| 4b13802b54 | |||
| aa6786981a | |||
|
|
8771b14d2a | ||
| e30e50fc78 |
31
.claude/settings.json
Normal file
31
.claude/settings.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"PreToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Write|Edit",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "bash -c 'input=$(cat); fp=$(echo \"$input\" | jq -r \".tool_input.file_path\"); if [[ \"$fp\" == *composer.lock ]] || [[ \"$fp\" == vendor/* ]] || [[ \"$fp\" == */vendor/* ]]; then echo \"{\\\"decision\\\":\\\"deny\\\",\\\"reason\\\":\\\"Do not edit $fp directly\\\"}\" >&2; exit 2; fi'"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"PostToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Write|Edit",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "bash -c 'input=$(cat); fp=$(echo \"$input\" | jq -r \".tool_input.file_path\"); if [[ \"$fp\" == *.php ]]; then cd \"$CLAUDE_PROJECT_DIR\" && php vendor/bin/phpcbf --standard=PSR12 \"$fp\" 2>/dev/null; fi; true'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "bash -c 'input=$(cat); fp=$(echo \"$input\" | jq -r \".tool_input.file_path\"); if [[ \"$fp\" == *.php ]]; then cd \"$CLAUDE_PROJECT_DIR\" && composer phpstan 2>&1 | tail -5; fi; true'",
|
||||||
|
"timeout": 30
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
13
.claude/skills/check-quality/SKILL.md
Normal file
13
.claude/skills/check-quality/SKILL.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
name: check-quality
|
||||||
|
description: Run lint, phpstan, and tests in sequence, fix any issues found
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Run the full quality check pipeline:
|
||||||
|
1. `composer lint` — fix any PSR-12 violations with `composer lint-fix`
|
||||||
|
2. `composer phpstan` — fix any static analysis issues
|
||||||
|
3. `composer test` — fix any failing tests
|
||||||
|
|
||||||
|
After each step, if issues are found, fix them before proceeding to the next step.
|
||||||
|
Do not commit. Report results when done.
|
||||||
16
.claude/skills/gen-test/SKILL.md
Normal file
16
.claude/skills/gen-test/SKILL.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
name: gen-test
|
||||||
|
description: Generate a Pest test for a PHP class following project conventions
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Generate a Pest test file for the specified class.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
- Place tests in `tests/Unit/` mirroring the src/ structure
|
||||||
|
- Use Pest syntax (test(), expect(), describe())
|
||||||
|
- For DTOs: test construction with valid data, verify all readonly properties
|
||||||
|
- For traits: test each method the trait provides
|
||||||
|
- For clients: mock Guzzle responses, test Valinor hydration
|
||||||
|
- Follow existing test patterns in tests/Unit/
|
||||||
|
- Read existing tests first to match style
|
||||||
15
.claude/skills/new-dto/SKILL.md
Normal file
15
.claude/skills/new-dto/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
name: new-dto
|
||||||
|
description: Create a new final readonly DTO class with Valinor-compatible constructor
|
||||||
|
disable-model-invocation: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Create a new DTO class following project conventions:
|
||||||
|
- `final readonly class` with constructor promotion
|
||||||
|
- Place in `src/v1/Dto/` or `src/v3/Dto/` based on API version
|
||||||
|
- All properties as constructor-promoted readonly parameters
|
||||||
|
- Use appropriate PHP types (string, int, ?string for nullable)
|
||||||
|
- Apply relevant traits (HasSource, HasLanguage, etc.) if applicable
|
||||||
|
- Namespace: `Ivuorinen\BusinessDataFetcher\{v1|v3}\Dto`
|
||||||
|
- Generate a corresponding Pest test in tests/Unit/
|
||||||
|
- Read existing DTOs first to match style
|
||||||
28
.github/labels.yml
vendored
Normal file
28
.github/labels.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: bug
|
||||||
|
color: d73a4a
|
||||||
|
description: Something isn't working
|
||||||
|
|
||||||
|
- name: enhancement
|
||||||
|
color: a2eeef
|
||||||
|
description: New feature or request
|
||||||
|
|
||||||
|
- name: documentation
|
||||||
|
color: 0075ca
|
||||||
|
description: Improvements or additions to documentation
|
||||||
|
|
||||||
|
- name: dependencies
|
||||||
|
color: 0366d6
|
||||||
|
description: Pull requests that update a dependency file
|
||||||
|
|
||||||
|
- name: breaking-change
|
||||||
|
color: e11d48
|
||||||
|
description: Breaking change to public API
|
||||||
|
|
||||||
|
- name: maintenance
|
||||||
|
color: fbca04
|
||||||
|
description: Code maintenance and refactoring
|
||||||
|
|
||||||
|
- name: ci
|
||||||
|
color: 7057ff
|
||||||
|
description: Continuous integration and tooling
|
||||||
2
.github/renovate.json
vendored
2
.github/renovate.json
vendored
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": ["github>ivuorinen/.github:renovate-config"]
|
"extends": ["github>ivuorinen/renovate-config"]
|
||||||
}
|
}
|
||||||
|
|||||||
50
.github/workflows/composer.yml
vendored
50
.github/workflows/composer.yml
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
---
|
||||||
name: PHP Composer
|
name: PHP Composer
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@@ -12,28 +13,41 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
# pre-installed php from 7.4 to 8.3
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php-versions: ['8.2', '8.3', '8.4']
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Validate composer.json and composer.lock
|
- uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # 2.37.0
|
||||||
run: composer validate --strict
|
with:
|
||||||
|
php-version: ${{ matrix.php-versions }}
|
||||||
|
|
||||||
- name: Cache Composer packages
|
- name: Validate composer.json and composer.lock
|
||||||
id: composer-cache
|
run: composer validate --strict
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: vendor
|
|
||||||
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-php-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Cache Composer packages
|
||||||
run: composer install --prefer-dist --no-progress
|
id: composer-cache
|
||||||
|
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||||
|
with:
|
||||||
|
path: ~/.composer/cache
|
||||||
|
key: ${{ runner.os }}-composer-${{ matrix.php-versions }}-${{ hashFiles('**/composer.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-composer-${{ matrix.php-versions }}-
|
||||||
|
${{ runner.os }}-composer-
|
||||||
|
|
||||||
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
|
- name: Install dependencies
|
||||||
# Docs: https://getcomposer.org/doc/articles/scripts.md
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
# - name: Run test suite
|
- name: Run linting
|
||||||
# run: composer run-script test
|
run: composer lint
|
||||||
|
|
||||||
|
- name: Run static analysis
|
||||||
|
run: composer phpstan
|
||||||
|
|
||||||
|
- name: Run test suite
|
||||||
|
run: composer test
|
||||||
|
|||||||
17
.github/workflows/pr-lint.yml
vendored
17
.github/workflows/pr-lint.yml
vendored
@@ -2,12 +2,19 @@
|
|||||||
name: PR Lint
|
name: PR Lint
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
branches-ignore: [master, main]
|
|
||||||
# Remove the line above to run when pushing to master
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master, main]
|
branches: [master, main]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
SuperLinter:
|
lint:
|
||||||
uses: ivuorinen/.github/.github/workflows/pr-lint.yml@main
|
permissions:
|
||||||
|
contents: read
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
statuses: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- uses: ivuorinen/actions/pr-lint@1da3a0e79fcd7da6bed9ee1979f1449ba11f58f9 # v2026.03.14
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
14
.github/workflows/release-drafter.yml
vendored
14
.github/workflows/release-drafter.yml
vendored
@@ -1,10 +1,18 @@
|
|||||||
---
|
---
|
||||||
name: Release Drafter
|
name: Release Monthly
|
||||||
|
|
||||||
# yamllint disable-line rule:truthy
|
# yamllint disable-line rule:truthy
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Draft:
|
release:
|
||||||
uses: ivuorinen/.github/.github/workflows/sync-labels.yml@main
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: ivuorinen/actions/release-monthly@1da3a0e79fcd7da6bed9ee1979f1449ba11f58f9 # v2026.03.14
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
8
.github/workflows/stale.yml
vendored
8
.github/workflows/stale.yml
vendored
@@ -9,10 +9,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write # only for delete-branch option
|
contents: read
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
uses: ivuorinen/.github/.github/workflows/stale.yml@main
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: ivuorinen/actions/stale@1da3a0e79fcd7da6bed9ee1979f1449ba11f58f9 # v2026.03.14
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
8
.github/workflows/sync-labels.yml
vendored
8
.github/workflows/sync-labels.yml
vendored
@@ -18,4 +18,10 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
SyncLabels:
|
SyncLabels:
|
||||||
uses: ivuorinen/.github/.github/workflows/sync-labels.yml@main
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- uses: ivuorinen/actions/sync-labels@1da3a0e79fcd7da6bed9ee1979f1449ba11f58f9 # v2026.03.14
|
||||||
|
with:
|
||||||
|
labels: .github/labels.yml
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
124
.gitignore
vendored
124
.gitignore
vendored
@@ -1,90 +1,49 @@
|
|||||||
.php-cs-fixer.cache
|
# PHP / Composer
|
||||||
.php-cs-fixer.php
|
|
||||||
composer.phar
|
composer.phar
|
||||||
/vendor/
|
/vendor/
|
||||||
|
|
||||||
|
# PHP CS Fixer
|
||||||
|
.php-cs-fixer.cache
|
||||||
|
.php-cs-fixer.php
|
||||||
|
|
||||||
|
# PHPUnit / Pest
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
.phpunit.cache
|
.phpunit.cache
|
||||||
/app/phpunit.xml
|
|
||||||
/phpunit.xml
|
/phpunit.xml
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
/build/
|
/build/
|
||||||
logs
|
|
||||||
|
# Logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
# Environment
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
lib-cov
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
.nyc_output
|
|
||||||
.grunt
|
|
||||||
bower_components
|
|
||||||
.lock-wscript
|
|
||||||
build/Release
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
web_modules/
|
|
||||||
*.tsbuildinfo
|
|
||||||
.npm
|
|
||||||
.eslintcache
|
|
||||||
.stylelintcache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
.node_repl_history
|
|
||||||
*.tgz
|
|
||||||
.yarn-integrity
|
|
||||||
.env
|
.env
|
||||||
.env.development.local
|
.env*.local
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
# OS / Editor
|
||||||
.env.local
|
.DS_Store
|
||||||
.cache
|
|
||||||
.parcel-cache
|
|
||||||
.next
|
|
||||||
out
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
.cache/
|
|
||||||
.vuepress/dist
|
|
||||||
.temp
|
|
||||||
.docusaurus
|
|
||||||
.serverless/
|
|
||||||
.fusebox/
|
|
||||||
.dynamodb/
|
|
||||||
.tern-port
|
|
||||||
.vscode-test
|
|
||||||
.yarn/cache
|
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
|
||||||
.yarn/install-state.gz
|
|
||||||
.pnp.*
|
|
||||||
[._]*.s[a-v][a-z]
|
[._]*.s[a-v][a-z]
|
||||||
!*.svg # comment out if you don't need vector files
|
!*.svg
|
||||||
[._]*.sw[a-p]
|
[._]*.sw[a-p]
|
||||||
[._]s[a-rt-v][a-z]
|
[._]s[a-rt-v][a-z]
|
||||||
[._]ss[a-gi-z]
|
[._]ss[a-gi-z]
|
||||||
[._]sw[a-p]
|
[._]sw[a-p]
|
||||||
|
*~
|
||||||
|
[._]*.un~
|
||||||
|
|
||||||
|
# Vim
|
||||||
Session.vim
|
Session.vim
|
||||||
Sessionx.vim
|
Sessionx.vim
|
||||||
.netrwhist
|
.netrwhist
|
||||||
*~
|
|
||||||
tags
|
tags
|
||||||
[._]*.un~
|
|
||||||
|
# JetBrains (PHPStorm)
|
||||||
.idea/**/workspace.xml
|
.idea/**/workspace.xml
|
||||||
.idea/**/tasks.xml
|
.idea/**/tasks.xml
|
||||||
.idea/**/usage.statistics.xml
|
.idea/**/usage.statistics.xml
|
||||||
.idea/**/dictionaries
|
.idea/**/dictionaries
|
||||||
.idea/**/shelf
|
.idea/**/shelf
|
||||||
.idea/**/aws.xml
|
|
||||||
.idea/**/contentModel.xml
|
|
||||||
.idea/**/dataSources/
|
.idea/**/dataSources/
|
||||||
.idea/**/dataSources.ids
|
.idea/**/dataSources.ids
|
||||||
.idea/**/dataSources.local.xml
|
.idea/**/dataSources.local.xml
|
||||||
@@ -92,44 +51,13 @@ tags
|
|||||||
.idea/**/dynamic.xml
|
.idea/**/dynamic.xml
|
||||||
.idea/**/uiDesigner.xml
|
.idea/**/uiDesigner.xml
|
||||||
.idea/**/dbnavigator.xml
|
.idea/**/dbnavigator.xml
|
||||||
.idea/**/gradle.xml
|
|
||||||
.idea/**/libraries
|
.idea/**/libraries
|
||||||
cmake-build-*/
|
|
||||||
.idea/**/mongoSettings.xml
|
|
||||||
*.iws
|
*.iws
|
||||||
out/
|
|
||||||
.idea_modules/
|
.idea_modules/
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
.idea/replstate.xml
|
.idea/replstate.xml
|
||||||
.idea/sonarlint/
|
.idea/sonarlint/
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
.idea/httpRequests
|
.idea/httpRequests
|
||||||
.idea/caches/build_file_checksums.ser
|
.idea/caches/build_file_checksums.ser
|
||||||
npm-debug.log
|
|
||||||
yarn-error.log
|
|
||||||
bootstrap/compiled.php
|
|
||||||
app/storage/
|
|
||||||
public/storage
|
|
||||||
public/hot
|
|
||||||
public_html/storage
|
|
||||||
public_html/hot
|
|
||||||
storage/*.key
|
|
||||||
Homestead.yaml
|
|
||||||
Homestead.json
|
|
||||||
/.vagrant
|
|
||||||
/node_modules
|
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
/coverage
|
|
||||||
/.next/
|
|
||||||
/out/
|
|
||||||
/build
|
|
||||||
.DS_Store
|
|
||||||
*.pem
|
|
||||||
.env*.local
|
|
||||||
.vercel
|
|
||||||
next-env.d.ts
|
|
||||||
|
|
||||||
|
# Claude Code
|
||||||
|
.claude/settings.local.json
|
||||||
|
|||||||
4
.markdownlint.json
Normal file
4
.markdownlint.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"MD013": false,
|
||||||
|
"MD041": false
|
||||||
|
}
|
||||||
1
.markdownlintignore
Normal file
1
.markdownlintignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
docs.md
|
||||||
26
.mega-linter.yml
Normal file
26
.mega-linter.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
APPLY_FIXES: all
|
||||||
|
PARALLEL: true
|
||||||
|
VALIDATE_ALL_CODEBASE: true
|
||||||
|
GITHUB_STATUS_REPORTER: true
|
||||||
|
SARIF_REPORTER: true
|
||||||
|
IGNORE_GENERATED_FILES: true
|
||||||
|
PRINT_ALPACA: false
|
||||||
|
SHOW_SKIPPED_LINTERS: false
|
||||||
|
SHOW_ELAPSED_TIME: false
|
||||||
|
FILEIO_REPORTER: false
|
||||||
|
|
||||||
|
ENABLE_LINTERS:
|
||||||
|
- YAML_YAMLLINT
|
||||||
|
- MARKDOWN_MARKDOWNLINT
|
||||||
|
- PHP_PHPCS
|
||||||
|
|
||||||
|
DISABLE_LINTERS:
|
||||||
|
- REPOSITORY_DEVSKIM
|
||||||
|
- JSON_PRETTIER
|
||||||
|
- YAML_PRETTIER
|
||||||
|
|
||||||
|
PHP_PHPCS_CLI_LINT_MODE: project
|
||||||
|
PHP_PHPCS_ARGUMENTS: "--warning-severity=0"
|
||||||
|
|
||||||
|
FILTER_REGEX_EXCLUDE: "(vendor/|node_modules/|\\.git/|\\.claude/|composer\\.lock|package-lock\\.json)"
|
||||||
20
.yamllint.yml
Normal file
20
.yamllint.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
extends: default
|
||||||
|
|
||||||
|
rules:
|
||||||
|
comments:
|
||||||
|
require-starting-space: true
|
||||||
|
ignore-shebangs: true
|
||||||
|
min-spaces-from-content: 1
|
||||||
|
line-length:
|
||||||
|
max: 120
|
||||||
|
allow-non-breakable-words: true
|
||||||
|
allow-non-breakable-inline-mappings: false
|
||||||
|
truthy:
|
||||||
|
check-keys: false
|
||||||
|
brackets:
|
||||||
|
min-spaces-inside: 0
|
||||||
|
max-spaces-inside: 1
|
||||||
|
|
||||||
|
ignore: |
|
||||||
|
vendor/
|
||||||
40
CHANGELOG.md
Normal file
40
CHANGELOG.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- v3 API client (`Ivuorinen\BusinessDataFetcher\v3\Client`) with support for:
|
||||||
|
- Company search (`searchCompanies()`)
|
||||||
|
- Code list descriptions (`getDescription()`)
|
||||||
|
- Postal code lookup (`getPostCodes()`)
|
||||||
|
- Full company ZIP download (`getAllCompanies()`)
|
||||||
|
- v3 DTOs based on the official OpenAPI schema
|
||||||
|
- Pest test suite with 57 tests covering traits, DTOs, and both API clients
|
||||||
|
- Shared HTTP infrastructure (`AbstractClient`, `HttpClientFactory`)
|
||||||
|
- PHP 8.4 added to CI matrix
|
||||||
|
- CI pipeline now runs linting, static analysis, and tests
|
||||||
|
- `phpunit.xml` configuration
|
||||||
|
- `.github/labels.yml` for label sync workflow
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **BREAKING:** Replaced `spatie/data-transfer-object` with `cuyz/valinor` for DTO hydration
|
||||||
|
- **BREAKING:** All v1 DTOs are now `final readonly` classes with constructor promotion
|
||||||
|
- **BREAKING:** Removed `$sourceText` and `$authorityText` computed properties from traits; use `getSourceText()` and `getAuthorityString()` methods instead
|
||||||
|
- **BREAKING:** `BusinessDataFetcher` constructor now accepts an optional `?Client` parameter for testability
|
||||||
|
- Upgraded `squizlabs/php_codesniffer` from v3 to v4
|
||||||
|
- **BREAKING:** `BusinessDataFetcher` now extends `AbstractClient`
|
||||||
|
- **BREAKING:** Traits are now method-only (no properties or constructors)
|
||||||
|
- **BREAKING:** Removed empty `HasVersion` trait (version is a regular constructor property)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- `spatie/data-transfer-object` dependency
|
||||||
|
- `ivuorinen/markdowndocs` dependency (incompatible with Pest's symfony/console requirement)
|
||||||
|
- `composer docs` script (pending markdowndocs update)
|
||||||
45
CLAUDE.md
Normal file
45
CLAUDE.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
PHP library for fetching Finnish business data from the PRH (Finnish Patent and Registration Office) open data API. Supports both v1 (BIS) and v3 (YTJ) APIs.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer lint # PSR-12 linting (phpcs v4) + Rector dry-run
|
||||||
|
composer lint-fix # Auto-fix PSR-12 violations (phpcbf) + Rector apply
|
||||||
|
composer rector # Run Rector standalone
|
||||||
|
composer phpstan # Static analysis (level 9)
|
||||||
|
composer test # Pest test suite
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- **v1 Entry point**: `src/BusinessDataFetcher.php` — extends `AbstractClient`, fetches from `/bis/v1`
|
||||||
|
- **v3 Entry point**: `src/v3/Client.php` — extends `AbstractClient`, fetches from `/opendata-ytj-api/v3`
|
||||||
|
- **Shared HTTP**: `src/Http/AbstractClient.php` — base class with Guzzle + Valinor mapper
|
||||||
|
- **v1 DTOs**: `src/v1/Dto/` — `final readonly` classes with Valinor-compatible constructors
|
||||||
|
- **v3 DTOs**: `src/v3/Dto/` — `final readonly` classes matching the v3 OpenAPI schema
|
||||||
|
- **Traits**: `src/v1/Traits/` — method-only helpers (`HasSource`, `HasLanguage`, `HasRegister`, `HasAuthority`, `HasChange`)
|
||||||
|
- **Exceptions**: `src/v1/Exceptions/`, `src/v3/Exceptions/`
|
||||||
|
- **Tests**: `tests/Unit/` — Pest tests for traits, DTOs, and both clients
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- PHP 8.2+
|
||||||
|
- PSR-12 coding standard (squizlabs/php_codesniffer v4)
|
||||||
|
- Rector (`rector.php`): `deadCode`, `codeQuality`, `typeDeclarations` sets — no `codingStyle` (phpcs handles that)
|
||||||
|
- PHPStan level 9
|
||||||
|
- Valinor v1 for DTO hydration with `allowSuperfluousKeys()`
|
||||||
|
- All DTOs are `final readonly` with constructor promotion
|
||||||
|
- Traits are method-only (no properties)
|
||||||
|
- Namespace: `Ivuorinen\BusinessDataFetcher`
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
- GitHub Actions workflows in `.github/workflows/`
|
||||||
|
- Reusable composite actions from `ivuorinen/actions` (not `ivuorinen/.github`)
|
||||||
|
- Renovate config: `.github/renovate.json` extends `github>ivuorinen/renovate-config`
|
||||||
|
- `pinact run -u -v --fix` — pin all action refs to commit SHAs after editing workflows
|
||||||
|
- PHP matrix: 8.2, 8.3, 8.4
|
||||||
47
CONTRIBUTING.md
Normal file
47
CONTRIBUTING.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- PHP 8.2+
|
||||||
|
- Composer
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/ivuorinen/business-data-fetcher.git
|
||||||
|
cd business-data-fetcher
|
||||||
|
composer install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Running checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer lint # PSR-12 linting
|
||||||
|
composer lint-fix # Auto-fix PSR-12 violations
|
||||||
|
composer phpstan # Static analysis (level 9)
|
||||||
|
composer test # Pest test suite
|
||||||
|
```
|
||||||
|
|
||||||
|
### Branch Strategy
|
||||||
|
|
||||||
|
- `main` — stable release branch
|
||||||
|
- `feat/*` — feature branches
|
||||||
|
- `fix/*` — bugfix branches
|
||||||
|
|
||||||
|
### Pull Request Process
|
||||||
|
|
||||||
|
1. Create a feature or fix branch from `main`
|
||||||
|
2. Make your changes
|
||||||
|
3. Ensure all checks pass: `composer lint && composer phpstan && composer test`
|
||||||
|
4. Open a PR against `main`
|
||||||
|
5. PRs require passing CI before merge
|
||||||
|
|
||||||
|
## Code Conventions
|
||||||
|
|
||||||
|
- PSR-12 coding standard
|
||||||
|
- PHPStan level 9 strict analysis
|
||||||
|
- All DTOs are `final readonly` classes with constructor promotion
|
||||||
|
- Use Valinor for hydration (not manual array mapping)
|
||||||
|
- Write Pest tests for new functionality
|
||||||
111
README.md
111
README.md
@@ -1,36 +1,112 @@
|
|||||||
# Business Data Fetcher
|
# Business Data Fetcher
|
||||||
|
|
||||||
This is an API client to Finnish Patent and Registration
|
[](https://github.com/ivuorinen/business-data-fetcher/actions/workflows/composer.yml)
|
||||||
Office's (PRH) Business Information System (BIS).
|
|
||||||
|
|
||||||
Use it to get company data from the Business Information System by Business ID.
|
PHP library for fetching Finnish business data from the PRH (Finnish Patent and Registration Office) open data API.
|
||||||
|
|
||||||
|
Supports both **v1** (BIS) and **v3** (YTJ) APIs.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer install ivuorinen/business-data-fetcher
|
composer require ivuorinen/business-data-fetcher
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage example
|
## Usage
|
||||||
|
|
||||||
|
### v1 API (BIS)
|
||||||
|
|
||||||
|
Fetch company details by Business ID:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
use Ivuorinen\BusinessDataFetcher\BusinessDataFetcher;
|
||||||
require_once 'vendor/autoload.php';
|
|
||||||
|
|
||||||
$client = new Ivuorinen\BusinessDataFetcher\BusinessDataFetcher();
|
$client = new BusinessDataFetcher();
|
||||||
try {
|
$results = $client->getBusinessInformation('1639413-9');
|
||||||
$results = $client->getBusinessInformation('1639413-9');
|
|
||||||
print_r($results);
|
foreach ($results as $company) {
|
||||||
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
|
echo $company->name . "\n";
|
||||||
var_dump($e);
|
echo $company->businessId . "\n";
|
||||||
|
|
||||||
|
foreach ($company->names as $name) {
|
||||||
|
echo $name->name . ' (' . $name->getLanguageString() . ")\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Data source
|
### v3 API (YTJ)
|
||||||
|
|
||||||
All models are transcribed from PRH Open Data portal. You can find the examples
|
Search companies with multiple filters:
|
||||||
and models descriptions, among other details and live API query tool following
|
|
||||||
this link: https://avoindata.prh.fi/ytj_en.html
|
```php
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Client;
|
||||||
|
|
||||||
|
$client = new Client();
|
||||||
|
|
||||||
|
// Search by name
|
||||||
|
$result = $client->searchCompanies(name: 'Example');
|
||||||
|
echo "Found {$result->totalResults} companies\n";
|
||||||
|
|
||||||
|
foreach ($result->companies as $company) {
|
||||||
|
echo $company->businessId->value . ' - ';
|
||||||
|
echo $company->names[0]->name . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search by Business ID
|
||||||
|
$result = $client->searchCompanies(businessId: '1639413-9');
|
||||||
|
|
||||||
|
// Search with multiple filters
|
||||||
|
$result = $client->searchCompanies(
|
||||||
|
location: 'Helsinki',
|
||||||
|
companyForm: 'OY',
|
||||||
|
mainBusinessLine: '62010',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get code list descriptions
|
||||||
|
$description = $client->getDescription('REK', 'en');
|
||||||
|
|
||||||
|
// Get postal codes
|
||||||
|
$postCodes = $client->getPostCodes('fi');
|
||||||
|
|
||||||
|
// Download all companies as ZIP
|
||||||
|
$stream = $client->getAllCompanies();
|
||||||
|
file_put_contents('companies.zip', $stream->getContents());
|
||||||
|
```
|
||||||
|
|
||||||
|
## v1 vs v3 API Comparison
|
||||||
|
|
||||||
|
| Feature | v1 (BIS) | v3 (YTJ) |
|
||||||
|
| --------- | ---------- | ---------- |
|
||||||
|
| Base URL | `/bis/v1` | `/opendata-ytj-api/v3` |
|
||||||
|
| Lookup | By Business ID only | Search by name, location, form, etc. |
|
||||||
|
| Company form | String code | Structured with descriptions |
|
||||||
|
| Addresses | Flat structure | Nested with PostOffice objects |
|
||||||
|
| Code lists | N/A | `/description` endpoint |
|
||||||
|
| Postal codes | N/A | `/post_codes` endpoint |
|
||||||
|
| Bulk download | N/A | `/all_companies` ZIP |
|
||||||
|
|
||||||
|
## Migration from v1 DTOs
|
||||||
|
|
||||||
|
If upgrading from the Spatie DTO version:
|
||||||
|
|
||||||
|
- DTOs are now `final readonly` classes (no `->toArray()`)
|
||||||
|
- `$sourceText` / `$authorityText` properties removed; use `getSourceText()` / `getAuthorityString()` methods
|
||||||
|
- `HasVersion` trait removed; `$version` is a regular constructor property
|
||||||
|
- `BusinessDataFetcher` constructor accepts an optional Guzzle `Client` for testing
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer lint # PSR-12 linting
|
||||||
|
composer lint-fix # Auto-fix violations
|
||||||
|
composer phpstan # Static analysis (level 9)
|
||||||
|
composer test # Pest test suite
|
||||||
|
```
|
||||||
|
|
||||||
|
## Data Source
|
||||||
|
|
||||||
|
- v1: <https://avoindata.prh.fi/ytj_en.html>
|
||||||
|
- v3: <https://avoindata.prh.fi/fi/ytj/swagger-ui>
|
||||||
|
|
||||||
## Notice of Liability
|
## Notice of Liability
|
||||||
|
|
||||||
@@ -40,4 +116,3 @@ of this library are providing this without compensation and cannot be held respo
|
|||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT licensed](LICENSE.md)
|
[MIT licensed](LICENSE.md)
|
||||||
|
|
||||||
|
|||||||
69
captainhook.json
Normal file
69
captainhook.json
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
{
|
||||||
|
"pre-commit": {
|
||||||
|
"enabled": true,
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"action": "\\CaptainHook\\App\\Hook\\Diff\\Action\\BlockSecrets",
|
||||||
|
"options": {},
|
||||||
|
"conditions": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "composer lint-fix",
|
||||||
|
"options": {},
|
||||||
|
"conditions": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action": "composer test",
|
||||||
|
"options": {},
|
||||||
|
"conditions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"commit-msg": {
|
||||||
|
"enabled": true,
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"action": "\\Ramsey\\CaptainHook\\ValidateConventionalCommit",
|
||||||
|
"options": {},
|
||||||
|
"conditions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pre-push": {
|
||||||
|
"enabled": false,
|
||||||
|
"actions": []
|
||||||
|
},
|
||||||
|
"post-commit": {
|
||||||
|
"enabled": false,
|
||||||
|
"actions": []
|
||||||
|
},
|
||||||
|
"post-merge": {
|
||||||
|
"enabled": false,
|
||||||
|
"actions": []
|
||||||
|
},
|
||||||
|
"post-checkout": {
|
||||||
|
"enabled": false,
|
||||||
|
"actions": []
|
||||||
|
},
|
||||||
|
"post-rewrite": {
|
||||||
|
"enabled": false,
|
||||||
|
"actions": []
|
||||||
|
},
|
||||||
|
"post-change": {
|
||||||
|
"enabled": true,
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"action": "composer install",
|
||||||
|
"options": {},
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"exec": "CaptainHook.FileChanged.Any",
|
||||||
|
"args": [
|
||||||
|
["composer.json", "composer.lock"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,16 +5,51 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
"guzzlehttp/guzzle": "^7.4.5",
|
"ext-json": "*",
|
||||||
"spatie/data-transfer-object": "^3.9"
|
"guzzlehttp/guzzle": "^7.4",
|
||||||
|
"cuyz/valinor": "^2.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Ivuorinen\\BusinessDataFetcher\\": "src/"
|
"Ivuorinen\\BusinessDataFetcher\\": "src/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Ivuorinen\\BusinessDataFetcher\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"squizlabs/php_codesniffer": "^3.10",
|
"squizlabs/php_codesniffer": "^4.0",
|
||||||
"ivuorinen/markdowndocs": "^4.0"
|
"phpstan/phpstan": "^2.0",
|
||||||
|
"pestphp/pest": "^3.0",
|
||||||
|
"rector/rector": "^2.3",
|
||||||
|
"captainhook/captainhook": "^5.0",
|
||||||
|
"captainhook/hook-installer": "^1.0",
|
||||||
|
"ramsey/conventional-commits": "^1.7",
|
||||||
|
"captainhook/secrets": "^0.9.7",
|
||||||
|
"phpstan/extension-installer": "^1.0",
|
||||||
|
"jbelien/phpstan-sarif-formatter": "^1.0",
|
||||||
|
"bartlett/sarif-php-converters": "^1.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": [
|
||||||
|
"php vendor/bin/phpcs --standard=PSR12 src",
|
||||||
|
"php vendor/bin/rector --dry-run"
|
||||||
|
],
|
||||||
|
"lint-fix": [
|
||||||
|
"php vendor/bin/phpcbf --standard=PSR12 src",
|
||||||
|
"php vendor/bin/rector"
|
||||||
|
],
|
||||||
|
"rector": "php vendor/bin/rector",
|
||||||
|
"phpstan": "php vendor/bin/phpstan analyse",
|
||||||
|
"test": "php vendor/bin/pest"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"pestphp/pest-plugin": true,
|
||||||
|
"captainhook/hook-installer": true,
|
||||||
|
"phpstan/extension-installer": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4879
composer.lock
generated
4879
composer.lock
generated
File diff suppressed because it is too large
Load Diff
22
docs.md
22
docs.md
@@ -25,7 +25,7 @@
|
|||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
| public | <strong>__construct()</strong> : <em>void</em><br /><em>BusinessDataFetcher constructor.</em> |
|
| public | <strong>__construct()</strong> : <em>void</em><br /><em>BusinessDataFetcher constructor.</em> |
|
||||||
| public | <strong>getBusinessInformation(</strong><em>\string</em> <strong>$businessId</strong>)</strong> : <em>array</em><br /><em>Fetch Business Information.</em> |
|
| public | <strong>getBusinessInformation(</strong><em>\string</em> <strong>$businessId</strong>)</strong> : <em>array</em><br /><em>Fetch Business Information.</em> |
|
||||||
| public | <strong>parse_response(</strong><em>\Psr\Http\Message\ResponseInterface</em> <strong>$response</strong>)</strong> : <em>array</em> |
|
| public | <strong>parseResponse(</strong><em>\Psr\Http\Message\ResponseInterface</em> <strong>$response</strong>)</strong> : <em>array</em><br /><em>Parse the response from the API.</em> |
|
||||||
|
|
||||||
|
|
||||||
<hr /><a id="class-ivuorinenbusinessdatafetcherdtobiscompanyname"></a>
|
<hr /><a id="class-ivuorinenbusinessdatafetcherdtobiscompanyname"></a>
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -58,10 +60,12 @@
|
|||||||
|
|
||||||
### Class: \Ivuorinen\BusinessDataFetcher\Dto\BisCompanyBusinessIdChange
|
### Class: \Ivuorinen\BusinessDataFetcher\Dto\BisCompanyBusinessIdChange
|
||||||
|
|
||||||
> Company Business ID Change
|
> Company Business Id Change
|
||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getChangeString()</strong> : <em>string</em><br /><em>Get the description string of the change.</em> |
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -71,10 +75,11 @@
|
|||||||
|
|
||||||
### Class: \Ivuorinen\BusinessDataFetcher\Dto\BisAddress
|
### Class: \Ivuorinen\BusinessDataFetcher\Dto\BisAddress
|
||||||
|
|
||||||
> Business Address
|
> Address
|
||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -88,6 +93,7 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -101,6 +107,7 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -114,9 +121,9 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
| public | <strong>getAuthorityText()</strong> : <em>string</em> |
|
| public | <strong>getAuthorityString()</strong> : <em>string</em><br /><em>Get the name of the authority.</em> |
|
||||||
| public | <strong>getRegisterText()</strong> : <em>string</em> |
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getStatusText()</strong> : <em>string</em> |
|
| public | <strong>getRegisterString()</strong> : <em>string</em><br /><em>Get the name of the register.</em> |
|
||||||
|
|
||||||
|
|
||||||
*This class extends \Spatie\DataTransferObject\DataTransferObject*
|
*This class extends \Spatie\DataTransferObject\DataTransferObject*
|
||||||
@@ -129,6 +136,7 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -142,6 +150,7 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
@@ -167,6 +176,7 @@
|
|||||||
|
|
||||||
| Visibility | Function |
|
| Visibility | Function |
|
||||||
|:-----------|:---------|
|
|:-----------|:---------|
|
||||||
|
| public | <strong>getLanguageString()</strong> : <em>string</em><br /><em>Get the language code as a string.</em> |
|
||||||
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
| public | <strong>getSourceText()</strong> : <em>string</em> |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ require_once "vendor/autoload.php";
|
|||||||
$client = new Ivuorinen\BusinessDataFetcher\BusinessDataFetcher();
|
$client = new Ivuorinen\BusinessDataFetcher\BusinessDataFetcher();
|
||||||
try {
|
try {
|
||||||
$results = $client->getBusinessInformation("1639413-9");
|
$results = $client->getBusinessInformation("1639413-9");
|
||||||
print_r($results);
|
// Convert to JSON
|
||||||
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
|
echo json_encode($results, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT);
|
||||||
|
} catch (Exception $e) {
|
||||||
var_dump($e);
|
var_dump($e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ BisCompanyForm {
|
|||||||
endDate (string, optional): Ending date of registration
|
endDate (string, optional): Ending date of registration
|
||||||
name (string): Name of company form
|
name (string): Name of company form
|
||||||
language (string, optional): Two letter language code
|
language (string, optional): Two letter language code
|
||||||
type (string): Type of company form
|
type (string, optional): Type of company form
|
||||||
}
|
}
|
||||||
|
|
||||||
BisCompanyLiquidation {
|
BisCompanyLiquidation {
|
||||||
|
|||||||
153
gen/parser.php
153
gen/parser.php
@@ -1,42 +1,53 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Load models.txt that contains https://avoindata.prh.fi/ytj_en.html models.
|
// Previously https://avoindata.prh.fi/ytj_en.html had model definitions as plain text.
|
||||||
// Just copy and paste the plaintext Response Class contents to the file and
|
// Now the page is not available anymore, but keeping the parser for future use.
|
||||||
|
// The models.txt file is a copy of the models from that page.
|
||||||
|
// This parser reads the models.txt file and generates DTO classes for the models in the src/Dto directory.
|
||||||
|
//
|
||||||
|
// Current version of the API by PRH is Swagger based, so the models are available in the Swagger definition:
|
||||||
|
// https://avoindata.prh.fi/fi/ytj/swagger-ui
|
||||||
|
//
|
||||||
// run this file: php parser.php
|
// run this file: php parser.php
|
||||||
$models = file_get_contents(sprintf('%s%2$smodels.txt', __DIR__, DIRECTORY_SEPARATOR));
|
|
||||||
|
|
||||||
// Capture the names as one group,
|
// Set the directory separator alias.
|
||||||
// and blocks inside curly braces as another,
|
const DS = DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
// Load the models.txt file.
|
||||||
|
$models = file_get_contents(sprintf('%s%smodels.txt', __DIR__, DS));
|
||||||
|
|
||||||
|
// Capture the names as one group, and blocks inside curly braces as another,
|
||||||
// then combine them later.
|
// then combine them later.
|
||||||
preg_match_all("/(\w+)\s\{([\w\W]*?)\}/m", $models, $output_array);
|
preg_match_all("/(\w+)\s\{([\w\W]*?)\}/m", $models, $output_array);
|
||||||
|
|
||||||
[$all, $names, $fields] = $output_array;
|
[$all, $names, $fields] = $output_array;
|
||||||
|
|
||||||
$fields = array_map(function ($f) {
|
$fields = array_map(static function ($f) {
|
||||||
$f = explode("\n", $f);
|
$d = explode("\n", $f);
|
||||||
$f = array_map("trim", $f);
|
$d = array_map("trim", $d);
|
||||||
$f = array_filter($f);
|
$d = array_filter($d);
|
||||||
|
|
||||||
$f = array_map(function ($field) {
|
$d = array_map(static function ($field) {
|
||||||
[$name_and_type, $docs] = explode(":", $field, 2);
|
[$name_and_type, $docs] = explode(":", $field, 2);
|
||||||
$names_and_types = explode(" ", $name_and_type, 2);
|
[$name, $type] = explode(" ", $name_and_type, 2);
|
||||||
|
|
||||||
[$name, $type] = $names_and_types;
|
|
||||||
|
|
||||||
$type = str_replace(["(", ")"], "", $type);
|
$type = str_replace(["(", ")"], "", $type);
|
||||||
|
|
||||||
|
// Handle optional types.
|
||||||
if (str_contains($type, "optional")) {
|
if (str_contains($type, "optional")) {
|
||||||
$type = str_replace(["optional", ","], "", $type);
|
$type = str_replace(["optional", ","], "", $type);
|
||||||
$type = "?" . trim($type);
|
$type = "?" . trim($type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle integer types.
|
||||||
if ($type === "integer") {
|
if ($type === "integer") {
|
||||||
$type = "int";
|
$type = "int";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle array types. Convert Array[Type] to Type[].
|
||||||
if (str_contains($type, "Array")) {
|
if (str_contains($type, "Array")) {
|
||||||
$type = str_replace(["Array[", "]"], "", $type);
|
$type = str_replace(["Array[", "]"], "", $type);
|
||||||
$type = $type . "[]";
|
$type .= "[]";
|
||||||
}
|
}
|
||||||
|
|
||||||
$default = null;
|
$default = null;
|
||||||
@@ -60,62 +71,90 @@ $fields = array_map(function ($f) {
|
|||||||
"default" => $default,
|
"default" => $default,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}, $f ?? []);
|
}, $d);
|
||||||
|
|
||||||
$f = array_merge(...$f);
|
return array_merge(...$d);
|
||||||
|
|
||||||
return $f;
|
|
||||||
}, $fields);
|
}, $fields);
|
||||||
|
|
||||||
$classes = array_combine($names, $fields);
|
$classes = array_combine($names, $fields);
|
||||||
|
|
||||||
ksort($classes);
|
ksort($classes);
|
||||||
|
|
||||||
// print_r($classes);
|
$files = [];
|
||||||
|
|
||||||
// Files that have already been processed.
|
|
||||||
// Uncomment to display the results again.
|
|
||||||
$added = [
|
|
||||||
// "BisCompanyRegisteredOffice",
|
|
||||||
// "BisCompanyRegisteredEntry",
|
|
||||||
// "BisCompanyName",
|
|
||||||
// "BisCompanyLiquidation",
|
|
||||||
// "BisCompanyLanguage",
|
|
||||||
// "BisCompanyForm",
|
|
||||||
// "BisCompanyDetails",
|
|
||||||
// "BisCompanyContactDetail",
|
|
||||||
// "BisCompanyBusinessLine",
|
|
||||||
// "BisCompanyBusinessIdChange",
|
|
||||||
// "BisAddress",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Output the classes as preformatted for easier copypasta.
|
|
||||||
// This is not the prettiest way to generate the codes, but it works.
|
// This is not the prettiest way to generate the codes, but it works.
|
||||||
foreach ($classes as $className => $vars) {
|
foreach ($classes as $className => $vars) {
|
||||||
if (in_array($className, $added)) {
|
// Get name of the class from filename and split CamelCase to words.
|
||||||
continue;
|
$classNameString = $className;
|
||||||
|
$classNameString = str_replace("Bis", "", $classNameString);
|
||||||
|
$classNameString = (string)preg_replace('/(?<!^)[A-Z]/', ' $0', $classNameString);
|
||||||
|
$classNameString = ucwords($classNameString);
|
||||||
|
|
||||||
|
$usesHeader = [
|
||||||
|
"",
|
||||||
|
"use Spatie\DataTransferObject\DataTransferObject;",
|
||||||
|
];
|
||||||
|
|
||||||
|
$hasCasters = [
|
||||||
|
"BisCompanyDetails",
|
||||||
|
];
|
||||||
|
|
||||||
|
if (in_array($className, $hasCasters, true)) {
|
||||||
|
$usesHeader["CastWith"] = "use Spatie\DataTransferObject\Attributes\CastWith;";
|
||||||
|
$usesHeader["Casters"] = "use Spatie\DataTransferObject\Casters;";
|
||||||
|
}
|
||||||
|
$traits = [];
|
||||||
|
|
||||||
|
if (array_key_exists('authority', $vars)) {
|
||||||
|
$traits[] = " use Traits\HasAuthority;";
|
||||||
|
}
|
||||||
|
if (array_key_exists('source', $vars)) {
|
||||||
|
$traits[] = " use Traits\HasSource;";
|
||||||
|
}
|
||||||
|
if (array_key_exists('version', $vars)) {
|
||||||
|
$traits[] = " use Traits\HasVersion;";
|
||||||
|
}
|
||||||
|
if (array_key_exists('language', $vars)) {
|
||||||
|
$traits[] = " use Traits\HasLanguage;";
|
||||||
|
}
|
||||||
|
if (array_key_exists('change', $vars)) {
|
||||||
|
$traits[] = " use Traits\HasChange;";
|
||||||
|
}
|
||||||
|
if (array_key_exists('register', $vars)) {
|
||||||
|
$traits[] = " use Traits\HasRegister;";
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "
|
if (!empty($traits)) {
|
||||||
|
$usesHeader[] = "use Ivuorinen\BusinessDataFetcher\\v1\Traits;";
|
||||||
|
}
|
||||||
|
|
||||||
|
$usesString = implode("\n", $usesHeader);
|
||||||
|
|
||||||
|
$used = ['authority', 'source', 'version', 'language', 'change', 'register'];
|
||||||
|
|
||||||
|
$file = "<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\\v1\Dto;
|
||||||
|
$usesString
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $className
|
* $classNameString
|
||||||
*/
|
*/
|
||||||
class $className extends DataTransferObject
|
class $className extends DataTransferObject
|
||||||
{
|
{";
|
||||||
";
|
if (!empty($traits)) {
|
||||||
if (array_key_exists("source", $vars)) {
|
$file .= "\n" . implode("\n", $traits) . "\n";
|
||||||
echo " use HasSource;\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($vars as $varKey => $varData) {
|
foreach ($vars as $varKey => $varData) {
|
||||||
if ($varKey === "source") {
|
if (in_array($varKey, $used, true)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$caster = "";
|
$caster = "";
|
||||||
if (str_contains($varData["type"], "[")) {
|
if (str_contains($varData["type"], "[")) {
|
||||||
$classType = str_replace(["[", "]", "?"], "", $varData["type"]);
|
$classType = str_replace(["[", "]", "?"], "", $varData["type"]);
|
||||||
$caster = "\n #[CastWith(Casters\ArrayCaster::class, itemType: {$classType}::class)]";
|
$caster = "\n #[CastWith(Casters\ArrayCaster::class, itemType: $classType::class)]";
|
||||||
}
|
}
|
||||||
|
|
||||||
$type = $varData["type"];
|
$type = $varData["type"];
|
||||||
@@ -126,12 +165,28 @@ class $className extends DataTransferObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
$default = $varData["default"] !== null ? " = " . $varData["default"] . ";" : ";";
|
$default = $varData["default"] !== null ? " = " . $varData["default"] . ";" : ";";
|
||||||
echo "
|
|
||||||
|
$file .= "
|
||||||
/**
|
/**
|
||||||
* {$varData["docs"]}{$typeHelper}
|
* {$varData["docs"]}{$typeHelper}
|
||||||
*/{$caster}
|
*/{$caster}
|
||||||
public {$type} \${$varData["name"]}{$default}
|
public $type \${$varData["name"]}{$default}
|
||||||
";
|
";
|
||||||
}
|
}
|
||||||
echo "\n}";
|
$file .= "}\n";
|
||||||
|
|
||||||
|
$files[$className] = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($files)) {
|
||||||
|
echo "Generating files:\n";
|
||||||
|
|
||||||
|
// Set the directory for the DTO classes.
|
||||||
|
$dtoDir = implode(DS, [dirname(__FILE__, 2), 'src', 'v1', 'Dto']);
|
||||||
|
|
||||||
|
foreach ($files as $className => $file) {
|
||||||
|
$filePath = sprintf('%s%s%s.php', $dtoDir, DS, $className);
|
||||||
|
echo $filePath . "\n";
|
||||||
|
file_put_contents($filePath, $file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<ruleset name="PHP_CodeSniffer">
|
<ruleset name="PHP_CodeSniffer">
|
||||||
<description>PSR12</description>
|
<description>PSR12</description>
|
||||||
|
<file>src</file>
|
||||||
<rule ref="PSR12">
|
<rule ref="PSR12">
|
||||||
<exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
|
<exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
|
||||||
<exclude name="PSR12.Operators.OperatorSpacing"/>
|
<exclude name="PSR12.Operators.OperatorSpacing"/>
|
||||||
|
|||||||
4
phpstan.neon
Normal file
4
phpstan.neon
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
parameters:
|
||||||
|
level: 9
|
||||||
|
paths:
|
||||||
|
- src
|
||||||
18
phpunit.xml.dist
Normal file
18
phpunit.xml.dist
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
colors="true"
|
||||||
|
cacheDirectory=".phpunit.cache"
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Unit">
|
||||||
|
<directory>tests/Unit</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<source>
|
||||||
|
<include>
|
||||||
|
<directory>src</directory>
|
||||||
|
</include>
|
||||||
|
</source>
|
||||||
|
</phpunit>
|
||||||
16
rector.php
Normal file
16
rector.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Rector\Config\RectorConfig;
|
||||||
|
|
||||||
|
return RectorConfig::configure()
|
||||||
|
->withPaths([
|
||||||
|
__DIR__ . '/src',
|
||||||
|
])
|
||||||
|
->withPhpSets(php82: true)
|
||||||
|
->withPreparedSets(
|
||||||
|
deadCode: true,
|
||||||
|
codeQuality: true,
|
||||||
|
typeDeclarations: true,
|
||||||
|
);
|
||||||
@@ -2,49 +2,37 @@
|
|||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher;
|
namespace Ivuorinen\BusinessDataFetcher;
|
||||||
|
|
||||||
use GuzzleHttp\Client;
|
|
||||||
use GuzzleHttp\Exception\RequestException;
|
use GuzzleHttp\Exception\RequestException;
|
||||||
use Ivuorinen\BusinessDataFetcher\Dto\BisCompanyDetails;
|
use Ivuorinen\BusinessDataFetcher\Http\AbstractClient;
|
||||||
use Ivuorinen\BusinessDataFetcher\Exceptions\ApiResponseErrorException;
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyDetails;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Exceptions\ApiResponseErrorException;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
/**
|
/** Client for the PRH BIS v1 API (Finnish business data). */
|
||||||
* Fetches and returns business data from avoindata
|
class BusinessDataFetcher extends AbstractClient
|
||||||
*/
|
|
||||||
class BusinessDataFetcher
|
|
||||||
{
|
{
|
||||||
/**
|
/** @inheritDoc */
|
||||||
* @var \GuzzleHttp\Client
|
protected function getBaseUri(): string
|
||||||
*/
|
|
||||||
private Client $httpClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BusinessDataFetcher constructor.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
{
|
||||||
$this->httpClient = new Client([
|
return 'https://avoindata.prh.fi';
|
||||||
'base_uri' => 'https://avoindata.prh.fi',
|
}
|
||||||
'timeout' => 2,
|
|
||||||
]);
|
/** @inheritDoc */
|
||||||
|
protected function getTimeout(): int
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch Business Information.
|
* Fetch Business Information.
|
||||||
*
|
*
|
||||||
* @param string $businessId
|
* @return BisCompanyDetails[]
|
||||||
*
|
|
||||||
* @return array $response_data
|
|
||||||
* @throws \Exception|\GuzzleHttp\Exception\GuzzleException
|
* @throws \Exception|\GuzzleHttp\Exception\GuzzleException
|
||||||
*/
|
*/
|
||||||
public function getBusinessInformation(string $businessId): array
|
public function getBusinessInformation(string $businessId): array
|
||||||
{
|
{
|
||||||
// Set request variables
|
|
||||||
$requestUrl = '/bis/v1';
|
|
||||||
$response_data = [];
|
|
||||||
|
|
||||||
// Get the business data
|
|
||||||
try {
|
try {
|
||||||
$uri = $requestUrl . '/' . $businessId;
|
$uri = '/bis/v1/' . rawurlencode($businessId);
|
||||||
$response = $this->httpClient->get($uri);
|
$response = $this->httpClient->get($uri);
|
||||||
|
|
||||||
if ($response->getStatusCode() !== 200) {
|
if ($response->getStatusCode() !== 200) {
|
||||||
@@ -54,7 +42,7 @@ class BusinessDataFetcher
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response_data = $this->parse_response($response);
|
return $this->parseResponse($response);
|
||||||
} catch (RequestException $exception) {
|
} catch (RequestException $exception) {
|
||||||
throw new ApiResponseErrorException(
|
throw new ApiResponseErrorException(
|
||||||
$exception->getMessage(),
|
$exception->getMessage(),
|
||||||
@@ -62,18 +50,16 @@ class BusinessDataFetcher
|
|||||||
$exception
|
$exception
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response_data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Psr\Http\Message\ResponseInterface $response
|
* Parse the response from the API.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return BisCompanyDetails[]
|
||||||
* @throws \JsonException
|
* @throws \JsonException
|
||||||
* @throws \Spatie\DataTransferObject\Exceptions\UnknownProperties
|
* @throws ApiResponseErrorException
|
||||||
*/
|
*/
|
||||||
public function parse_response(\Psr\Http\Message\ResponseInterface $response): array
|
public function parseResponse(ResponseInterface $response): array
|
||||||
{
|
{
|
||||||
$data = json_decode(
|
$data = json_decode(
|
||||||
$response->getBody()->getContents(),
|
$response->getBody()->getContents(),
|
||||||
@@ -82,10 +68,24 @@ class BusinessDataFetcher
|
|||||||
JSON_THROW_ON_ERROR
|
JSON_THROW_ON_ERROR
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!is_array($data)) {
|
||||||
|
throw new ApiResponseErrorException(
|
||||||
|
'Invalid response data',
|
||||||
|
$response->getStatusCode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($data['results']) || !is_array($data['results'])) {
|
||||||
|
throw new ApiResponseErrorException(
|
||||||
|
'Invalid response data',
|
||||||
|
$response->getStatusCode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$results = [];
|
$results = [];
|
||||||
|
|
||||||
foreach ($data['results'] as $result) {
|
foreach ($data['results'] as $result) {
|
||||||
$results[] = new BisCompanyDetails($result);
|
$results[] = $this->mapper->map(BisCompanyDetails::class, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return $results;
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business Address
|
|
||||||
*/
|
|
||||||
class BisAddress extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical addresses
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Care of address
|
|
||||||
*/
|
|
||||||
public ?string $careOf = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Street address
|
|
||||||
*/
|
|
||||||
public ?string $street = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ZIP code
|
|
||||||
*/
|
|
||||||
public ?string $postCode = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* City of address
|
|
||||||
*/
|
|
||||||
public ?string $city = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of address, 1 for street address, 2 for postal address
|
|
||||||
*/
|
|
||||||
public int $type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter country code
|
|
||||||
*/
|
|
||||||
public ?string $country = null;
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Business ID Change
|
|
||||||
*/
|
|
||||||
class BisCompanyBusinessIdChange extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description of reason
|
|
||||||
*/
|
|
||||||
public string $description = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reason code
|
|
||||||
*/
|
|
||||||
public string $reason = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of Business ID change
|
|
||||||
*/
|
|
||||||
public ?string $changeDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business ID Change
|
|
||||||
*
|
|
||||||
* 2 = Business ID removal,
|
|
||||||
* 3 = Combining of double IDs,
|
|
||||||
* 5 = ID changed,
|
|
||||||
* 44 = Fusion,
|
|
||||||
* 45 = Operator continuing VAT activities,
|
|
||||||
* 46 = Relation to predecessor,
|
|
||||||
* 47 = Division,
|
|
||||||
* 48 = Bankruptcy relationship,
|
|
||||||
* 49 = Operations continued by a private trader,
|
|
||||||
* 57 = Partial division,
|
|
||||||
* DIF = Division,
|
|
||||||
* FUU = Fusion
|
|
||||||
*/
|
|
||||||
public int $change;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Old Business ID
|
|
||||||
*/
|
|
||||||
public string $oldBusinessId = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New Business ID
|
|
||||||
*/
|
|
||||||
public string $newBusinessId = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Business Line
|
|
||||||
*/
|
|
||||||
class BisCompanyBusinessLine extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zero for main line of business, positive for others
|
|
||||||
*/
|
|
||||||
public int $order;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical lines of business
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of line of business
|
|
||||||
*/
|
|
||||||
public string $name = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Contact Detail
|
|
||||||
*/
|
|
||||||
class BisCompanyContactDetail extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical contact details
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Value of contact detail
|
|
||||||
*/
|
|
||||||
public string $value = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of contact detail
|
|
||||||
*/
|
|
||||||
public string $type = "";
|
|
||||||
}
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Spatie\DataTransferObject\Attributes\CastWith;
|
|
||||||
use Spatie\DataTransferObject\Casters;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Details
|
|
||||||
*/
|
|
||||||
class BisCompanyDetails extends DataTransferObject
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Primary company name and translations
|
|
||||||
* @var BisCompanyName[] $names
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyName::class)]
|
|
||||||
public array $names = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auxiliary company name and translations
|
|
||||||
* @var ?BisCompanyName[] $auxiliaryNames
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyName::class)]
|
|
||||||
public ?array $auxiliaryNames = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company's street and postal addresses
|
|
||||||
* @var ?BisAddress[] $addresses
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisAddress::class)]
|
|
||||||
public ?array $addresses = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company form and translations
|
|
||||||
* @var ?BisCompanyForm[] $companyForms
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyForm::class)]
|
|
||||||
public ?array $companyForms = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bankruptcy, liquidation or restructuring proceedings
|
|
||||||
* @var ?BisCompanyLiquidation[] $liquidations
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyLiquidation::class)]
|
|
||||||
public ?array $liquidations = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company's lines of business and translations
|
|
||||||
* @var ?BisCompanyBusinessLine[] $businessLines
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyBusinessLine::class)]
|
|
||||||
public ?array $businessLines = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company's language(s)
|
|
||||||
* @var ?BisCompanyLanguage[] $languages
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyLanguage::class)]
|
|
||||||
public ?array $languages = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company's place of registered office and its translations
|
|
||||||
* @var ?BisCompanyRegisteredOffice[] $registeredOffices
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyRegisteredOffice::class)]
|
|
||||||
public ?array $registeredOffices = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company's contact details and translations
|
|
||||||
* @var ?BisCompanyContactDetail[] $contactDetails
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyContactDetail::class)]
|
|
||||||
public ?array $contactDetails = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company's registered entries
|
|
||||||
* @var ?BisCompanyRegisteredEntry[] $registeredEntries
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyRegisteredEntry::class)]
|
|
||||||
public ?array $registeredEntries = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company's Business ID changes
|
|
||||||
* @var ?BisCompanyBusinessIdChange[] $businessIdChanges
|
|
||||||
*/
|
|
||||||
#[CastWith(Casters\ArrayCaster::class, itemType: BisCompanyBusinessIdChange::class)]
|
|
||||||
public ?array $businessIdChanges = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Business ID
|
|
||||||
*/
|
|
||||||
public string $businessId = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company form
|
|
||||||
*/
|
|
||||||
public ?string $companyForm = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A URI for more details, if details aren't already included
|
|
||||||
*/
|
|
||||||
public ?string $detailsUri = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Primary company name
|
|
||||||
*/
|
|
||||||
public string $name = "";
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Form
|
|
||||||
*/
|
|
||||||
class BisCompanyForm extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical company forms
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of company form
|
|
||||||
*/
|
|
||||||
public string $name = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of company form.
|
|
||||||
*
|
|
||||||
* Note: According to spec, this shouldn't be nullable,
|
|
||||||
* but payloads show otherwise.
|
|
||||||
*
|
|
||||||
* @var string|null
|
|
||||||
*/
|
|
||||||
public ?string $type;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Language
|
|
||||||
*/
|
|
||||||
class BisCompanyLanguage extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical company forms
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bankruptcy, liquidation or restructuring proceedings
|
|
||||||
*/
|
|
||||||
public string $name = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of liquidation
|
|
||||||
*/
|
|
||||||
public string $type = "";
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Liquidation
|
|
||||||
*/
|
|
||||||
class BisCompanyLiquidation extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical company forms
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bankruptcy, liquidation or restructuring proceedings
|
|
||||||
*/
|
|
||||||
public string $name = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of liquidation
|
|
||||||
*/
|
|
||||||
public string $type = "";
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Name
|
|
||||||
*/
|
|
||||||
class BisCompanyName extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Order
|
|
||||||
*
|
|
||||||
* Zero for primary company name,
|
|
||||||
* other for translations of the primary company name
|
|
||||||
* and auxiliary company names
|
|
||||||
*/
|
|
||||||
public int $order;
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical company names
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company name
|
|
||||||
*/
|
|
||||||
public string $name = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Exceptions\UnexpectedValueException;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Registered Entry
|
|
||||||
*/
|
|
||||||
class BisCompanyRegisteredEntry extends DataTransferObject
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Description of entry
|
|
||||||
*/
|
|
||||||
public string $description = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zero for common entries, one for ‘Unregistered’ and two for ‘Registered’
|
|
||||||
*/
|
|
||||||
public int $status;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* register (int):
|
|
||||||
* - One for Trade Register,
|
|
||||||
* - two for Register of Foundations,
|
|
||||||
* - three for Register of Associations,
|
|
||||||
* - four for Tax Administration,
|
|
||||||
* - five for Prepayment Register,
|
|
||||||
* - six for VAT Register,
|
|
||||||
* - seven for Employer Register and
|
|
||||||
* - eight for register of bodies liable for tax on insurance premiums
|
|
||||||
*
|
|
||||||
* @see getRegisterText()
|
|
||||||
*/
|
|
||||||
public int $register;
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language;
|
|
||||||
/**
|
|
||||||
* authority (int):
|
|
||||||
* - One for Tax Administration,
|
|
||||||
* - two for Finnish Patent and Registration Office and
|
|
||||||
* - three for Population Register
|
|
||||||
*
|
|
||||||
* @see getAuthorityText()
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public int $authority;
|
|
||||||
|
|
||||||
public function getStatusText(): string
|
|
||||||
{
|
|
||||||
// Zero for common entries, one for ‘Unregistered’ and two for ‘Registered’
|
|
||||||
return match ($this->status) {
|
|
||||||
0 => "Common",
|
|
||||||
1 => "Unregistered",
|
|
||||||
2 => "Registered",
|
|
||||||
default => throw new UnexpectedValueException("Unexpected value: " . $this->status),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRegisterText(): string
|
|
||||||
{
|
|
||||||
return match ($this->register) {
|
|
||||||
1 => "Trade Register",
|
|
||||||
2 => "Register of Foundations",
|
|
||||||
3 => "Register of Associations",
|
|
||||||
4 => "Tax Administration",
|
|
||||||
5 => "Prepayment Register",
|
|
||||||
6 => "VAT Register",
|
|
||||||
7 => "Employer Register",
|
|
||||||
8 => "register of bodies liable for tax on insurance premiums",
|
|
||||||
default => throw new UnexpectedValueException("Unexpected value: " . $this->register),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAuthorityText(): string
|
|
||||||
{
|
|
||||||
return match ($this->authority) {
|
|
||||||
1 => "Tax Administration",
|
|
||||||
2 => "Finnish Patent and Registration Office",
|
|
||||||
3 => "Population Register",
|
|
||||||
default => throw new UnexpectedValueException("Unexpected value: " . $this->authority),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Dto;
|
|
||||||
|
|
||||||
use Ivuorinen\BusinessDataFetcher\Traits\HasSource;
|
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Company Registered Office
|
|
||||||
*/
|
|
||||||
class BisCompanyRegisteredOffice extends DataTransferObject
|
|
||||||
{
|
|
||||||
use HasSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zero for primary place of registered office, positive for others
|
|
||||||
*/
|
|
||||||
public int $order;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One for current version and >1 for historical places of registered office
|
|
||||||
*/
|
|
||||||
public int $version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date of registration
|
|
||||||
*/
|
|
||||||
public string $registrationDate = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ending date of registration
|
|
||||||
*/
|
|
||||||
public ?string $endDate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of place of registered office
|
|
||||||
*/
|
|
||||||
public string $name = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Two letter language code
|
|
||||||
*/
|
|
||||||
public ?string $language = null;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Exceptions;
|
|
||||||
|
|
||||||
class ApiResponseErrorException extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Exceptions;
|
|
||||||
|
|
||||||
class UnexpectedValueException extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
73
src/Http/AbstractClient.php
Normal file
73
src/Http/AbstractClient.php
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\Http;
|
||||||
|
|
||||||
|
use CuyZ\Valinor\Mapper\TreeMapper;
|
||||||
|
use CuyZ\Valinor\MapperBuilder;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base HTTP client for PRH API communication.
|
||||||
|
*
|
||||||
|
* Provides shared Guzzle HTTP client and Valinor mapper instances
|
||||||
|
* for concrete API client implementations.
|
||||||
|
*/
|
||||||
|
abstract class AbstractClient
|
||||||
|
{
|
||||||
|
protected Client $httpClient;
|
||||||
|
|
||||||
|
protected TreeMapper $mapper;
|
||||||
|
|
||||||
|
/** Initialize HTTP client and Valinor mapper. */
|
||||||
|
public function __construct(?Client $httpClient = null)
|
||||||
|
{
|
||||||
|
$this->httpClient = $httpClient ?? HttpClientFactory::create(
|
||||||
|
$this->getBaseUri(),
|
||||||
|
$this->getTimeout()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->mapper = (new MapperBuilder())
|
||||||
|
->allowSuperfluousKeys()
|
||||||
|
->mapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the base URI for the API. */
|
||||||
|
abstract protected function getBaseUri(): string;
|
||||||
|
|
||||||
|
/** Get the HTTP request timeout in seconds. */
|
||||||
|
protected function getTimeout(): int
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a GET request and decode the JSON response.
|
||||||
|
*
|
||||||
|
* @param array<string, mixed> $query
|
||||||
|
* @return array<mixed>
|
||||||
|
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||||
|
* @throws \JsonException
|
||||||
|
*/
|
||||||
|
protected function getJson(string $uri, array $query = []): array
|
||||||
|
{
|
||||||
|
$options = [];
|
||||||
|
if ($query !== []) {
|
||||||
|
$options['query'] = $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $this->httpClient->get($uri, $options);
|
||||||
|
|
||||||
|
$data = json_decode(
|
||||||
|
$response->getBody()->getContents(),
|
||||||
|
true,
|
||||||
|
512,
|
||||||
|
JSON_THROW_ON_ERROR
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!is_array($data)) {
|
||||||
|
throw new \JsonException('Response is not a valid JSON object or array');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/Http/HttpClientFactory.php
Normal file
18
src/Http/HttpClientFactory.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\Http;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
|
||||||
|
/** Factory for creating pre-configured Guzzle HTTP clients. */
|
||||||
|
class HttpClientFactory
|
||||||
|
{
|
||||||
|
/** Create a Guzzle client with the given base URI and timeout. */
|
||||||
|
public static function create(string $baseUri, int $timeout = 10): Client
|
||||||
|
{
|
||||||
|
return new Client([
|
||||||
|
'base_uri' => $baseUri,
|
||||||
|
'timeout' => $timeout,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Ivuorinen\BusinessDataFetcher\Traits;
|
|
||||||
|
|
||||||
trait HasSource
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Source of the information.
|
|
||||||
*
|
|
||||||
* source (integer, optional):
|
|
||||||
* - Zero for common,
|
|
||||||
* - one for Finnish Patent and Registration Office,
|
|
||||||
* - two for Tax Administration or
|
|
||||||
* - three for Business Information System
|
|
||||||
*
|
|
||||||
* Use `getSourceText()` to get the text representation.
|
|
||||||
*
|
|
||||||
* @see getSourceText()
|
|
||||||
*
|
|
||||||
* @var int|null
|
|
||||||
*/
|
|
||||||
public ?int $source;
|
|
||||||
|
|
||||||
public function getSourceText(): string
|
|
||||||
{
|
|
||||||
return match ($this->source) {
|
|
||||||
0 => 'common',
|
|
||||||
1 => 'Finnish Patent and Registration Office',
|
|
||||||
2 => 'Tax Administration',
|
|
||||||
3 => 'Business Information System',
|
|
||||||
default => '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
27
src/v1/Dto/BisAddress.php
Normal file
27
src/v1/Dto/BisAddress.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a postal or visiting address from the BIS v1 API. */
|
||||||
|
final readonly class BisAddress
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $type = 0,
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public ?string $careOf = null,
|
||||||
|
public ?string $street = null,
|
||||||
|
public ?string $postCode = null,
|
||||||
|
public ?string $city = null,
|
||||||
|
public ?string $country = null,
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/v1/Dto/BisCompanyBusinessIdChange.php
Normal file
25
src/v1/Dto/BisCompanyBusinessIdChange.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a business ID change event (e.g. fusion, division). */
|
||||||
|
final readonly class BisCompanyBusinessIdChange
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
use Traits\HasChange;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $description = '',
|
||||||
|
public string $reason = '',
|
||||||
|
public ?string $changeDate = null,
|
||||||
|
public string $oldBusinessId = '',
|
||||||
|
public string $newBusinessId = '',
|
||||||
|
public ?int $source = null,
|
||||||
|
public ?string $language = null,
|
||||||
|
public string|int|null $change = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/v1/Dto/BisCompanyBusinessLine.php
Normal file
23
src/v1/Dto/BisCompanyBusinessLine.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a company's line of business (industry classification). */
|
||||||
|
final readonly class BisCompanyBusinessLine
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $order = 0,
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public string $name = '',
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/v1/Dto/BisCompanyContactDetail.php
Normal file
23
src/v1/Dto/BisCompanyContactDetail.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a company contact detail (phone, email, website, etc.). */
|
||||||
|
final readonly class BisCompanyContactDetail
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public string $value = '',
|
||||||
|
public string $type = '',
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/v1/Dto/BisCompanyDetails.php
Normal file
40
src/v1/Dto/BisCompanyDetails.php
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
/** Top-level DTO for a company record from the BIS v1 API. */
|
||||||
|
final readonly class BisCompanyDetails
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param list<BisCompanyName> $names
|
||||||
|
* @param list<BisCompanyName> $auxiliaryNames
|
||||||
|
* @param list<BisAddress> $addresses
|
||||||
|
* @param list<BisCompanyForm> $companyForms
|
||||||
|
* @param list<BisCompanyLiquidation> $liquidations
|
||||||
|
* @param list<BisCompanyBusinessLine> $businessLines
|
||||||
|
* @param list<BisCompanyLanguage> $languages
|
||||||
|
* @param list<BisCompanyRegisteredOffice> $registeredOffices
|
||||||
|
* @param list<BisCompanyContactDetail> $contactDetails
|
||||||
|
* @param list<BisCompanyRegisteredEntry> $registeredEntries
|
||||||
|
* @param list<BisCompanyBusinessIdChange> $businessIdChanges
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public string $businessId = '',
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $companyForm = null,
|
||||||
|
public ?string $detailsUri = null,
|
||||||
|
public string $name = '',
|
||||||
|
public array $names = [],
|
||||||
|
public array $auxiliaryNames = [],
|
||||||
|
public array $addresses = [],
|
||||||
|
public array $companyForms = [],
|
||||||
|
public array $liquidations = [],
|
||||||
|
public array $businessLines = [],
|
||||||
|
public array $languages = [],
|
||||||
|
public array $registeredOffices = [],
|
||||||
|
public array $contactDetails = [],
|
||||||
|
public array $registeredEntries = [],
|
||||||
|
public array $businessIdChanges = [],
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/v1/Dto/BisCompanyForm.php
Normal file
23
src/v1/Dto/BisCompanyForm.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a company's legal form (e.g. Ltd, cooperative). */
|
||||||
|
final readonly class BisCompanyForm
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public string $name = '',
|
||||||
|
public ?string $type = null,
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/v1/Dto/BisCompanyLanguage.php
Normal file
22
src/v1/Dto/BisCompanyLanguage.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a company's registered language. */
|
||||||
|
final readonly class BisCompanyLanguage
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public string $name = '',
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/v1/Dto/BisCompanyLiquidation.php
Normal file
23
src/v1/Dto/BisCompanyLiquidation.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a company liquidation or bankruptcy entry. */
|
||||||
|
final readonly class BisCompanyLiquidation
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public string $name = '',
|
||||||
|
public string $type = '',
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/v1/Dto/BisCompanyName.php
Normal file
23
src/v1/Dto/BisCompanyName.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a company name or auxiliary name entry. */
|
||||||
|
final readonly class BisCompanyName
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $order = 0,
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public string $name = '',
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/v1/Dto/BisCompanyRegisteredEntry.php
Normal file
24
src/v1/Dto/BisCompanyRegisteredEntry.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a registration entry in a public register. */
|
||||||
|
final readonly class BisCompanyRegisteredEntry
|
||||||
|
{
|
||||||
|
use Traits\HasAuthority;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
use Traits\HasRegister;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public string $description = '',
|
||||||
|
public int $status = 0,
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public int $authority = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
public int|null $register = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/v1/Dto/BisCompanyRegisteredOffice.php
Normal file
23
src/v1/Dto/BisCompanyRegisteredOffice.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Dto;
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Represents a company's registered office (domicile). */
|
||||||
|
final readonly class BisCompanyRegisteredOffice
|
||||||
|
{
|
||||||
|
use Traits\HasSource;
|
||||||
|
use Traits\HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public int $order = 0,
|
||||||
|
public string $registrationDate = '',
|
||||||
|
public ?string $endDate = null,
|
||||||
|
public string $name = '',
|
||||||
|
public ?int $source = null,
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $language = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/v1/Exceptions/ApiResponseErrorException.php
Normal file
10
src/v1/Exceptions/ApiResponseErrorException.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/** Thrown when the BIS v1 API returns an error response. */
|
||||||
|
class ApiResponseErrorException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
10
src/v1/Exceptions/UnexpectedValueException.php
Normal file
10
src/v1/Exceptions/UnexpectedValueException.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/** Thrown when the BIS v1 API returns an unexpected value. */
|
||||||
|
class UnexpectedValueException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
18
src/v1/Traits/HasAuthority.php
Normal file
18
src/v1/Traits/HasAuthority.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Provides a human-readable authority name from the authority code. */
|
||||||
|
trait HasAuthority
|
||||||
|
{
|
||||||
|
/** Get the authority name (e.g. "Tax Administration"). */
|
||||||
|
public function getAuthorityString(): string
|
||||||
|
{
|
||||||
|
return match ($this->authority) {
|
||||||
|
1 => 'Tax Administration',
|
||||||
|
2 => 'Finnish Patent and Registration Office',
|
||||||
|
3 => 'Population Register',
|
||||||
|
default => 'unknown:' . $this->authority,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/v1/Traits/HasChange.php
Normal file
25
src/v1/Traits/HasChange.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Provides a human-readable description of a business ID change reason. */
|
||||||
|
trait HasChange
|
||||||
|
{
|
||||||
|
/** Get the change reason description (e.g. "Fusion", "Division"). */
|
||||||
|
public function getChangeString(): string
|
||||||
|
{
|
||||||
|
return match ($this->change) {
|
||||||
|
2 => 'Business ID removal',
|
||||||
|
3 => 'Combining of double IDs',
|
||||||
|
5 => 'ID changed',
|
||||||
|
44, 'FUU' => 'Fusion',
|
||||||
|
45 => 'Operator continuing VAT activities',
|
||||||
|
46 => 'Relation to predecessor',
|
||||||
|
47, 'DIF' => 'Division',
|
||||||
|
48 => 'Bankruptcy relationship',
|
||||||
|
49 => 'Operations continued by a private trader',
|
||||||
|
57 => 'Partial division',
|
||||||
|
default => 'unknown:' . $this->change,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/v1/Traits/HasLanguage.php
Normal file
22
src/v1/Traits/HasLanguage.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Provides a human-readable language name from a language code. */
|
||||||
|
trait HasLanguage
|
||||||
|
{
|
||||||
|
/** Get the language name (e.g. "finnish", "english", "swedish"). */
|
||||||
|
public function getLanguageString(): string
|
||||||
|
{
|
||||||
|
if ($this->language === null) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($this->language) {
|
||||||
|
'fi' => 'finnish',
|
||||||
|
'en' => 'english',
|
||||||
|
'sv' => 'swedish',
|
||||||
|
default => 'unknown:' . $this->language,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/v1/Traits/HasRegister.php
Normal file
23
src/v1/Traits/HasRegister.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Provides a human-readable register name from the register code. */
|
||||||
|
trait HasRegister
|
||||||
|
{
|
||||||
|
/** Get the register name (e.g. "Trade Register", "VAT Register"). */
|
||||||
|
public function getRegisterString(): string
|
||||||
|
{
|
||||||
|
return match ($this->register) {
|
||||||
|
1 => 'Trade Register',
|
||||||
|
2 => 'Register of Foundations',
|
||||||
|
3 => 'Register of Associations',
|
||||||
|
4 => 'Tax Administration',
|
||||||
|
5 => 'Prepayment Register',
|
||||||
|
6 => 'VAT Register',
|
||||||
|
7 => 'Employer Register',
|
||||||
|
8 => 'Register of bodies liable for tax on insurance premiums',
|
||||||
|
default => 'unknown:' . $this->register,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/v1/Traits/HasSource.php
Normal file
19
src/v1/Traits/HasSource.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v1\Traits;
|
||||||
|
|
||||||
|
/** Provides a human-readable data source name from the source code. */
|
||||||
|
trait HasSource
|
||||||
|
{
|
||||||
|
/** Get the data source name (e.g. "Tax Administration", "PRH"). */
|
||||||
|
public function getSourceText(): string
|
||||||
|
{
|
||||||
|
return match ($this->source) {
|
||||||
|
0 => 'common',
|
||||||
|
1 => 'Finnish Patent and Registration Office',
|
||||||
|
2 => 'Tax Administration',
|
||||||
|
3 => 'Business Information System',
|
||||||
|
default => '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
124
src/v3/Client.php
Normal file
124
src/v3/Client.php
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3;
|
||||||
|
|
||||||
|
use GuzzleHttp\Exception\RequestException;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\Http\AbstractClient;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Dto\CompanySearchResult;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Dto\PostCodeEntry;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Exceptions\V3ApiException;
|
||||||
|
use Psr\Http\Message\StreamInterface;
|
||||||
|
|
||||||
|
/** Client for the PRH YTJ v3 API (Finnish business data). */
|
||||||
|
class Client extends AbstractClient
|
||||||
|
{
|
||||||
|
private const API_PREFIX = '/opendata-ytj-api/v3';
|
||||||
|
|
||||||
|
/** @inheritDoc */
|
||||||
|
protected function getBaseUri(): string
|
||||||
|
{
|
||||||
|
return 'https://avoindata.prh.fi';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for companies.
|
||||||
|
*
|
||||||
|
* @throws V3ApiException
|
||||||
|
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||||
|
*/
|
||||||
|
public function searchCompanies(
|
||||||
|
?string $name = null,
|
||||||
|
?string $businessId = null,
|
||||||
|
?string $location = null,
|
||||||
|
?string $companyForm = null,
|
||||||
|
?string $mainBusinessLine = null,
|
||||||
|
?string $registrationDateStart = null,
|
||||||
|
?string $registrationDateEnd = null,
|
||||||
|
?string $postCode = null,
|
||||||
|
?string $businessIdRegistrationStart = null,
|
||||||
|
?string $businessIdRegistrationEnd = null,
|
||||||
|
?int $page = null,
|
||||||
|
): CompanySearchResult {
|
||||||
|
$query = array_filter([
|
||||||
|
'name' => $name,
|
||||||
|
'businessId' => $businessId,
|
||||||
|
'location' => $location,
|
||||||
|
'companyForm' => $companyForm,
|
||||||
|
'mainBusinessLine' => $mainBusinessLine,
|
||||||
|
'registrationDateStart' => $registrationDateStart,
|
||||||
|
'registrationDateEnd' => $registrationDateEnd,
|
||||||
|
'postCode' => $postCode,
|
||||||
|
'businessIdRegistrationStart' => $businessIdRegistrationStart,
|
||||||
|
'businessIdRegistrationEnd' => $businessIdRegistrationEnd,
|
||||||
|
'page' => $page,
|
||||||
|
], fn (string|int|null $v): bool => $v !== null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$data = $this->getJson(self::API_PREFIX . '/companies', $query);
|
||||||
|
return $this->mapper->map(CompanySearchResult::class, $data);
|
||||||
|
} catch (RequestException | \JsonException $e) {
|
||||||
|
throw new V3ApiException($e->getMessage(), (int) $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve code list description.
|
||||||
|
*
|
||||||
|
* @throws V3ApiException
|
||||||
|
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||||
|
*/
|
||||||
|
public function getDescription(string $code, string $lang = 'en'): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$response = $this->httpClient->get(self::API_PREFIX . '/description', [
|
||||||
|
'query' => ['code' => $code, 'lang' => $lang],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response->getBody()->getContents();
|
||||||
|
} catch (RequestException $e) {
|
||||||
|
throw new V3ApiException($e->getMessage(), $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve postal code details.
|
||||||
|
*
|
||||||
|
* @return PostCodeEntry[]
|
||||||
|
* @throws V3ApiException
|
||||||
|
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||||
|
*/
|
||||||
|
public function getPostCodes(string $lang = 'en'): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->getJson(self::API_PREFIX . '/post_codes', ['lang' => $lang]);
|
||||||
|
|
||||||
|
$results = [];
|
||||||
|
foreach ($data as $entry) {
|
||||||
|
$results[] = $this->mapper->map(PostCodeEntry::class, $entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
} catch (RequestException | \JsonException $e) {
|
||||||
|
throw new V3ApiException($e->getMessage(), (int) $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all companies as a ZIP download stream.
|
||||||
|
*
|
||||||
|
* @throws V3ApiException
|
||||||
|
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||||
|
*/
|
||||||
|
public function getAllCompanies(): StreamInterface
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$response = $this->httpClient->get(self::API_PREFIX . '/all_companies', [
|
||||||
|
'stream' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response->getBody();
|
||||||
|
} catch (RequestException $e) {
|
||||||
|
throw new V3ApiException($e->getMessage(), $e->getCode(), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/v3/Dto/Address.php
Normal file
28
src/v3/Dto/Address.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a postal or visiting address from the YTJ v3 API. */
|
||||||
|
final readonly class Address
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param list<PostOffice> $postOffices
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public int $type = 0,
|
||||||
|
public string $source = '',
|
||||||
|
public ?string $street = null,
|
||||||
|
public ?string $postCode = null,
|
||||||
|
public array $postOffices = [],
|
||||||
|
public ?string $postOfficeBox = null,
|
||||||
|
public ?string $buildingNumber = null,
|
||||||
|
public ?string $entrance = null,
|
||||||
|
public ?string $apartmentNumber = null,
|
||||||
|
public ?string $apartmentIdSuffix = null,
|
||||||
|
public ?string $co = null,
|
||||||
|
public ?string $country = null,
|
||||||
|
public ?string $freeAddressLine = null,
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/v3/Dto/BusinessId.php
Normal file
14
src/v3/Dto/BusinessId.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a Finnish business ID (Y-tunnus) with registration metadata. */
|
||||||
|
final readonly class BusinessId
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $value,
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $source = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/v3/Dto/BusinessLine.php
Normal file
19
src/v3/Dto/BusinessLine.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a company's line of business (industry classification) from the YTJ v3 API. */
|
||||||
|
final readonly class BusinessLine
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param list<DescriptionEntry> $descriptions
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public string $code,
|
||||||
|
public array $descriptions = [],
|
||||||
|
public ?string $typeCodeSet = null,
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $source = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/v3/Dto/Company.php
Normal file
32
src/v3/Dto/Company.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Top-level DTO for a company record from the YTJ v3 API. */
|
||||||
|
final readonly class Company
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param list<RegisterName> $names
|
||||||
|
* @param list<CompanyForm> $companyForms
|
||||||
|
* @param list<CompanySituation> $companySituations
|
||||||
|
* @param list<RegisteredEntry> $registeredEntries
|
||||||
|
* @param list<Address> $addresses
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public BusinessId $businessId,
|
||||||
|
public string $tradeRegisterStatus = '',
|
||||||
|
public string $lastModified = '',
|
||||||
|
public ?EuId $euId = null,
|
||||||
|
public array $names = [],
|
||||||
|
public ?BusinessLine $mainBusinessLine = null,
|
||||||
|
public ?Website $website = null,
|
||||||
|
public array $companyForms = [],
|
||||||
|
public array $companySituations = [],
|
||||||
|
public array $registeredEntries = [],
|
||||||
|
public array $addresses = [],
|
||||||
|
public ?string $status = null,
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $endDate = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/v3/Dto/CompanyForm.php
Normal file
20
src/v3/Dto/CompanyForm.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a company's legal form (e.g. Ltd, cooperative) from the YTJ v3 API. */
|
||||||
|
final readonly class CompanyForm
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param list<DescriptionEntry> $descriptions
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public string $type = '',
|
||||||
|
public string $source = '',
|
||||||
|
public int $version = 0,
|
||||||
|
public array $descriptions = [],
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $endDate = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/v3/Dto/CompanySearchResult.php
Normal file
16
src/v3/Dto/CompanySearchResult.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Paginated search result containing matched companies from the YTJ v3 API. */
|
||||||
|
final readonly class CompanySearchResult
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param list<Company> $companies
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public int $totalResults = 0,
|
||||||
|
public array $companies = [],
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/v3/Dto/CompanySituation.php
Normal file
15
src/v3/Dto/CompanySituation.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a company's operational situation (e.g. active, dissolved). */
|
||||||
|
final readonly class CompanySituation
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $type,
|
||||||
|
public string $source,
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $endDate = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/v3/Dto/DescriptionEntry.php
Normal file
13
src/v3/Dto/DescriptionEntry.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a localized description with a language code. */
|
||||||
|
final readonly class DescriptionEntry
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $languageCode = '',
|
||||||
|
public string $description = '',
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/v3/Dto/EuId.php
Normal file
13
src/v3/Dto/EuId.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a company's EU VAT identification number. */
|
||||||
|
final readonly class EuId
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $value = '',
|
||||||
|
public ?string $source = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/v3/Dto/PostCodeEntry.php
Normal file
16
src/v3/Dto/PostCodeEntry.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a Finnish postal code with associated city and municipality. */
|
||||||
|
final readonly class PostCodeEntry
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $postCode = '',
|
||||||
|
public string $city = '',
|
||||||
|
public bool $active = true,
|
||||||
|
public string $languageCode = '',
|
||||||
|
public ?string $municipalityCode = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/v3/Dto/PostOffice.php
Normal file
14
src/v3/Dto/PostOffice.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a localized post office name within an address. */
|
||||||
|
final readonly class PostOffice
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $city,
|
||||||
|
public string $languageCode,
|
||||||
|
public ?string $municipalityCode = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/v3/Dto/RegisterName.php
Normal file
17
src/v3/Dto/RegisterName.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a company name registered in a specific register. */
|
||||||
|
final readonly class RegisterName
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $name = '',
|
||||||
|
public string $type = '',
|
||||||
|
public string $source = '',
|
||||||
|
public int $version = 0,
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $endDate = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/v3/Dto/RegisteredEntry.php
Normal file
20
src/v3/Dto/RegisteredEntry.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a registration entry in a public register from the YTJ v3 API. */
|
||||||
|
final readonly class RegisteredEntry
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param list<DescriptionEntry> $descriptions
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public string $type = '',
|
||||||
|
public string $register = '',
|
||||||
|
public string $authority = '',
|
||||||
|
public array $descriptions = [],
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $endDate = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/v3/Dto/Website.php
Normal file
14
src/v3/Dto/Website.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Dto;
|
||||||
|
|
||||||
|
/** Represents a company's registered website URL. */
|
||||||
|
final readonly class Website
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $url,
|
||||||
|
public ?string $registrationDate = null,
|
||||||
|
public ?string $source = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/v3/Exceptions/V3ApiException.php
Normal file
10
src/v3/Exceptions/V3ApiException.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ivuorinen\BusinessDataFetcher\v3\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/** Thrown when the YTJ v3 API returns an error response. */
|
||||||
|
class V3ApiException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
112
tests/Fixtures/sample-response.json
Normal file
112
tests/Fixtures/sample-response.json
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"type": "fi.prh.opendata.bis",
|
||||||
|
"version": "1",
|
||||||
|
"totalResults": -1,
|
||||||
|
"resultsFrom": 0,
|
||||||
|
"previousResultsUri": null,
|
||||||
|
"nextResultsUri": null,
|
||||||
|
"exceptionNoticeUri": null,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"businessId": "1639413-9",
|
||||||
|
"registrationDate": "2001-04-03",
|
||||||
|
"companyForm": "OY",
|
||||||
|
"detailsUri": null,
|
||||||
|
"name": "Oy Example Ab",
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"order": 0,
|
||||||
|
"version": 1,
|
||||||
|
"registrationDate": "2015-01-19",
|
||||||
|
"endDate": null,
|
||||||
|
"name": "Oy Example Ab",
|
||||||
|
"source": 0,
|
||||||
|
"language": "fi"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"auxiliaryNames": [],
|
||||||
|
"addresses": [
|
||||||
|
{
|
||||||
|
"careOf": null,
|
||||||
|
"street": "Testitie 1",
|
||||||
|
"postCode": "00100",
|
||||||
|
"type": 1,
|
||||||
|
"city": "HELSINKI",
|
||||||
|
"country": "FI",
|
||||||
|
"source": 0,
|
||||||
|
"version": 1,
|
||||||
|
"registrationDate": "2019-04-30",
|
||||||
|
"endDate": null,
|
||||||
|
"language": "fi"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"companyForms": [
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"registrationDate": "2001-04-03",
|
||||||
|
"endDate": null,
|
||||||
|
"name": "Osakeyhtiö",
|
||||||
|
"type": "OY",
|
||||||
|
"source": 0,
|
||||||
|
"language": "fi"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"liquidations": [],
|
||||||
|
"businessLines": [
|
||||||
|
{
|
||||||
|
"order": 0,
|
||||||
|
"version": 1,
|
||||||
|
"registrationDate": "2017-12-31",
|
||||||
|
"endDate": null,
|
||||||
|
"name": "Computer programming activities",
|
||||||
|
"source": 2,
|
||||||
|
"language": "en"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"registrationDate": "2001-04-03",
|
||||||
|
"endDate": null,
|
||||||
|
"name": "Finnish",
|
||||||
|
"source": 0,
|
||||||
|
"language": "en"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"registeredOffices": [
|
||||||
|
{
|
||||||
|
"order": 0,
|
||||||
|
"version": 1,
|
||||||
|
"registrationDate": "2001-04-03",
|
||||||
|
"endDate": null,
|
||||||
|
"name": "HELSINKI",
|
||||||
|
"source": 0,
|
||||||
|
"language": "fi"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contactDetails": [
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"registrationDate": "2019-04-30",
|
||||||
|
"endDate": null,
|
||||||
|
"language": "fi",
|
||||||
|
"value": "www.example.fi",
|
||||||
|
"type": "Website",
|
||||||
|
"source": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"registeredEntries": [
|
||||||
|
{
|
||||||
|
"authority": 2,
|
||||||
|
"register": 1,
|
||||||
|
"status": 2,
|
||||||
|
"registrationDate": "2001-06-01",
|
||||||
|
"endDate": null,
|
||||||
|
"description": "Registered",
|
||||||
|
"language": "en"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"businessIdChanges": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
101
tests/Fixtures/v3-search-response.json
Normal file
101
tests/Fixtures/v3-search-response.json
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
{
|
||||||
|
"totalResults": 1,
|
||||||
|
"companies": [
|
||||||
|
{
|
||||||
|
"businessId": {
|
||||||
|
"value": "1639413-9",
|
||||||
|
"registrationDate": "2001-04-03",
|
||||||
|
"source": "YTJ"
|
||||||
|
},
|
||||||
|
"euId": {
|
||||||
|
"value": "FIFOO123456",
|
||||||
|
"source": "YTJ"
|
||||||
|
},
|
||||||
|
"names": [
|
||||||
|
{
|
||||||
|
"name": "Oy Example Ab",
|
||||||
|
"type": "TOIM",
|
||||||
|
"registrationDate": "2015-01-19",
|
||||||
|
"endDate": null,
|
||||||
|
"version": 1,
|
||||||
|
"source": "YTJ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mainBusinessLine": {
|
||||||
|
"code": "62010",
|
||||||
|
"descriptions": [
|
||||||
|
{
|
||||||
|
"languageCode": "3",
|
||||||
|
"description": "Computer programming activities"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeCodeSet": "TOL2008",
|
||||||
|
"registrationDate": "2017-12-31",
|
||||||
|
"source": "VERO"
|
||||||
|
},
|
||||||
|
"website": {
|
||||||
|
"url": "www.example.fi",
|
||||||
|
"registrationDate": "2019-04-30",
|
||||||
|
"source": "YTJ"
|
||||||
|
},
|
||||||
|
"companyForms": [
|
||||||
|
{
|
||||||
|
"type": "OY",
|
||||||
|
"descriptions": [
|
||||||
|
{
|
||||||
|
"languageCode": "1",
|
||||||
|
"description": "Osakeyhtiö"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"languageCode": "3",
|
||||||
|
"description": "Limited company"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"registrationDate": "2001-04-03",
|
||||||
|
"endDate": null,
|
||||||
|
"version": 1,
|
||||||
|
"source": "YTJ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"companySituations": [],
|
||||||
|
"registeredEntries": [
|
||||||
|
{
|
||||||
|
"type": "REK",
|
||||||
|
"descriptions": [
|
||||||
|
{
|
||||||
|
"languageCode": "3",
|
||||||
|
"description": "Registered"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"registrationDate": "2001-06-01",
|
||||||
|
"endDate": null,
|
||||||
|
"register": "1",
|
||||||
|
"authority": "2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addresses": [
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"street": "Testitie 1",
|
||||||
|
"postCode": "00100",
|
||||||
|
"postOffices": [
|
||||||
|
{
|
||||||
|
"city": "HELSINKI",
|
||||||
|
"languageCode": "1",
|
||||||
|
"municipalityCode": "091"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"co": null,
|
||||||
|
"country": "FI",
|
||||||
|
"registrationDate": "2019-04-30",
|
||||||
|
"source": "YTJ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tradeRegisterStatus": "2",
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"registrationDate": "2001-04-03",
|
||||||
|
"endDate": null,
|
||||||
|
"lastModified": "2023-06-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
9
tests/Pest.php
Normal file
9
tests/Pest.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Test Case
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// uses(Tests\TestCase::class)->in('Feature');
|
||||||
52
tests/Unit/BusinessDataFetcherTest.php
Normal file
52
tests/Unit/BusinessDataFetcherTest.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Handler\MockHandler;
|
||||||
|
use GuzzleHttp\HandlerStack;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\BusinessDataFetcher;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyDetails;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Exceptions\ApiResponseErrorException;
|
||||||
|
|
||||||
|
function createFetcherWithMock(Response ...$responses): BusinessDataFetcher
|
||||||
|
{
|
||||||
|
$mock = new MockHandler($responses);
|
||||||
|
$client = new Client(['handler' => HandlerStack::create($mock)]);
|
||||||
|
return new BusinessDataFetcher($client);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns BisCompanyDetails array on success', function () {
|
||||||
|
$json = file_get_contents(__DIR__ . '/../Fixtures/sample-response.json');
|
||||||
|
$fetcher = createFetcherWithMock(new Response(200, [], $json));
|
||||||
|
|
||||||
|
$results = $fetcher->getBusinessInformation('1639413-9');
|
||||||
|
|
||||||
|
expect($results)->toBeArray()
|
||||||
|
->and($results)->toHaveCount(1)
|
||||||
|
->and($results[0])->toBeInstanceOf(BisCompanyDetails::class)
|
||||||
|
->and($results[0]->businessId)->toBe('1639413-9');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws on non-200 status code', function () {
|
||||||
|
$fetcher = createFetcherWithMock(
|
||||||
|
new Response(500, [], '{"error": "Internal Server Error"}')
|
||||||
|
);
|
||||||
|
|
||||||
|
$fetcher->getBusinessInformation('1639413-9');
|
||||||
|
})->throws(ApiResponseErrorException::class);
|
||||||
|
|
||||||
|
it('throws on malformed JSON', function () {
|
||||||
|
$fetcher = createFetcherWithMock(
|
||||||
|
new Response(200, [], 'not-json')
|
||||||
|
);
|
||||||
|
|
||||||
|
$fetcher->getBusinessInformation('1639413-9');
|
||||||
|
})->throws(JsonException::class);
|
||||||
|
|
||||||
|
it('throws when results key is missing', function () {
|
||||||
|
$fetcher = createFetcherWithMock(
|
||||||
|
new Response(200, [], '{"type": "test"}')
|
||||||
|
);
|
||||||
|
|
||||||
|
$fetcher->getBusinessInformation('1639413-9');
|
||||||
|
})->throws(ApiResponseErrorException::class);
|
||||||
43
tests/Unit/v1/Dto/BisCompanyDetailsTest.php
Normal file
43
tests/Unit/v1/Dto/BisCompanyDetailsTest.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use CuyZ\Valinor\MapperBuilder;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyDetails;
|
||||||
|
|
||||||
|
it('hydrates from sample JSON fixture', function () {
|
||||||
|
$json = json_decode(
|
||||||
|
file_get_contents(__DIR__ . '/../../../Fixtures/sample-response.json'),
|
||||||
|
true,
|
||||||
|
512,
|
||||||
|
JSON_THROW_ON_ERROR
|
||||||
|
);
|
||||||
|
|
||||||
|
$mapper = (new MapperBuilder())
|
||||||
|
->allowSuperfluousKeys()
|
||||||
|
->mapper();
|
||||||
|
|
||||||
|
$result = $mapper->map(BisCompanyDetails::class, $json['results'][0]);
|
||||||
|
|
||||||
|
expect($result)
|
||||||
|
->toBeInstanceOf(BisCompanyDetails::class)
|
||||||
|
->and($result->businessId)->toBe('1639413-9')
|
||||||
|
->and($result->registrationDate)->toBe('2001-04-03')
|
||||||
|
->and($result->companyForm)->toBe('OY')
|
||||||
|
->and($result->name)->toBe('Oy Example Ab')
|
||||||
|
->and($result->names)->toHaveCount(1)
|
||||||
|
->and($result->names[0]->name)->toBe('Oy Example Ab')
|
||||||
|
->and($result->names[0]->getLanguageString())->toBe('finnish')
|
||||||
|
->and($result->names[0]->getSourceText())->toBe('common')
|
||||||
|
->and($result->addresses)->toHaveCount(1)
|
||||||
|
->and($result->addresses[0]->street)->toBe('Testitie 1')
|
||||||
|
->and($result->addresses[0]->postCode)->toBe('00100')
|
||||||
|
->and($result->addresses[0]->city)->toBe('HELSINKI')
|
||||||
|
->and($result->companyForms)->toHaveCount(1)
|
||||||
|
->and($result->companyForms[0]->name)->toBe('Osakeyhtiö')
|
||||||
|
->and($result->businessLines)->toHaveCount(1)
|
||||||
|
->and($result->businessLines[0]->name)->toBe('Computer programming activities')
|
||||||
|
->and($result->registeredEntries)->toHaveCount(1)
|
||||||
|
->and($result->registeredEntries[0]->getAuthorityString())->toBe('Finnish Patent and Registration Office')
|
||||||
|
->and($result->registeredEntries[0]->getRegisterString())->toBe('Trade Register')
|
||||||
|
->and($result->contactDetails)->toHaveCount(1)
|
||||||
|
->and($result->contactDetails[0]->value)->toBe('www.example.fi');
|
||||||
|
});
|
||||||
87
tests/Unit/v1/Dto/DtoHydrationTest.php
Normal file
87
tests/Unit/v1/Dto/DtoHydrationTest.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use CuyZ\Valinor\MapperBuilder;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisAddress;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyBusinessIdChange;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyBusinessLine;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyContactDetail;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyForm;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyLanguage;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyLiquidation;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyName;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyRegisteredEntry;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Dto\BisCompanyRegisteredOffice;
|
||||||
|
|
||||||
|
function valinorMapper(): CuyZ\Valinor\Mapper\TreeMapper
|
||||||
|
{
|
||||||
|
return (new MapperBuilder())
|
||||||
|
->allowSuperfluousKeys()
|
||||||
|
->mapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
it('hydrates all DTOs from arrays', function (string $class, array $data, string $property, mixed $expected) {
|
||||||
|
$dto = valinorMapper()->map($class, $data);
|
||||||
|
expect($dto)->toBeInstanceOf($class)
|
||||||
|
->and($dto->$property)->toBe($expected);
|
||||||
|
})->with([
|
||||||
|
'BisAddress' => [
|
||||||
|
BisAddress::class,
|
||||||
|
['type' => 1, 'street' => 'Katu 1', 'postCode' => '00100', 'city' => 'HELSINKI', 'source' => 0, 'version' => 1, 'language' => 'fi', 'registrationDate' => '2020-01-01'],
|
||||||
|
'street',
|
||||||
|
'Katu 1',
|
||||||
|
],
|
||||||
|
'BisCompanyName' => [
|
||||||
|
BisCompanyName::class,
|
||||||
|
['order' => 0, 'name' => 'Test Oy', 'source' => 1, 'version' => 1, 'language' => 'fi', 'registrationDate' => '2020-01-01'],
|
||||||
|
'name',
|
||||||
|
'Test Oy',
|
||||||
|
],
|
||||||
|
'BisCompanyForm' => [
|
||||||
|
BisCompanyForm::class,
|
||||||
|
['name' => 'Osakeyhtiö', 'type' => 'OY', 'source' => 0, 'version' => 1, 'language' => 'fi', 'registrationDate' => '2020-01-01'],
|
||||||
|
'type',
|
||||||
|
'OY',
|
||||||
|
],
|
||||||
|
'BisCompanyBusinessLine' => [
|
||||||
|
BisCompanyBusinessLine::class,
|
||||||
|
['order' => 0, 'name' => 'IT', 'source' => 2, 'version' => 1, 'language' => 'en', 'registrationDate' => '2020-01-01'],
|
||||||
|
'name',
|
||||||
|
'IT',
|
||||||
|
],
|
||||||
|
'BisCompanyLanguage' => [
|
||||||
|
BisCompanyLanguage::class,
|
||||||
|
['name' => 'Finnish', 'source' => 0, 'version' => 1, 'language' => 'fi', 'registrationDate' => '2020-01-01'],
|
||||||
|
'language',
|
||||||
|
'fi',
|
||||||
|
],
|
||||||
|
'BisCompanyRegisteredEntry' => [
|
||||||
|
BisCompanyRegisteredEntry::class,
|
||||||
|
['authority' => 2, 'register' => 1, 'status' => 2, 'description' => 'Registered', 'language' => 'en', 'registrationDate' => '2020-01-01'],
|
||||||
|
'description',
|
||||||
|
'Registered',
|
||||||
|
],
|
||||||
|
'BisCompanyLiquidation' => [
|
||||||
|
BisCompanyLiquidation::class,
|
||||||
|
['name' => 'Bankruptcy', 'type' => 'K', 'source' => 0, 'version' => 1, 'language' => 'fi', 'registrationDate' => '2020-01-01'],
|
||||||
|
'name',
|
||||||
|
'Bankruptcy',
|
||||||
|
],
|
||||||
|
'BisCompanyRegisteredOffice' => [
|
||||||
|
BisCompanyRegisteredOffice::class,
|
||||||
|
['order' => 0, 'name' => 'Helsinki', 'source' => 0, 'version' => 1, 'language' => 'fi', 'registrationDate' => '2020-01-01'],
|
||||||
|
'name',
|
||||||
|
'Helsinki',
|
||||||
|
],
|
||||||
|
'BisCompanyContactDetail' => [
|
||||||
|
BisCompanyContactDetail::class,
|
||||||
|
['value' => 'www.test.fi', 'type' => 'Website', 'source' => 0, 'version' => 1, 'language' => 'fi', 'registrationDate' => '2020-01-01'],
|
||||||
|
'value',
|
||||||
|
'www.test.fi',
|
||||||
|
],
|
||||||
|
'BisCompanyBusinessIdChange' => [
|
||||||
|
BisCompanyBusinessIdChange::class,
|
||||||
|
['description' => 'Changed', 'reason' => '1', 'oldBusinessId' => '1234567-8', 'newBusinessId' => '8765432-1', 'source' => 0, 'language' => 'fi', 'change' => 5],
|
||||||
|
'oldBusinessId',
|
||||||
|
'1234567-8',
|
||||||
|
],
|
||||||
|
]);
|
||||||
30
tests/Unit/v1/Traits/HasAuthorityTest.php
Normal file
30
tests/Unit/v1/Traits/HasAuthorityTest.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits\HasAuthority;
|
||||||
|
|
||||||
|
function makeAuthorityObject(int $authority): object
|
||||||
|
{
|
||||||
|
return new class ($authority) {
|
||||||
|
use HasAuthority;
|
||||||
|
|
||||||
|
public function __construct(public int $authority)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns Tax Administration for authority 1', function () {
|
||||||
|
expect(makeAuthorityObject(1)->getAuthorityString())->toBe('Tax Administration');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns Finnish Patent and Registration Office for authority 2', function () {
|
||||||
|
expect(makeAuthorityObject(2)->getAuthorityString())->toBe('Finnish Patent and Registration Office');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns Population Register for authority 3', function () {
|
||||||
|
expect(makeAuthorityObject(3)->getAuthorityString())->toBe('Population Register');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns unknown for unknown authority', function () {
|
||||||
|
expect(makeAuthorityObject(99)->getAuthorityString())->toBe('unknown:99');
|
||||||
|
});
|
||||||
41
tests/Unit/v1/Traits/HasChangeTest.php
Normal file
41
tests/Unit/v1/Traits/HasChangeTest.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits\HasChange;
|
||||||
|
|
||||||
|
function makeChangeObject(string|int|null $change): object
|
||||||
|
{
|
||||||
|
return new class ($change) {
|
||||||
|
use HasChange;
|
||||||
|
|
||||||
|
public function __construct(public string|int|null $change)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it('maps all integer change codes correctly', function (int $code, string $expected) {
|
||||||
|
expect(makeChangeObject($code)->getChangeString())->toBe($expected);
|
||||||
|
})->with([
|
||||||
|
[2, 'Business ID removal'],
|
||||||
|
[3, 'Combining of double IDs'],
|
||||||
|
[5, 'ID changed'],
|
||||||
|
[44, 'Fusion'],
|
||||||
|
[45, 'Operator continuing VAT activities'],
|
||||||
|
[46, 'Relation to predecessor'],
|
||||||
|
[47, 'Division'],
|
||||||
|
[48, 'Bankruptcy relationship'],
|
||||||
|
[49, 'Operations continued by a private trader'],
|
||||||
|
[57, 'Partial division'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
it('maps FUU string to Fusion', function () {
|
||||||
|
expect(makeChangeObject('FUU')->getChangeString())->toBe('Fusion');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('maps DIF string to Division', function () {
|
||||||
|
expect(makeChangeObject('DIF')->getChangeString())->toBe('Division');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns unknown for unrecognized change', function () {
|
||||||
|
expect(makeChangeObject(999)->getChangeString())->toBe('unknown:999');
|
||||||
|
});
|
||||||
30
tests/Unit/v1/Traits/HasLanguageTest.php
Normal file
30
tests/Unit/v1/Traits/HasLanguageTest.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits\HasLanguage;
|
||||||
|
|
||||||
|
function makeLanguageObject(?string $language): object
|
||||||
|
{
|
||||||
|
return new class ($language) {
|
||||||
|
use HasLanguage;
|
||||||
|
|
||||||
|
public function __construct(public ?string $language)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns finnish for fi', function () {
|
||||||
|
expect(makeLanguageObject('fi')->getLanguageString())->toBe('finnish');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns english for en', function () {
|
||||||
|
expect(makeLanguageObject('en')->getLanguageString())->toBe('english');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns swedish for sv', function () {
|
||||||
|
expect(makeLanguageObject('sv')->getLanguageString())->toBe('swedish');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns unknown for unrecognized language', function () {
|
||||||
|
expect(makeLanguageObject('de')->getLanguageString())->toBe('unknown:de');
|
||||||
|
});
|
||||||
35
tests/Unit/v1/Traits/HasRegisterTest.php
Normal file
35
tests/Unit/v1/Traits/HasRegisterTest.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits\HasRegister;
|
||||||
|
|
||||||
|
function makeRegisterObject(?int $register): object
|
||||||
|
{
|
||||||
|
return new class ($register) {
|
||||||
|
use HasRegister;
|
||||||
|
|
||||||
|
public function __construct(public ?int $register)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it('maps all register codes correctly', function (int $code, string $expected) {
|
||||||
|
expect(makeRegisterObject($code)->getRegisterString())->toBe($expected);
|
||||||
|
})->with([
|
||||||
|
[1, 'Trade Register'],
|
||||||
|
[2, 'Register of Foundations'],
|
||||||
|
[3, 'Register of Associations'],
|
||||||
|
[4, 'Tax Administration'],
|
||||||
|
[5, 'Prepayment Register'],
|
||||||
|
[6, 'VAT Register'],
|
||||||
|
[7, 'Employer Register'],
|
||||||
|
[8, 'Register of bodies liable for tax on insurance premiums'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
it('returns unknown for unrecognized register', function () {
|
||||||
|
expect(makeRegisterObject(99)->getRegisterString())->toBe('unknown:99');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns unknown for null register', function () {
|
||||||
|
expect(makeRegisterObject(null)->getRegisterString())->toBe('unknown:');
|
||||||
|
});
|
||||||
34
tests/Unit/v1/Traits/HasSourceTest.php
Normal file
34
tests/Unit/v1/Traits/HasSourceTest.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v1\Traits\HasSource;
|
||||||
|
|
||||||
|
function makeSourceObject(?int $source): object
|
||||||
|
{
|
||||||
|
return new class ($source) {
|
||||||
|
use HasSource;
|
||||||
|
|
||||||
|
public function __construct(public ?int $source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns common for source 0', function () {
|
||||||
|
expect(makeSourceObject(0)->getSourceText())->toBe('common');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns Finnish Patent and Registration Office for source 1', function () {
|
||||||
|
expect(makeSourceObject(1)->getSourceText())->toBe('Finnish Patent and Registration Office');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns Tax Administration for source 2', function () {
|
||||||
|
expect(makeSourceObject(2)->getSourceText())->toBe('Tax Administration');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns Business Information System for source 3', function () {
|
||||||
|
expect(makeSourceObject(3)->getSourceText())->toBe('Business Information System');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns empty string for unknown source', function () {
|
||||||
|
expect(makeSourceObject(99)->getSourceText())->toBe('');
|
||||||
|
});
|
||||||
73
tests/Unit/v3/ClientTest.php
Normal file
73
tests/Unit/v3/ClientTest.php
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Handler\MockHandler;
|
||||||
|
use GuzzleHttp\HandlerStack;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Client as V3Client;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Dto\CompanySearchResult;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Dto\PostCodeEntry;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Exceptions\V3ApiException;
|
||||||
|
|
||||||
|
function createV3ClientWithMock(Response ...$responses): V3Client
|
||||||
|
{
|
||||||
|
$mock = new MockHandler($responses);
|
||||||
|
$client = new Client(['handler' => HandlerStack::create($mock)]);
|
||||||
|
return new V3Client($client);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('searches companies successfully', function () {
|
||||||
|
$json = file_get_contents(__DIR__ . '/../../Fixtures/v3-search-response.json');
|
||||||
|
$client = createV3ClientWithMock(new Response(200, [], $json));
|
||||||
|
|
||||||
|
$result = $client->searchCompanies(name: 'Example');
|
||||||
|
|
||||||
|
expect($result)
|
||||||
|
->toBeInstanceOf(CompanySearchResult::class)
|
||||||
|
->and($result->totalResults)->toBe(1)
|
||||||
|
->and($result->companies)->toHaveCount(1)
|
||||||
|
->and($result->companies[0]->businessId->value)->toBe('1639413-9')
|
||||||
|
->and($result->companies[0]->names[0]->name)->toBe('Oy Example Ab')
|
||||||
|
->and($result->companies[0]->tradeRegisterStatus)->toBe('2')
|
||||||
|
->and($result->companies[0]->addresses[0]->street)->toBe('Testitie 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws V3ApiException on request failure for search', function () {
|
||||||
|
$client = createV3ClientWithMock(new Response(500, [], '{"message":"error"}'));
|
||||||
|
$client->searchCompanies(name: 'Test');
|
||||||
|
})->throws(V3ApiException::class);
|
||||||
|
|
||||||
|
it('retrieves description as plain text', function () {
|
||||||
|
$client = createV3ClientWithMock(new Response(200, [], 'Trade Register'));
|
||||||
|
$result = $client->getDescription('REK', 'en');
|
||||||
|
|
||||||
|
expect($result)->toBe('Trade Register');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws V3ApiException on description failure', function () {
|
||||||
|
$client = createV3ClientWithMock(new Response(400, [], '{"message":"bad request"}'));
|
||||||
|
$client->getDescription('INVALID');
|
||||||
|
})->throws(V3ApiException::class);
|
||||||
|
|
||||||
|
it('retrieves post codes', function () {
|
||||||
|
$json = (string) json_encode([
|
||||||
|
['postCode' => '00100', 'city' => 'HELSINKI', 'active' => true, 'languageCode' => '1', 'municipalityCode' => '091'],
|
||||||
|
['postCode' => '00200', 'city' => 'HELSINKI', 'active' => true, 'languageCode' => '1', 'municipalityCode' => '091'],
|
||||||
|
]);
|
||||||
|
$client = createV3ClientWithMock(new Response(200, [], $json));
|
||||||
|
|
||||||
|
$results = $client->getPostCodes('fi');
|
||||||
|
|
||||||
|
expect($results)->toHaveCount(2)
|
||||||
|
->and($results[0])->toBeInstanceOf(PostCodeEntry::class)
|
||||||
|
->and($results[0]->postCode)->toBe('00100')
|
||||||
|
->and($results[0]->city)->toBe('HELSINKI')
|
||||||
|
->and($results[1]->postCode)->toBe('00200');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns stream for all companies download', function () {
|
||||||
|
$client = createV3ClientWithMock(new Response(200, [], 'zip-content'));
|
||||||
|
$stream = $client->getAllCompanies();
|
||||||
|
|
||||||
|
expect($stream->getContents())->toBe('zip-content');
|
||||||
|
});
|
||||||
53
tests/Unit/v3/Dto/CompanyTest.php
Normal file
53
tests/Unit/v3/Dto/CompanyTest.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use CuyZ\Valinor\MapperBuilder;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Dto\Company;
|
||||||
|
use Ivuorinen\BusinessDataFetcher\v3\Dto\CompanySearchResult;
|
||||||
|
|
||||||
|
it('hydrates Company from v3 search response fixture', function () {
|
||||||
|
$json = json_decode(
|
||||||
|
file_get_contents(__DIR__ . '/../../../Fixtures/v3-search-response.json'),
|
||||||
|
true,
|
||||||
|
512,
|
||||||
|
JSON_THROW_ON_ERROR
|
||||||
|
);
|
||||||
|
|
||||||
|
$mapper = (new MapperBuilder())
|
||||||
|
->allowSuperfluousKeys()
|
||||||
|
->mapper();
|
||||||
|
|
||||||
|
$result = $mapper->map(CompanySearchResult::class, $json);
|
||||||
|
|
||||||
|
expect($result->totalResults)->toBe(1)
|
||||||
|
->and($result->companies)->toHaveCount(1);
|
||||||
|
|
||||||
|
$company = $result->companies[0];
|
||||||
|
|
||||||
|
expect($company)->toBeInstanceOf(Company::class)
|
||||||
|
->and($company->businessId->value)->toBe('1639413-9')
|
||||||
|
->and($company->businessId->registrationDate)->toBe('2001-04-03')
|
||||||
|
->and($company->euId)->not->toBeNull()
|
||||||
|
->and($company->euId->value)->toBe('FIFOO123456')
|
||||||
|
->and($company->names)->toHaveCount(1)
|
||||||
|
->and($company->names[0]->name)->toBe('Oy Example Ab')
|
||||||
|
->and($company->names[0]->type)->toBe('TOIM')
|
||||||
|
->and($company->mainBusinessLine)->not->toBeNull()
|
||||||
|
->and($company->mainBusinessLine->code)->toBe('62010')
|
||||||
|
->and($company->mainBusinessLine->descriptions)->toHaveCount(1)
|
||||||
|
->and($company->mainBusinessLine->descriptions[0]->description)->toBe('Computer programming activities')
|
||||||
|
->and($company->website)->not->toBeNull()
|
||||||
|
->and($company->website->url)->toBe('www.example.fi')
|
||||||
|
->and($company->companyForms)->toHaveCount(1)
|
||||||
|
->and($company->companyForms[0]->type)->toBe('OY')
|
||||||
|
->and($company->companyForms[0]->descriptions)->toHaveCount(2)
|
||||||
|
->and($company->registeredEntries)->toHaveCount(1)
|
||||||
|
->and($company->registeredEntries[0]->register)->toBe('1')
|
||||||
|
->and($company->registeredEntries[0]->authority)->toBe('2')
|
||||||
|
->and($company->addresses)->toHaveCount(1)
|
||||||
|
->and($company->addresses[0]->street)->toBe('Testitie 1')
|
||||||
|
->and($company->addresses[0]->postOffices)->toHaveCount(1)
|
||||||
|
->and($company->addresses[0]->postOffices[0]->city)->toBe('HELSINKI')
|
||||||
|
->and($company->tradeRegisterStatus)->toBe('2')
|
||||||
|
->and($company->status)->toBe('ACTIVE')
|
||||||
|
->and($company->lastModified)->toBe('2023-06-15T10:30:00Z');
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user