Skip to content

Commit 20fc992

Browse files
committed
Initial commit
0 parents  commit 20fc992

36 files changed

+2548
-0
lines changed

Diff for: .editorconfig

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[*]
2+
charset = utf-8
3+
indent_size = 4
4+
indent_style = space
5+
insert_final_newline = true
6+
trim_trailing_whitespace = true
7+
8+
[*.neon]
9+
indent_style = space
10+
11+
[Makefile]
12+
indent_style = tab

Diff for: .gitattributes

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.* export-ignore
2+
*.md export-ignore
3+
*.neon export-ignore
4+
*.dist export-ignore
5+
tests export-ignore

Diff for: .github/dependabot.yml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# https://help.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates
2+
3+
version: 2
4+
5+
updates:
6+
-
7+
commit-message:
8+
include: "scope"
9+
prefix: "github-actions"
10+
directory: "/"
11+
labels:
12+
- "dependency"
13+
- "automerge"
14+
open-pull-requests-limit: 5
15+
package-ecosystem: "github-actions"
16+
schedule:
17+
interval: "daily"

Diff for: .github/workflows/ci.yaml

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
name: "PHP"
2+
3+
on:
4+
schedule:
5+
- cron: '0 5 * * *'
6+
pull_request:
7+
push:
8+
branches:
9+
- "develop"
10+
- "master"
11+
12+
env:
13+
REQUIRED_PHP_EXTENSIONS: "ctype, filter, hash, iconv, json"
14+
15+
jobs:
16+
coding-standards:
17+
name: "Coding Standards"
18+
19+
runs-on: "ubuntu-latest"
20+
21+
strategy:
22+
matrix:
23+
php-version:
24+
- "8.1"
25+
env:
26+
PHP_CS_FIXER_IGNORE_ENV: "1" # Remove if PHP-CS-Fixer supports PHP 8.2
27+
28+
steps:
29+
- name: "Checkout"
30+
uses: "actions/checkout@v4"
31+
32+
- name: "Install PHP with extensions"
33+
uses: "shivammathur/[email protected]"
34+
with:
35+
coverage: "none"
36+
extensions: "${{ env.REQUIRED_PHP_EXTENSIONS }}"
37+
php-version: "${{ matrix.php-version }}"
38+
tools: "composer:v2"
39+
40+
- name: "Validate composer.json"
41+
run: "composer validate"
42+
43+
- name: "Install dependencies with composer"
44+
uses: "ramsey/[email protected]"
45+
with:
46+
composer-options: "--no-scripts"
47+
48+
- name: "Run ergebnis/composer-normalize"
49+
run: "composer normalize"
50+
51+
- name: "Run friendsofphp/php-cs-fixer"
52+
run: "vendor/bin/php-cs-fixer fix --diff --verbose"
53+
54+
static-code-analysis:
55+
name: "Static Code Analysis"
56+
57+
runs-on: "ubuntu-latest"
58+
59+
strategy:
60+
matrix:
61+
php-version:
62+
- "8.1"
63+
64+
steps:
65+
- name: "Checkout"
66+
uses: "actions/checkout@v4"
67+
68+
- name: "Install PHP with extensions"
69+
uses: "shivammathur/setup-php@v2"
70+
with:
71+
coverage: "none"
72+
extensions: "${{ env.REQUIRED_PHP_EXTENSIONS }}"
73+
php-version: "${{ matrix.php-version }}"
74+
75+
- name: "Install dependencies with composer"
76+
uses: "ramsey/[email protected]"
77+
78+
- name: "Static code analysis"
79+
run: "vendor/bin/phpstan analyse --configuration phpstan.neon.dist --no-progress"
80+
81+
tests:
82+
name: "Tests"
83+
84+
runs-on: "ubuntu-latest"
85+
86+
strategy:
87+
matrix:
88+
php-version:
89+
- "8.1"
90+
91+
steps:
92+
- name: "Checkout"
93+
uses: "actions/checkout@v4"
94+
95+
- name: "Install PHP with extensions"
96+
uses: "shivammathur/setup-php@v2"
97+
with:
98+
coverage: "pcov"
99+
extensions: "${{ env.REQUIRED_PHP_EXTENSIONS }}"
100+
php-version: "${{ matrix.php-version }}"
101+
102+
- name: "Install dependencies with composer"
103+
uses: "ramsey/[email protected]"
104+
105+
- name: "Run unit tests"
106+
run: "vendor/bin/phpunit --configuration=phpunit.xml.dist --coverage-clover=.build/logs/clover.xml"
107+
108+
- name: "Send code coverage report to Codecov.io"
109+
run: "bash <(curl -s https://codecov.io/bash)"

