PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Controller / Mobile / GetMobileInfoController.php
ameliabooking / src / Application / Controller / Mobile Last commit date
Appointments 2 weeks ago Events 2 weeks ago GetMobileInfoController.php 2 weeks ago MobileV1Controller.php 2 weeks ago
GetMobileInfoController.php
106 lines
1 <?php
2
3 namespace AmeliaBooking\Application\Controller\Mobile;
4
5 use AmeliaBooking\Application\Controller\Controller;
6 use AmeliaBooking\Infrastructure\Licence\Licence;
7 use AmeliaVendor\Psr\Http\Message\ServerRequestInterface as Request;
8 use AmeliaVendor\Psr\Http\Message\ResponseInterface as Response;
9
10 /**
11 * Version-negotiation handshake for the Amelia Staff mobile app.
12 *
13 * The mobile app talks to the versioned /mobile/v1/* routes, but different sites
14 * run different plugin builds. This endpoint lets the app detect version skew
15 * BEFORE it makes (or fails) a real call, so it can show a precise "update the
16 * plugin" vs "update the app" dialog instead of a cryptic 404.
17 *
18 * Contract (must stay stable FOREVER — it is the thing used to detect breaking
19 * changes, so it can never itself have one):
20 *
21 * GET /mobile/info -> 200 {
22 * "message": "success",
23 * "data": {
24 * "pluginVersion": "9.5", // AMELIA_VERSION, informational
25 * "mobileApi": { "min": 1, "max": 1}, // inclusive range of mobile-API
26 * // contract versions this build serves
27 * "licenseOk": true // false when the installed license does
28 * // not include the mobile-app feature (Pro+)
29 * }
30 * }
31 *
32 * Deliberately:
33 * - UNVERSIONED — lives outside /mobile/v1/ so it survives any contract change.
34 * - UNAUTHENTICATED — extends the base Controller (NOT MobileV1Controller, which
35 * forces a Bearer token) and returns its payload directly, bypassing the
36 * command/handler pipeline. No token, nonce, API key or DB access. The app
37 * calls it before login, so it must work with no credentials.
38 *
39 * The app declares the single contract version it was built against and compares:
40 * appVersion > max -> plugin too old -> "update the plugin"
41 * appVersion < min -> contract dropped -> "update the app" (force-update case)
42 * otherwise -> compatible
43 *
44 * Release invariant: this endpoint MUST ship in the same release as the
45 * /mobile/v1/* routes (see MobileV1.php), otherwise the very release that
46 * introduces mobile support would fail its own compatibility check.
47 *
48 * Bump protocol for the constants below:
49 * - Raise MOBILE_API_MAX when adding a new, additive mobile-API contract version.
50 * - Raise MOBILE_API_MIN only when DELIBERATELY dropping support for an older app
51 * contract — this forces those app builds to update.
52 */
53 class GetMobileInfoController extends Controller
54 {
55 /** Oldest mobile-API contract version this plugin build still serves. */
56 public const MOBILE_API_MIN = 1;
57
58 /** Newest mobile-API contract version this plugin build serves. */
59 public const MOBILE_API_MAX = 1;
60
61 /**
62 * @param Request $request
63 * @param Response $response
64 * @param $args
65 * @param bool $validApiCall
66 *
67 * @return Response
68 */
69 public function __invoke(Request $request, Response $response, $args, $validApiCall = false)
70 {
71 $response = $response->withStatus(self::STATUS_OK);
72 $response = $response->withHeader('Content-Type', 'application/json;charset=utf-8');
73 $response->getBody()->write(
74 json_encode(
75 [
76 'message' => 'success',
77 'data' => [
78 'pluginVersion' => defined('AMELIA_VERSION') ? AMELIA_VERSION : null,
79 'mobileApi' => [
80 'min' => self::MOBILE_API_MIN,
81 'max' => self::MOBILE_API_MAX,
82 ],
83 'licenseOk' => Licence::hasFeatureAccess('mobileApp'),
84 ],
85 ]
86 )
87 );
88
89 return $response;
90 }
91
92 /**
93 * Required by the base Controller, but never reached: __invoke returns the
94 * static handshake payload directly and never enters the command pipeline.
95 *
96 * @param Request $request
97 * @param $args
98 *
99 * @return null
100 */
101 protected function instantiateCommand(Request $request, $args)
102 {
103 return null;
104 }
105 }
106