1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * http://www.gnu.org/copyleft/gpl.html
18 *
19 * @file
20 * @since 1.35
21 */
22
23namespace Vector;
24
25use Config;
26use User;
27use WebRequest;
28
29/**
30 * Given initial dependencies, retrieve the current skin version. This class does no parsing, just
31 * the lookup.
32 *
33 * Skin version is evaluated in the following order:
34 *
35 * - useskinversion URL query parameter override. See readme.
36 *
37 * - User preference. The User object for new accounts is updated (persisted as a user preference)
38 *   by hook according to VectorDefaultSkinVersionForNewAccounts. See Hooks and skin.json. The user
39 *   may then change the preference at will.
40 *
41 * - Site configuration default. The default is controlled by VectorDefaultSkinVersion and
42 *   VectorDefaultSkinVersionForExistingAccounts based on login state. The former is used
43 *   for anonymous users and as a fallback configuration, the latter is logged in users (existing
44 *   accounts). See skin.json.
45 *
46 * @unstable
47 *
48 * @package Vector
49 * @internal
50 */
51final class SkinVersionLookup {
52	/**
53	 * @var WebRequest
54	 */
55	private $request;
56	/**
57	 * @var User
58	 */
59	private $user;
60	/**
61	 * @var Config
62	 */
63	private $config;
64
65	/**
66	 * This constructor accepts all dependencies needed to obtain the skin version. The dependencies
67	 * are lazily evaluated, not cached, meaning they always return the current results.
68	 *
69	 * @param WebRequest $request
70	 * @param User $user
71	 * @param Config $config
72	 */
73	public function __construct( WebRequest $request, User $user, Config $config ) {
74		$this->request = $request;
75		$this->user = $user;
76		$this->config = $config;
77	}
78
79	/**
80	 * Whether or not the legacy skin is being used.
81	 *
82	 * @return bool
83	 * @throws \ConfigException
84	 */
85	public function isLegacy(): bool {
86		return $this->getVersion() === Constants::SKIN_VERSION_LEGACY;
87	}
88
89	/**
90	 * The skin version as a string. E.g., `Constants::SKIN_VERSION_LATEST`,
91	 * `Constants::SKIN_VERSION_LATEST`, or maybe 'beta'. Note: it's likely someone will put arbitrary
92	 * strings in the query parameter which means this function returns those strings as is.
93	 *
94	 * @return string
95	 * @throws \ConfigException
96	 */
97	public function getVersion(): string {
98		// Obtain the skin version from the 1) `useskinversion` URL query parameter override, 2) the
99		// user preference, 3) the configured default for logged in users, 4) or the site default.
100		//
101		// The latter two configurations cannot be set by `Hooks::onUserGetDefaultOptions()` as user
102		// sessions are unavailable at that time so it's not possible to determine whether the
103		// preference is for a logged in user or an anonymous user. Since new users are known to have
104		// had their user preferences initialized in `Hooks::onLocalUserCreated()`, that means all
105		// subsequent requests to `User->getOption()` that do not have a preference set are either
106		// existing accounts or anonymous users. Login state makes the distinction.
107		return (string)$this->request->getVal(
108			Constants::QUERY_PARAM_SKIN_VERSION,
109			$this->user->getOption(
110				Constants::PREF_KEY_SKIN_VERSION,
111				$this->config->get(
112					$this->user->isRegistered()
113						? Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION_FOR_EXISTING_ACCOUNTS
114						: Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION
115				)
116			)
117		);
118	}
119}
120