Diff for: .gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.build/
2+
vendor
3+
composer.lock
4+
.php-cs-fixer.cache
5+
phpunit.xml
6+
.idea
7+
.phpunit.result.cache

Diff for: .php-cs-fixer.dist.php

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of Storyblok-Api.
7+
*
8+
* (c) SensioLabs Deutschland <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
use Ergebnis\PhpCsFixer\Config\Factory;
15+
use Ergebnis\PhpCsFixer\Config\Rules;
16+
use Ergebnis\PhpCsFixer\Config\RuleSet\Php83;
17+
18+
$header = <<<'HEADER'
19+
This file is part of Storyblok-Api.
20+
21+
(c) SensioLabs Deutschland <[email protected]>
22+
23+
For the full copyright and license information, please view the LICENSE
24+
file that was distributed with this source code.
25+
HEADER;
26+
27+
$ruleSet = Php83::create()
28+
->withHeader($header)
29+
->withRules(Rules::fromArray(
30+
[
31+
'blank_line_before_statement' => [
32+
'statements' => [
33+
'break',
34+
'continue',
35+
'declare',
36+
'default',
37+
'do',
38+
'exit',
39+
'for',
40+
'foreach',
41+
'goto',
42+
'if',
43+
'include',
44+
'include_once',
45+
'require',
46+
'require_once',
47+
'return',
48+
'switch',
49+
'throw',
50+
'try',
51+
'while',
52+
],
53+
],
54+
'concat_space' => [
55+
'spacing' => 'none',
56+
],
57+
'date_time_immutable' => false,
58+
'error_suppression' => false,
59+
'final_class' => false,
60+
'mb_str_functions' => false,
61+
'native_function_invocation' => [
62+
'exclude' => [],
63+
'include' => [
64+
'@compiler_optimized',
65+
],
66+
'scope' => 'all',
67+
'strict' => false,
68+
],
69+
'php_unit_internal_class' => false,
70+
'php_unit_test_annotation' => [
71+
'style' => 'annotation',
72+
],
73+
'php_unit_test_class_requires_covers' => false,
74+
'return_to_yield_from' => false,
75+
'phpdoc_array_type' => false,
76+
'phpdoc_list_type' => false,
77+
'attribute_empty_parentheses' => false,
78+
'final_public_method_for_abstract_class' => false,
79+
'class_attributes_separation' => [
80+
'elements' => [
81+
'const' => 'only_if_meta',
82+
'property' => 'only_if_meta',
83+
'trait_import' => 'none',
84+
'case' => 'none',
85+
],
86+
],
87+
],
88+
));
89+
90+
$config = Factory::fromRuleSet($ruleSet);
91+
92+
$config->getFinder()
93+
->append([
94+
__DIR__.'/.php-cs-fixer.dist.php',
95+
])
96+
->in('src')
97+
->in('tests');
98+
99+
$config->setCacheFile(__DIR__.'/.build/php-cs-fixer/.php-cs-fixer.cache');
100+
101+
return $config;

Diff for: .php-version

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8.3

