Skip to content

Commit cc1f38c

Browse files
committed
Spike 8.0 entrypoints
1 parent 5c4323c commit cc1f38c

4 files changed

Lines changed: 104 additions & 122 deletions

File tree

src/Api/Controller/OxapiController.php

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,117 @@
99

1010
namespace OxidEsales\GraphQL\Base\Api\Controller;
1111

12-
use OxidEsales\Eshop\Core\Registry;
12+
use GraphQL\Error\FormattedError;
13+
use OxidEsales\Eshop\Core\Registry as EshopRegistry;
14+
use OxidEsales\EshopCommunity\Core\Di\ContainerFacade;
1315
use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Dao\ModuleConfigurationDaoInterface;
16+
use OxidEsales\GraphQL\Base\Exception\Error;
17+
use OxidEsales\GraphQL\Base\Exception\ErrorCategories;
18+
use OxidEsales\GraphQL\Base\Exception\InvalidRequest;
19+
use OxidEsales\GraphQL\Base\Framework\GraphQLQueryHandler;
20+
use OxidEsales\GraphQL\Base\Framework\RequestReader;
21+
use OxidEsales\GraphQL\Base\Framework\TimerHandler;
22+
use OxidEsales\GraphQL\Base\Service\Authentication as GraphQLAuthenticationService;
1423
use Symfony\Component\HttpFoundation\JsonResponse;
1524
use Symfony\Component\HttpFoundation\Response;
1625
use Symfony\Component\Routing\Attribute\Route;
1726
use Symfony\Component\Routing\Requirement\Requirement;
1827

1928
readonly class OxapiController
2029
{
21-
public function __construct(private ModuleConfigurationDaoInterface $moduleConfigurationDao)
30+
public const SESSION_ERROR_MESSAGE = 'OXID eShop PHP session spotted. Ensure you have skipSession=1 '
31+
. 'parameter sent to the widget.php. For more information about the problem, check '
32+
. 'Troubleshooting section in documentation.';
33+
34+
public function __construct(
35+
private readonly TimerHandler $timerHandler,
36+
private readonly GraphQLQueryHandler $queryHandler
37+
)
38+
{
39+
}
40+
41+
#[Route('/oxapi/{shp}/{lang}/', requirements: ['shp' => Requirement::DIGITS, 'lang' => Requirement::DIGITS], methods: ['GET', 'POST'])]
42+
public function process(int $shp, int $lang): Response
43+
{
44+
$_POST['shp'] = $shp;
45+
$_POST['lang'] = $lang;
46+
47+
/** @var TimerHandler $timerHandler */
48+
$this->timerHandler
49+
->create('bootstrap')
50+
->startAt($_SERVER['REQUEST_TIME_FLOAT'])
51+
->stop();
52+
53+
$headers = [
54+
'Content-Type: application/json',
55+
$this->generateServerTimingHeader()
56+
];
57+
$status = 200;
58+
59+
try {
60+
$this->handleShopSession();
61+
$result = $this->queryHandler
62+
->executeGraphQLQuery();
63+
} catch (Error $e) {
64+
$result = [
65+
'errors' => [
66+
FormattedError::createFromException($e)
67+
]
68+
];
69+
if (!$this->isAuthenticated($e)) {
70+
$headers[] = 'WWW-Authenticate: Bearer';
71+
}
72+
} catch (\Throwable $e) {
73+
EshopRegistry::getLogger()->error($e->getMessage(), [$e]);
74+
$result = [
75+
'errors' => [
76+
FormattedError::createFromException($e)
77+
]
78+
];
79+
$status = 500;
80+
}
81+
82+
return new JsonResponse($result, $status, $headers);
83+
}
84+
85+
private function handleShopSession(): void
2286
{
87+
//if there's already a php session running, bail out to prevent inconsistent behaviour
88+
if (PHP_SESSION_NONE !== session_status()) {
89+
throw new InvalidRequest(self::SESSION_ERROR_MESSAGE);
90+
}
91+
92+
$this->setShopUserFromToken();
93+
}
94+
95+
private function setShopUserFromToken(): void
96+
{
97+
$session = EshopRegistry::getSession();
98+
$session->setUser(null);
99+
$session->setBasket(null);
100+
$session->setVariable('usr', null);
101+
102+
$authentication = ContainerFacade::get(GraphQLAuthenticationService::class);
103+
$userId = $authentication->getUser()->id()->val();
104+
105+
if ($userId) {
106+
$session->setVariable('usr', $userId);
107+
}
108+
}
109+
110+
private function generateServerTimingHeader(): string
111+
{
112+
$timings = [];
113+
114+
foreach ($this->timerHandler->getTimers() as $name => $timer) {
115+
$timings[] = sprintf('%s;dur=%.3f', $name, $timer->getDuration() * 1000);
116+
}
117+
118+
return 'Server-Timing: ' . implode(',', $timings);
23119
}
24120

25-
#[Route('/oxapi/{shp}/{lang}/', requirements: ['lang' => Requirement::DIGITS], methods: ['GET'])]
26-
public function foo(int $shp, int $lang): Response
121+
private function isAuthenticated(Error $error): bool
27122
{
28-
#Registry::getConfig()->saveShopConfVar('string', 'testControllers', 'hello');
29-
return new JsonResponse(
30-
[
31-
'shp' => $shp,
32-
'lang' => $lang,
33-
'bla' => 'foo'
34-
]
35-
);
123+
return $error->getCategory() !== ErrorCategories::PERMISSIONERRORS;
36124
}
37125
}

src/Component/Widget/GraphQL.php

Lines changed: 0 additions & 105 deletions
This file was deleted.

src/Framework/GraphQLQueryHandler.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,14 @@ public function __construct(
3131
) {
3232
}
3333

34-
public function executeGraphQLQuery(): void
34+
public function executeGraphQLQuery(): array
3535
{
3636
$result = $this->executeQuery(
3737
$this->requestReader->getGraphQLRequestData()
3838
);
3939
$result->setErrorFormatter($this->getErrorFormatter());
40-
$this->responseWriter->renderJsonResponse(
41-
$result->toArray()
42-
);
40+
41+
return $result->toArray();
4342
}
4443

4544
/**

tests/Integration/TestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ protected function uploadFile(
199199
$boundary = '-------------' . uniqid();
200200
$postData = $this->buildFileUpload($boundary, $fields, $map, $files);
201201

202-
$ch = curl_init(getenv('OXID_SHOP_BASE_URL') . '/graphql?lang=0&shp=1');
202+
$ch = curl_init(getenv('OXID_SHOP_BASE_URL') . '/oxapi/1/0/');
203203

204204
$headers = [
205205
'Connection: keep-alive',

0 commit comments

Comments
 (0)