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

TYPO3-Headless / headless / 29398229494

15 Jul 2026 07:42AM UTC coverage: 69.663% (-5.8%) from 75.459%
29398229494

Pull #893

github

web-flow
Merge ab993c965 into 79b7c5472
Pull Request #893: [TASK] Reintroduce missing features, extension cleanup

360 of 545 new or added lines in 33 files covered. (66.06%)

167 existing lines in 7 files now uncovered.

1364 of 1958 relevant lines covered (69.66%)

7.27 hits per line

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

93.48
/Classes/Middleware/ElementBodyResponseMiddleware.php
1
<?php
2

3
/*
4
 * This file is part of the "headless" Extension for TYPO3 CMS.
5
 *
6
 * For the full copyright and license information, please read the
7
 * LICENSE.md file that was distributed with this source code.
8
 */
9

10
declare(strict_types=1);
11

12
namespace FriendsOfTYPO3\Headless\Middleware;
13

14
use FriendsOfTYPO3\Headless\Json\JsonDecoderInterface;
15
use FriendsOfTYPO3\Headless\Json\JsonEncoderInterface;
16
use FriendsOfTYPO3\Headless\Utility\HeadlessModeInterface;
17
use JsonException;
18
use Psr\Http\Message\ResponseInterface;
19
use Psr\Http\Message\ServerRequestInterface;
20
use Psr\Http\Server\MiddlewareInterface;
21
use Psr\Http\Server\RequestHandlerInterface;
22
use TYPO3\CMS\Core\Http\Stream;
23

24
use TYPO3\CMS\Core\Site\Entity\Site;
25

26
use function in_array;
27
use function is_array;
28

29
use function json_decode;
30

31
use const JSON_THROW_ON_ERROR;
32

33
class ElementBodyResponseMiddleware implements MiddlewareInterface
34
{
35
    public function __construct(
36
        protected JsonEncoderInterface $jsonEncoder,
37
        protected HeadlessModeInterface $headlessMode,
38
        protected JsonDecoderInterface $jsonDecoder,
39
    ) {}
1✔
40

41
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
42
    {
43
        $response = $handler->handle($request);
1✔
44

45
        $site = $request->getAttribute('site');
1✔
46

47
        if (!($site instanceof Site)) {
1✔
48
            return $response;
1✔
49
        }
50

51
        if (!$this->headlessMode->isEnabledFor($request)) {
1✔
52
            return $response;
1✔
53
        }
54

55
        $elementId = (int)($request->getParsedBody()['responseElementId'] ?? 0);
1✔
56

57
        if ($elementId <= 0 || !in_array($request->getMethod(), ['POST', 'PUT', 'DELETE'], true)) {
1✔
58
            return $response;
1✔
59
        }
60

61
        $recursiveElement = (bool)(int)($request->getParsedBody()['responseElementRecursive'] ?? 0);
1✔
62

63
        $body = $response->getBody()->__toString();
1✔
64
        if ($body === '') {
1✔
NEW
65
            return $response;
×
66
        }
67

68
        try {
69
            $responseJson = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
1✔
70
        } catch (JsonException) {
1✔
71
            return $response;
1✔
72
        }
73

74
        if (!is_array($responseJson)) {
1✔
NEW
75
            return $response;
×
76
        }
77

78
        $content = $responseJson['content'] ?? [];
1✔
79
        if (is_array($content)) {
1✔
80
            $content = $this->jsonDecoder->decode($content);
1✔
81
        } else {
NEW
82
            $content = [];
×
83
        }
84

85
        $stream = new Stream('php://temp', 'r+');
1✔
86
        $stream->write($this->jsonEncoder->encode($this->extractElement(
1✔
87
            $content,
1✔
88
            $elementId,
1✔
89
            $recursiveElement
1✔
90
        )));
1✔
91

92
        return $response->withBody($stream);
1✔
93
    }
94

95
    /**
96
     * @param array<string, mixed> $content
97
     * @param int $elementId
98
     * @return array<string, mixed>
99
     */
100
    private function extractElement(array $content, int $elementId, bool $recursiveElement = false): array
101
    {
102
        $body = [];
1✔
103

104
        foreach ($content as $items) {
1✔
105
            if (!is_array($items)) {
1✔
106
                continue;
1✔
107
            }
108
            // if array is flat means doNotGroupByColPos = 1 is set
109
            if ((int)($items['id'] ?? 0) === $elementId) {
1✔
110
                return $items;
1✔
111
            }
112

113
            foreach ($items as $item) {
1✔
114
                if ((int)($item['id'] ?? 0) === $elementId) {
1✔
115
                    return $item;
1✔
116
                }
117

118
                if ($recursiveElement && is_array($item)) {
1✔
119
                    foreach ($item as $prop) {
1✔
120
                        if (is_array($prop)) {
1✔
121
                            $result = $this->extractElement($prop, $elementId, true);
1✔
122

123
                            if (!empty($result)) {
1✔
124
                                return $result;
1✔
125
                            }
126
                        }
127
                    }
128
                }
129
            }
130
        }
131

132
        return $body;
1✔
133
    }
134
}
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