Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.29% covered (warning)
89.29%
25 / 28
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
InstanceContextManager
88.89% covered (warning)
88.89%
24 / 27
71.43% covered (warning)
71.43%
5 / 7
16.35
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
 getActiveInstanceId
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getActiveInstance
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
4.25
 isRemote
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 switchToLocal
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 switchToInstance
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 getAllActiveInstances
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Instance\Application\Service;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Instance\Domain\Model\ClientInstance;
12use App\Core\Instance\Domain\Repository\ClientInstanceRepositoryInterface;
13use Yiisoft\Session\SessionInterface;
14
15/**
16 * Instance Context Manager Service.
17 *
18 * Manages active instance context switching between local admin console
19 * and connected remote client SaaS application instances.
20 *
21 * @package App\Core\Instance\Application\Service
22 */
23final readonly class InstanceContextManager implements InstanceContextManagerInterface
24{
25    public const string SESSION_KEY = 'active_client_instance_id';
26
27    /**
28     * InstanceContextManager constructor.
29     *
30     * @param ClientInstanceRepositoryInterface $instanceRepo Instance repository.
31     * @param SessionInterface $session Active user session.
32     */
33    public function __construct(
34        private ClientInstanceRepositoryInterface $instanceRepo,
35        private SessionInterface $session
36    ) {
37    }
38
39    /**
40     * Returns currently active instance ID (or null for local admin console).
41     *
42     * @return int|null Instance ID or null if local.
43     */
44    public function getActiveInstanceId(): ?int
45    {
46        $val = $this->session->get(self::SESSION_KEY) ?? ($_SESSION[self::SESSION_KEY] ?? null);
47        if ($val === null || (int) $val <= 0) {
48            return null;
49        }
50
51        return (int) $val;
52    }
53
54    /**
55     * Returns active ClientInstance domain model or null if local.
56     *
57     * @return ClientInstance|null Active instance or null.
58     */
59    public function getActiveInstance(): ?ClientInstance
60    {
61        $id = $this->getActiveInstanceId();
62        if ($id === null) {
63            return null;
64        }
65
66        $instance = $this->instanceRepo->findById($id);
67        if ($instance === null || !$instance->isActive) {
68            $this->switchToLocal();
69            return null;
70        }
71
72        return $instance;
73    }
74
75    /**
76     * Checks if current execution context is connected to a remote client instance.
77     *
78     * @return bool True if remote instance is active.
79     */
80    public function isRemote(): bool
81    {
82        return false;
83    }
84
85    /**
86     * Switches context to local admin console.
87     */
88    public function switchToLocal(): void
89    {
90        $this->session->remove(self::SESSION_KEY);
91        if (isset($_SESSION[self::SESSION_KEY])) {
92            unset($_SESSION[self::SESSION_KEY]);
93        }
94    }
95
96    /**
97     * Switches context to specified remote client instance.
98     *
99     * @param int $instanceId Target instance ID.
100     * @return bool True if switch succeeded, false if instance not found/inactive.
101     */
102    public function switchToInstance(int $instanceId): bool
103    {
104        if ($instanceId <= 0) {
105            $this->switchToLocal();
106            return true;
107        }
108
109        $instance = $this->instanceRepo->findById($instanceId);
110        if ($instance === null || !$instance->isActive) {
111            return false;
112        }
113
114        $this->session->set(self::SESSION_KEY, $instance->id);
115        $_SESSION[self::SESSION_KEY] = $instance->id;
116        return true;
117    }
118
119    /**
120     * Returns all available active instances for context selection dropdown.
121     *
122     * @return list<ClientInstance> List of active instances.
123     */
124    public function getAllActiveInstances(): array
125    {
126        return $this->instanceRepo->findAllActive();
127    }
128}