Translated using Weblate (Portuguese)
[phpmyadmin.git] / src / Theme / Theme.php
blob1752750a0057fa8cdceda210131283ad7a09aa01
1 <?php
3 declare(strict_types=1);
5 namespace PhpMyAdmin\Theme;
7 use PhpMyAdmin\Exceptions\InvalidImagePath;
8 use PhpMyAdmin\Version;
9 use Webmozart\Assert\Assert;
10 use Webmozart\Assert\InvalidArgumentException;
12 use function __;
13 use function file_exists;
14 use function file_get_contents;
15 use function filemtime;
16 use function filesize;
17 use function in_array;
18 use function is_array;
19 use function is_dir;
20 use function is_readable;
21 use function json_decode;
22 use function sprintf;
23 use function trim;
24 use function version_compare;
26 use const DIRECTORY_SEPARATOR;
28 /**
29 * handles theme
31 * @todo add the possibility to make a theme depend on another theme
32 * and by default on original
33 * @todo make all components optional - get missing components from 'parent' theme
35 class Theme
37 /** @var string theme version */
38 public string $version = '0.0.0.0';
40 /** @var string theme name */
41 public string $name = '';
43 /** @var string theme id */
44 public string $id = '';
46 /** @var string theme path */
47 public string $path = '';
49 /** @var string file system theme path */
50 private string $fsPath = '';
52 /** @var string image path as an URL */
53 public string $imgPath = '';
55 /** @var string image path on the file-system */
56 public string $imgPathFs = '';
58 /** @var int last modification time for info file */
59 public int $mtimeInfo = 0;
61 /**
62 * needed because sometimes, the mtime for different themes
63 * is identical
65 * @var int filesize for info file
67 public int $filesizeInfo = 0;
69 /** @var list<non-empty-string> */
70 private array $colorModes = ['light'];
72 /** @var non-empty-string */
73 private string $colorMode = 'light';
75 /**
76 * Loads theme information
78 public function loadInfo(): bool
80 $infofile = $this->getFsPath() . 'theme.json';
81 if (! @file_exists($infofile)) {
82 return false;
85 if ($this->mtimeInfo === filemtime($infofile)) {
86 return true;
89 $content = @file_get_contents($infofile);
90 if ($content === false) {
91 return false;
94 $data = json_decode($content, true);
96 // Did we get expected data?
97 if (! is_array($data)) {
98 return false;
101 // Check that all required data are there
102 $members = ['name', 'version', 'supports'];
103 foreach ($members as $member) {
104 if (! isset($data[$member])) {
105 return false;
109 // Version check
110 if (! is_array($data['supports'])) {
111 return false;
114 if (! in_array(Version::SERIES, $data['supports'])) {
115 return false;
118 try {
119 Assert::keyExists($data, 'colorModes');
120 Assert::isNonEmptyList($data['colorModes']);
121 Assert::allStringNotEmpty($data['colorModes']);
122 $this->colorModes = $data['colorModes'];
123 $this->colorMode = $this->colorModes[0];
124 } catch (InvalidArgumentException) {
127 $this->mtimeInfo = filemtime($infofile);
128 $this->filesizeInfo = filesize($infofile);
130 $this->setVersion($data['version']);
131 $this->setName($data['name']);
133 return true;
136 public static function load(string $themeUrl, string $themeFsPath, string $themeName): self|null
138 $theme = new self();
140 $theme->setPath($themeUrl);
141 $theme->setFsPath($themeFsPath);
143 if (! $theme->loadInfo()) {
144 return null;
147 $theme->checkImgPath();
148 $theme->setId($themeName);
150 return $theme;
154 * checks image path for existence - if not found use img from fallback theme
156 public function checkImgPath(): bool
158 // try current theme first
159 if (is_dir($this->getFsPath() . 'img' . DIRECTORY_SEPARATOR)) {
160 $this->setImgPath($this->getPath() . '/img/');
161 $this->setImgPathFs($this->getFsPath() . 'img' . DIRECTORY_SEPARATOR);
163 return true;
166 // try fallback theme
167 $fallbackFsPathThemeDir = ThemeManager::getThemesFsDir() . ThemeManager::FALLBACK_THEME
168 . DIRECTORY_SEPARATOR . 'img' . DIRECTORY_SEPARATOR;
169 if (is_dir($fallbackFsPathThemeDir)) {
170 $fallbackUrl = ThemeManager::getThemesDir() . ThemeManager::FALLBACK_THEME
171 . '/img/';
172 $this->setImgPath($fallbackUrl);
173 $this->setImgPathFs($fallbackFsPathThemeDir);
175 return true;
178 throw new InvalidImagePath(sprintf(
179 __('No valid image path for theme %s found!'),
180 $this->getName(),
185 * returns path to theme
187 * @return string path to theme
189 public function getPath(): string
191 return $this->path;
195 * returns file system path to the theme
197 * @return string file system path to theme
199 public function getFsPath(): string
201 return $this->fsPath;
205 * set path to theme
207 * @param string $path path to theme
209 public function setPath(string $path): void
211 $this->path = trim($path);
215 * set file system path to the theme
217 * @param string $path path to theme
219 public function setFsPath(string $path): void
221 $this->fsPath = trim($path);
225 * sets version
227 * @param string $version version to set
229 public function setVersion(string $version): void
231 $this->version = trim($version);
235 * returns version
237 * @return string version
239 public function getVersion(): string
241 return $this->version;
245 * checks theme version against $version
246 * returns true if theme version is equal or higher to $version
248 * @param string $version version to compare to
250 public function checkVersion(string $version): bool
252 return version_compare($this->getVersion(), $version, 'lt');
256 * sets name
258 * @param string $name name to set
260 public function setName(string $name): void
262 $this->name = trim($name);
266 * returns name
268 * @return string name
270 public function getName(): string
272 return $this->name;
276 * sets id
278 * @param string $id new id
280 public function setId(string $id): void
282 $this->id = trim($id);
286 * returns id
288 * @return string id
290 public function getId(): string
292 return $this->id;
296 * Sets path to images for the theme
298 * @param string $path path to images for this theme as an URL path
300 public function setImgPath(string $path): void
302 $this->imgPath = $path;
306 * Sets path to images for the theme
308 * @param string $path file-system path to images for this theme
310 public function setImgPathFs(string $path): void
312 $this->imgPathFs = $path;
316 * Returns the path to image for the theme.
317 * If filename is given, it possibly fallbacks to fallback
318 * theme for it if image does not exist.
320 * @param string|null $file file name for image
321 * @param string|null $fallback fallback image
323 * @return string image path for this theme
325 public function getImgPath(string|null $file = null, string|null $fallback = null): string
327 if ($file === null) {
328 return $this->imgPath;
331 if (is_readable($this->imgPathFs . $file)) {
332 return $this->imgPath . $file;
335 if ($fallback !== null) {
336 return $this->getImgPath($fallback);
339 return './themes/' . ThemeManager::FALLBACK_THEME . '/img/' . $file;
342 /** @return list<non-empty-string> */
343 public function getColorModes(): array
345 return $this->colorModes;
348 public function setColorMode(string $colorMode): void
350 if (! in_array($colorMode, $this->colorModes, true)) {
351 return;
354 $this->colorMode = $colorMode;
357 /** @return non-empty-string */
358 public function getColorMode(): string
360 return $this->colorMode;