Diff for: FOO.php

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Bridge\Storyblok\Api;
6+
7+
use App\Bridge\Storyblok\Domain\Value\Link\LinkId;
8+
use App\Bridge\Storyblok\Domain\Value\Response\LinksResponse;
9+
use App\Bridge\Storyblok\Domain\Value\Response\StoriesResponse;
10+
use App\Bridge\Storyblok\Domain\Value\Response\StoryResponse;
11+
use App\Bridge\Storyblok\Domain\Value\Story;
12+
use App\Bridge\Storyblok\Domain\Value\Uuid;
13+
use App\Bridge\Storyblok\Exception\ApiResponseException;
14+
use Storyblok\ApiException;
15+
use Storyblok\Client;
16+
use Symfony\Component\HttpFoundation\Response;
17+
use Webmozart\Assert\Assert;
18+
19+
final readonly class StoryblokApi implements StoryblokApiInterface
20+
{
21+
private const int MAX_LINKS_PER_PAGE = 1000;
22+
23+
public function __construct(
24+
private Client $client,
25+
) {
26+
}
27+
28+
public function getLinks(): array
29+
{
30+
$responseBody = $this->doGetLinks();
31+
32+
return (new LinksResponse($responseBody))->links;
33+
}
34+
35+
public function getLinksAtRoot(): array
36+
{
37+
$responseBody = $this->doGetLinks([
38+
'with_parent' => 0,
39+
]);
40+
41+
return (new LinksResponse($responseBody))->links;
42+
}
43+
44+
public function getLinksByParentId(LinkId $parentId): array
45+
{
46+
$responseBody = $this->doGetLinks([
47+
'with_parent' => $parentId->value,
48+
]);
49+
50+
return (new LinksResponse($responseBody))->links;
51+
}
52+
53+
public function getStories(string $locale = 'en'): array
54+
{
55+
$response = $this->client
56+
->language($locale)
57+
->getStories();
58+
59+
if (Response::HTTP_OK !== $response->getCode()) {
60+
throw new ApiResponseException(
61+
sprintf('Storyblok API returned error code %s', $response->responseCode),
62+
);
63+
}
64+
65+
$responseBody = $response->getBody();
66+
Assert::isArray($responseBody);
67+
68+
return (new StoriesResponse($responseBody))->stories;
69+
}
70+
71+
public function getStoryBySlug(string $slug, string $locale = 'en'): Story
72+
{
73+
$response = $this->client
74+
->language($locale)
75+
->resolveLinks('url')
76+
->getStoryBySlug($slug);
77+
78+
if (Response::HTTP_OK !== $response->getCode()) {
79+
throw new ApiResponseException(
80+
sprintf('Storyblok API returned error code %s', $response->responseCode),
81+
);
82+
}
83+
84+
$responseBody = $response->getBody();
85+
Assert::isArray($responseBody);
86+
87+
return (new StoryResponse($responseBody))->story;
88+
}
89+
90+
public function getStoryByUuid(Uuid $uuid, string $locale = 'en'): Story
91+
{
92+
$response = $this->client
93+
->language($locale)
94+
->getStoryByUuid($uuid->value);
95+
96+
if (Response::HTTP_OK !== $response->getCode()) {
97+
throw new ApiResponseException(
98+
sprintf('Storyblok API returned error code %s', $response->responseCode),
99+
);
100+
}
101+
102+
$responseBody = $response->getBody();
103+
Assert::isArray($responseBody);
104+
105+
return (new StoryResponse($responseBody))->story;
106+
}
107+
108+
/**
109+
* @param array<string, mixed> $parameters
110+
*
111+
* @return array<string, mixed>
112+
*/
113+
private function doGetLinks(array $parameters = []): array
114+
{
115+
try {
116+
$response = $this->client->getLinks([
117+
'per_page' => self::MAX_LINKS_PER_PAGE,
118+
'include_dates' => true,
119+
...$parameters,
120+
]);
121+
} catch (ApiException $e) {
122+
throw new ApiResponseException(sprintf('Storyblok API exception: "%s".', $e->getMessage()), $e->getCode(), $e);
123+
}
124+
125+
if (Response::HTTP_OK !== $response->getCode()) {
126+
throw new ApiResponseException(sprintf('Unexpected Response Code "%s".', $response->getCode()));
127+
}
128+
129+
$responseBody = $response->getBody();
130+
Assert::isArray($responseBody);
131+
132+
return $responseBody;
133+
}
134+
}

0 commit comments

Comments
 (0)