Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
68.29% covered (warning)
68.29%
56 / 82
0.00% covered (danger)
0.00%
0 / 1
CRAP
n/a
0 / 0
createplace_drop_database
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3/**
4 * @file
5 * Place action: create new place (insert PLACE in central DB, create per-place database).
6 */
7
8declare(strict_types=1);
9
10/**
11 * Drop a place database (e.g. on rollback after failed schema deploy).
12 *
13 * @param string $database Database name (e.g. P00000001).
14 * @param \ConxHelper $conx Connection helper (uses ->server for DROP DATABASE).
15 */
16function createplace_drop_database(string $database, \ConxHelper $conx): void
17{
18    $conx_server = $conx->server;
19    if ($conx_server === null) {
20        return;
21    }
22    $dbname = '`'.str_replace('`', '``', $database).'`';
23    $results = [];
24    $conx_server->runsql([], 'DROP DATABASE IF EXISTS '.$dbname, $results);
25}
26
27/**
28 * Action callable: create a new place (insert PLACE in central DB with status PA, create place database).
29 *
30 * Requires valid session (device + session). Only status, user and optionally _uuid are set; the client completes data via sync (UPDATE).
31 *
32 * @param string $body JSON body; only _uuid is used if present.
33 * @param array<string, mixed> $query Query params: device, session.
34 * @param \ConxHelper $conx Connection helper.
35 * @param \Psr\Log\LoggerInterface $logger Logger.
36 * @param \UppServices\SessionService $sessionService Session service for check.
37 * @return array{output: string, contentType: string}
38 */
39return function (string $body, array $query, \ConxHelper $conx, \Psr\Log\LoggerInterface $logger, \UppServices\SessionService $sessionService): array {
40    $retval = \ApplicationError::Success;
41    $placeData = null;
42    $objid = null;
43    $tx = null;
44    $placeDb = null;
45    $pSchema = null;
46    $device = isset($query['device']) ? (string) $query['device'] : '';
47    $session = isset($query['session']) ? (string) $query['session'] : '';
48    $bodyData = $body !== '' ? (json_decode($body, true) ?? []) : [];
49
50    if (\success($retval)) {
51        if ($device === '' || $session === '') {
52            $logger->error("PlaceService::create: missing device or session in query.");
53            $retval = \ApplicationError::Parameters;
54        }
55    }
56
57    if (\success($retval)) {
58        if ($conx->global === null) {
59            $logger->error("PlaceService::create: failed to connect to central database.");
60            $retval = \ApplicationError::Database;
61        }
62    }
63
64    if (\success($retval)) {
65        $userid = null;
66        $retval = $sessionService->checkSession($conx, $session, $device, $userid);
67        if (\success($retval)) {
68            $placeData = [
69                'status' => 'PA',
70                'user' => (int) $userid,
71            ];
72            if (isset($bodyData['_uuid']) && $bodyData['_uuid'] !== null && $bodyData['_uuid'] !== '') {
73                $placeData['_uuid'] = (string) $bodyData['_uuid'];
74            }
75        }
76    }
77
78    if (\success($retval)) {
79        $tx = $conx->global->begin();
80        if (!$tx) {
81            $logger->error("PlaceService::create: failed to begin transaction.");
82            $retval = \ApplicationError::Database;
83        }
84    }
85
86    if (\success($retval)) {
87        $objidRef = null;
88        $res = $tx->insert('PLACE', $placeData, $objidRef);
89        if (!$res) {
90            $logger->error("PlaceService::create: failed to insert PLACE row.");
91            $retval = \ApplicationError::Database;
92        } else {
93            $objid = (int) $objidRef;
94            $placeDb = 'P'.\str_pad((string) $objid, 8, '0', STR_PAD_LEFT);
95        }
96    }
97
98    if (\success($retval)) {
99        if ($conx->server === null) {
100            $logger->error("PlaceService::create: failed to connect to server for CREATE DATABASE.");
101            $retval = \ApplicationError::Database;
102        }
103    }
104
105    if (\success($retval)) {
106        if (!\create_ddbb_schema($conx->server, $placeDb)) {
107            $logger->error("PlaceService::create: failed to create database '".$placeDb."'.");
108            $retval = \ApplicationError::Database;
109        }
110    }
111
112    if (\success($retval)) {
113        $conx->tenant = $objid;
114        if ($conx->tenant === null) {
115            createplace_drop_database($placeDb, $conx);
116            $logger->error("PlaceService::create: failed to connect to place database '".$placeDb."'.");
117            $retval = \ApplicationError::Database;
118        }
119    }
120
121    if (\success($retval)) {
122        $pSchemaPath = __DIR__.'/../../Resources/model/p_schema.json';
123        if (!\load_ddbb_schema_from($pSchemaPath, $pSchema)) {
124            createplace_drop_database($placeDb, $conx);
125            $logger->error("PlaceService::create: failed to load place schema from JSON.");
126            $retval = \ApplicationError::Database;
127        }
128    }
129
130    if (\success($retval)) {
131        if (!\update_ddbb_schema($conx->tenant, $pSchema)) {
132            createplace_drop_database($placeDb, $conx);
133            $logger->error("PlaceService::create: failed to deploy schema to place database '".$placeDb."'.");
134            $retval = \ApplicationError::Database;
135        }
136    }
137
138    if ($tx !== null) {
139        $tx->flush(\success($retval));
140    }
141    if ($placeDb !== null && !\success($retval)) {
142        createplace_drop_database($placeDb, $conx);
143    }
144
145    $result = [
146        'errorcode' => $retval,
147        'objid' => \success($retval) ? $objid : null,
148    ];
149    return ['output' => json_encode($result), 'contentType' => 'application/json; charset=utf-8'];
150};