Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.46% covered (success)
91.46%
75 / 82
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
SyncService
91.46% covered (success)
91.46%
75 / 82
33.33% covered (danger)
33.33%
1 / 3
33.68
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 synchronize
96.30% covered (success)
96.30%
26 / 27
0.00% covered (danger)
0.00%
0 / 1
9
 objidRequest
88.89% covered (success)
88.89%
48 / 54
0.00% covered (danger)
0.00%
0 / 1
23.73
1<?php
2
3declare(strict_types=1);
4
5namespace UppServices;
6
7use Psr\Http\Message\ServerRequestInterface;
8
9/**
10 * Handles sync flow: apply client changes and return updates (long-poll).
11 * Uses sync logic in Services/legacy/model/synchronize.php (run_synchronize).
12 * Follows tenantddbb-bestpractices: single ConxHelper; the helper creates connections lazily
13 * (->global, ->tenant when place is set). run_synchronize uses ->global for user target and ->tenant for place/table.
14 */
15class SyncService
16{
17    public function __construct()
18    {
19        require_once __DIR__.'/legacy/model/synchronize.php';
20    }
21
22    /**
23     * Run the full sync flow: validate session, apply changes, refresh/wait, load updates.
24     * Central when target=user or no place; place DB (P + 8 digits) when target=place and place is set.
25     * ConxHelper creates connections on first use; run_synchronize receives $conx and schema name for reconnect.
26     *
27     * @return array{errorcode: int, timestamp: mixed, reference: int, target: mixed, updated: bool, expired: bool, updates: array}
28     */
29    public function synchronize(ServerRequestInterface $request): array
30    {
31        $retval = \ApplicationError::Success;
32        $queryParams = $request->getQueryParams();
33        $postBody = (string) $request->getBody();
34        $target = $queryParams['target'] ?? null;
35        $place = isset($queryParams['place']) ? $queryParams['place'] : null;
36
37        $result = [
38            'errorcode' => $retval,
39            'timestamp' => null,
40            'reference' => 0,
41            'target' => $target,
42            'updated' => false,
43            'expired' => false,
44            'updates' => [],
45        ];
46
47        $conx = null;
48        if (\success($retval)) {
49            require_once __DIR__ . '/legacy/ddbb/conx.php';
50            $conx = new \ConxHelper(__FILE__);
51        }
52
53        if (\success($retval) && $conx !== null) {
54            $conx->tenant = $place;
55        }
56
57        if (\success($retval) && $conx !== null) {
58            $result = \run_synchronize($conx, $queryParams, $postBody);
59        }
60
61        if ($conx !== null) {
62            $conx->release();
63        }
64
65        // When we never ran run_synchronize, ensure errorcode reflects current $retval (e.g. validation failure).
66        if ($result['timestamp'] === null) {
67            $result['errorcode'] = $retval;
68        }
69
70        return $result;
71    }
72
73    /**
74     * Fetch a single row by objid from a tenant table (on-demand refresh during sync).
75     * Validates session (central DB), then queries the place DB for the given table and objid.
76     *
77     * @param ServerRequestInterface $request Query params: device, session, place, table, objid.
78     * @return array{errorcode: int, info: array|null} errorcode and row data on success.
79     */
80    public function objidRequest(ServerRequestInterface $request): array
81    {
82        $retval = \ApplicationError::Success;
83        $info = null;
84
85        $queryParams = $request->getQueryParams();
86        $device = $queryParams['device'] ?? null;
87        $session = $queryParams['session'] ?? null;
88        $place = $queryParams['place'] ?? null;
89        $table = $queryParams['table'] ?? null;
90        $objid = $queryParams['objid'] ?? null;
91
92        $conx = null;
93        if (\success($retval)) {
94            require_once __DIR__.'/legacy/ddbb/conx.php';
95            require_once __DIR__.'/legacy/session/session.php';
96            $conx = new \ConxHelper(__FILE__);
97        }
98
99        if (\success($retval) && !$device) {
100            \addlog(__FILE__, \LogLevel::Error, "No device provided on URL. Operation cancelled.");
101            $retval = \ApplicationError::Parameters;
102        }
103
104        if (\success($retval) && !$session) {
105            \addlog(__FILE__, \LogLevel::Error, "No session provided on URL. Operation cancelled.");
106            $retval = \ApplicationError::Parameters;
107        }
108
109        if (\success($retval)) {
110            $userid = null;
111            $sessionObjid = false;
112            $retval = \check_session($conx, $session, $device, $userid, $sessionObjid);
113        }
114
115        if (\success($retval) && ($place === false || $place === null || $place === '')) {
116            \addlog(__FILE__, \LogLevel::Error, "Mandatory argument 'place' not provided in url parameters. Operation cancelled.");
117            $retval = \ApplicationError::Parameters;
118        }
119
120        if (\success($retval)) {
121            $conx->tenant = $place;
122        }
123
124        if (\success($retval) && !$table) {
125            \addlog(__FILE__, \LogLevel::Error, "Mandatory argument 'table' not provided in url parameters.");
126            $retval = \ApplicationError::Parameters;
127        }
128
129        if (\success($retval) && !$objid) {
130            \addlog(__FILE__, \LogLevel::Error, "Mandatory argument 'objid' not provided in url parameters.");
131            $retval = \ApplicationError::Parameters;
132        }
133
134        if (\success($retval) && $conx->tenant === null) {
135            \addlog(__FILE__, \LogLevel::Error, "Connection to place database failed.");
136            $retval = \ApplicationError::Database;
137        }
138
139        if (\success($retval)) {
140            $results = [];
141            $res = $conx->tenant->query($table, ["objid" => $objid], $results);
142            if ($res) {
143                if (count($results) > 0) {
144                    $info = $results[0];
145                    \addlog(__FILE__, \LogLevel::Debug, "On-demand refreshing entry: ".$table."@".$objid);
146                }
147                else {
148                    \addlog(__FILE__, \LogLevel::Error, "No entry found for ".$table."@".$objid);
149                    $retval = \ApplicationError::NotFound;
150                }
151            }
152            else {
153                \addlog(__FILE__, \LogLevel::Error, "Query failed for table ".$table." objid ".$objid);
154                $retval = \ApplicationError::Database;
155            }
156        }
157
158        if ($conx !== null) {
159            $conx->release();
160        }
161
162        return [
163            'errorcode' => $retval,
164            'info' => \success($retval) ? $info : null,
165        ];
166    }
167}