Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.56% covered (success)
95.56%
43 / 45
83.33% covered (warning)
83.33%
10 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
Context
95.56% covered (success)
95.56%
43 / 45
83.33% covered (warning)
83.33%
10 / 12
17
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
 console
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 assets
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 paths
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 locales
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 locale
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 defaultLocale
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 localeId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 translator
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 httpRequest
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 origin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 withLocale
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray;
6
7use Celema\Container\Container;
8use Celema\Core\Factory\Factory;
9use Celema\Core\Request;
10use Celema\Quma\Database;
11use Celema\Verba\Translator;
12use Celema\Verba\Verba;
13use Closure;
14
15final class Context
16{
17    private ?Assets\Repository $assets = null;
18    private ?Node\UrlPaths $paths = null;
19    private ?Locales $runtimeLocales = null;
20    private ?Locale $runtimeLocale = null;
21
22    /** @var array<string, Translator> */
23    private array $translators = [];
24
25    public function __construct(
26        public readonly Database $db,
27        public readonly ?Request $request,
28        public readonly Config $config,
29        public readonly Container $container,
30        public readonly Factory $factory,
31    ) {}
32
33    public static function console(
34        Database $db,
35        Config $config,
36        Container $container,
37        Factory $factory,
38        Locales $locales,
39    ): self {
40        $context = new self($db, null, $config, $container, $factory);
41        $context->runtimeLocales = $locales;
42        $context->runtimeLocale = $locales->getDefault();
43
44        return $context;
45    }
46
47    public function assets(): Assets\Repository
48    {
49        return $this->assets ??= new Assets\Repository($this->db, $this->config);
50    }
51
52    public function paths(): Node\UrlPaths
53    {
54        return $this->paths ??= new Node\UrlPaths($this->db);
55    }
56
57    public function locales(): Locales
58    {
59        if ($this->runtimeLocales !== null) {
60            return $this->runtimeLocales;
61        }
62
63        $locales = $this->request?->get('locales', null);
64
65        if (!$locales instanceof Locales) {
66            throw new Exception\RuntimeException('Locales are not available in this CMS context');
67        }
68
69        return $locales;
70    }
71
72    public function locale(): Locale
73    {
74        if ($this->runtimeLocale !== null) {
75            return $this->runtimeLocale;
76        }
77
78        $locale = $this->request?->get('locale', null);
79
80        if (!$locale instanceof Locale) {
81            throw new Exception\RuntimeException('The current locale is not available in this CMS context');
82        }
83
84        return $locale;
85    }
86
87    public function defaultLocale(): Locale
88    {
89        return $this->locales()->getDefault();
90    }
91
92    public function localeId(): string
93    {
94        return $this->locale()->id;
95    }
96
97    public function translator(): Translator
98    {
99        $locale = $this->locale();
100
101        return $this->translators[$locale->id] ??= new Translator(
102            $locale->id,
103            $this->locales()->catalogs(),
104            $locale->fallbacks(),
105        );
106    }
107
108    public function httpRequest(): Request
109    {
110        return (
111            $this->request ?? throw new Exception\RuntimeException(
112                'An HTTP request is not available in this CMS context',
113            )
114        );
115    }
116
117    public function origin(): string
118    {
119        return $this->request?->origin() ?? '';
120    }
121
122    public function withLocale(Locale $locale, Closure $callback): mixed
123    {
124        $runtimeLocale = $this->runtimeLocale;
125        $requestLocale = $this->request?->get('locale', null);
126        $translator = Verba::translator();
127        $this->runtimeLocale = $locale;
128        $this->request?->set('locale', $locale);
129        Verba::activate($this->translator());
130
131        try {
132            return $callback();
133        } finally {
134            $this->runtimeLocale = $runtimeLocale;
135            $this->request?->set('locale', $requestLocale);
136
137            if ($translator !== null) {
138                Verba::activate($translator);
139            } else {
140                Verba::deactivate();
141            }
142        }
143    }
144}