• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CPS-IT / personio-jobs / 15388375997

02 Jun 2025 09:09AM UTC coverage: 3.654% (+0.04%) from 3.61%
15388375997

push

github

web-flow
Merge pull request #228 from CPS-IT/task/drop-v11

[!!!][TASK] Drop support for TYPO3 v11.5

0 of 8 new or added lines in 5 files covered. (0.0%)

6 existing lines in 5 files now uncovered.

27 of 739 relevant lines covered (3.65%)

0.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.85
/Classes/Service/PersonioApiService.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "personio_jobs".
7
 *
8
 * Copyright (C) 2023 Elias Häußler <e.haeussler@familie-redlich.de>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace CPSIT\Typo3PersonioJobs\Service;
25

26
use CPSIT\Typo3PersonioJobs\Configuration\ExtensionConfiguration;
27
use CPSIT\Typo3PersonioJobs\Domain\Model\Job;
28
use CPSIT\Typo3PersonioJobs\Domain\Model\JobDescription;
29
use CPSIT\Typo3PersonioJobs\Event\AfterJobsMappedEvent;
30
use CPSIT\Typo3PersonioJobs\Exception\MalformedApiResponseException;
31
use CPSIT\Typo3PersonioJobs\Utility\FrontendUtility;
32
use CuyZ\Valinor\Mapper\MappingError;
33
use CuyZ\Valinor\Mapper\Tree\Message\Messages;
34
use CuyZ\Valinor\Mapper\TreeMapper;
35
use CuyZ\Valinor\MapperBuilder;
36
use EliasHaeussler\ValinorXml\Exception\ArrayPathHasUnexpectedType;
37
use EliasHaeussler\ValinorXml\Exception\ArrayPathIsInvalid;
38
use EliasHaeussler\ValinorXml\Exception\XmlIsMalformed;
39
use EliasHaeussler\ValinorXml\Mapper\Source\XmlSource;
40
use Psr\EventDispatcher\EventDispatcherInterface;
41
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
42
use TYPO3\CMS\Core\Http\RequestFactory;
43
use TYPO3\CMS\Core\Http\Uri;
44
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
45

46
/**
47
 * PersonioApiService
48
 *
49
 * @author Elias Häußler <e.haeussler@familie-redlich.de>
50
 * @license GPL-2.0-or-later
51
 */
52
#[Autoconfigure(public: true)]
53
final readonly class PersonioApiService
54
{
55
    private Uri $apiUrl;
56
    private TreeMapper $mapper;
57

58
    public function __construct(
5✔
59
        private RequestFactory $requestFactory,
60
        private EventDispatcherInterface $eventDispatcher,
61
        ExtensionConfiguration $extensionConfiguration,
62
    ) {
63
        $this->apiUrl = $extensionConfiguration->getApiUrl();
5✔
64
        $this->mapper = $this->createMapper();
5✔
65
    }
66

67
    /**
68
     * @return list<Job>
69
     * @throws ArrayPathHasUnexpectedType
70
     * @throws ArrayPathIsInvalid
71
     * @throws XmlIsMalformed
72
     */
73
    public function getJobs(): array
5✔
74
    {
75
        $requestUri = $this->apiUrl->withPath('/xml');
5✔
76
        $response = $this->requestFactory->request((string)$requestUri);
5✔
77
        $source = XmlSource::fromXmlString((string)$response->getBody())
5✔
78
            ->asCollection('position')
5✔
79
            ->asCollection('position.*.jobDescriptions.jobDescription')
5✔
80
        ;
5✔
81

82
        try {
83
            $jobs = $this->mapper->map('list<' . Job::class . '>', $source['position']);
4✔
84

85
            $this->eventDispatcher->dispatch(new AfterJobsMappedEvent($requestUri, $jobs));
3✔
86

87
            return $jobs;
3✔
88
        } catch (MappingError $error) {
1✔
89
            $errors = Messages::flattenFromNode($error->node())->errors();
1✔
90

91
            throw MalformedApiResponseException::forMappingErrors($errors);
1✔
92
        }
93
    }
94

95
    public function getJobUrl(Job $job): Uri
×
96
    {
97
        $language = $this->getLanguageCode();
×
98
        $jobUrl = $this->apiUrl->withPath(sprintf('/job/%d', $job->getPersonioId()));
×
99

100
        if ($language !== null) {
×
101
            $jobUrl = $jobUrl->withQuery(sprintf('?language=%s', $language));
×
102
        }
103

104
        return $jobUrl;
×
105
    }
106

107
    public function getApplyUrl(Job $job): Uri
×
108
    {
109
        return $this->getJobUrl($job)->withFragment('apply');
×
110
    }
111

112
    private function createMapper(): TreeMapper
5✔
113
    {
114
        return (new MapperBuilder())
5✔
115
            ->supportDateFormats(\DateTimeInterface::ATOM)
5✔
116
            ->allowSuperfluousKeys()
5✔
117
            ->enableFlexibleCasting()
5✔
118
            ->registerConstructor(
5✔
119
                Job::fromApiResponse(...),
5✔
120
                JobDescription::fromApiResponse(...),
5✔
121
            )
5✔
122
            ->mapper()
5✔
123
        ;
5✔
124
    }
125

126
    private function getLanguageCode(): ?string
×
127
    {
128
        $serverRequest = FrontendUtility::getServerRequest();
×
129
        $siteLanguage = $serverRequest->getAttribute('language');
×
130

131
        if (!($siteLanguage instanceof SiteLanguage)) {
×
132
            return null;
×
133
        }
134

NEW
135
        return $siteLanguage->getLocale()->getLanguageCode();
×
136
    }
137
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc