`Element.scrollTo()` is not standardized
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / style / Style.class.php
1 <?php
2 namespace wcf\data\style;
3 use wcf\data\DatabaseObject;
4 use wcf\system\WCF;
5
6 /**
7 * Represents a style.
8 *
9 * @author Marcel Werk
10 * @copyright 2001-2017 WoltLab GmbH
11 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12 * @package WoltLabSuite\Core\Data\Style
13 *
14 * @property-read integer $styleID unique id of the style
15 * @property-read integer $packageID id of the package which delivers the style
16 * @property-read string $styleName name of style
17 * @property-read integer $templateGroupID id of the template group used for the style or `0` if the style uses no specific template group
18 * @property-read integer $isDefault is `1` if the style is the default style for guests and users, otherwise `0`
19 * @property-read integer $isDisabled is `1` if the style is disabled and thus cannot be used without having the specific permission to do so, otherwise `0`
20 * @property-read string $styleDescription description of the style or name of the language item which contains the description
21 * @property-read string $styleVersion version number of the style
22 * @property-read string $styleDate date when the used version of the style has been published
23 * @property-read string $image link or path (relative to `WCF_DIR`) to the preview image of the style
24 * @property-read string $copyright copyright text of the style
25 * @property-read string $license name of the style's license
26 * @property-read string $authorName name(s) of the style's author(s)
27 * @property-read string $authorURL link to the author's website
28 * @property-read string $imagePath path (relative to `WCF_DIR`) to the images used by the style or empty if style has no special image path
29 * @property-read string $packageName package identifier used to export the style as a package or empty (thus style cannot be exported as package)
30 * @property-read integer $isTainted is `0` if the original declarations of an imported or installed style are not and cannot be altered, otherwise `1`
31 */
32 class Style extends DatabaseObject {
33 /**
34 * list of style variables
35 * @var string[]
36 */
37 protected $variables = [];
38
39 const PREVIEW_IMAGE_MAX_HEIGHT = 64;
40 const PREVIEW_IMAGE_MAX_WIDTH = 102;
41
42 /**
43 * Returns the name of this style.
44 *
45 * @return string
46 */
47 public function __toString() {
48 return $this->styleName;
49 }
50
51 /**
52 * Returns the styles variables of this style.
53 *
54 * @return string[]
55 */
56 public function getVariables() {
57 $this->loadVariables();
58
59 return $this->variables;
60 }
61
62 /**
63 * Returns a specific style variable or null if not found.
64 * If $toHex is set to true the color defined by the variable
65 * will be converted to the hexadecimal notation (e.g. for use
66 * in emails)
67 *
68 * @param string $variableName
69 * @param boolean $toHex
70 * @return string
71 */
72 public function getVariable($variableName, $toHex = false) {
73 if (isset($this->variables[$variableName])) {
74 // check if variable is empty
75 if ($this->variables[$variableName] == '~""') {
76 return '';
77 }
78
79 if ($toHex && preg_match('/^rgba\((\d+), (\d+), (\d+), (1|0\.\d+)\)$/', $this->variables[$variableName], $matches)) {
80 $r = $matches[1];
81 $g = $matches[2];
82 $b = $matches[3];
83 $a = floatval($matches[4]);
84
85 // calculate alpha value assuming a white canvas, source rgb will be (255,255,255) or #fff
86 // see https://stackoverflow.com/a/2049362
87 if ($a < 1) {
88 $r = ((1 - $a) * 255) + ($a * $r);
89 $g = ((1 - $a) * 255) + ($a * $g);
90 $b = ((1 - $a) * 255) + ($a * $b);
91
92 $clamp = function($v) {
93 return max(0, min(255, intval($v)));
94 };
95
96 $r = $clamp($r);
97 $g = $clamp($g);
98 $b = $clamp($b);
99 }
100
101 return sprintf('#%02x%02x%02x', $r, $g, $b);
102 }
103
104 return $this->variables[$variableName];
105 }
106
107 return null;
108 }
109
110 /**
111 * Loads style-specific variables.
112 */
113 public function loadVariables() {
114 if (!empty($this->variables)) {
115 return;
116 }
117
118 $sql = "SELECT variable.variableName, variable.defaultValue, value.variableValue
119 FROM wcf".WCF_N."_style_variable variable
120 LEFT JOIN wcf".WCF_N."_style_variable_value value
121 ON (value.variableID = variable.variableID AND value.styleID = ?)
122 ORDER BY variable.variableID ASC";
123 $statement = WCF::getDB()->prepareStatement($sql);
124 $statement->execute([$this->styleID]);
125 while ($row = $statement->fetchArray()) {
126 $variableName = $row['variableName'];
127 $variableValue = isset($row['variableValue']) ? $row['variableValue'] : $row['defaultValue'];
128
129 $this->variables[$variableName] = $variableValue;
130 }
131 }
132
133 /**
134 * Returns the style preview image path.
135 *
136 * @return string
137 */
138 public function getPreviewImage() {
139 if ($this->image && file_exists(WCF_DIR.'images/'.$this->image)) {
140 return WCF::getPath().'images/'.$this->image;
141 }
142
143 return WCF::getPath().'images/stylePreview.png';
144 }
145
146 /**
147 * Splits the less variables string.
148 *
149 * @param string $variables
150 * @return array
151 * @since 3.0
152 */
153 public static function splitLessVariables($variables) {
154 $tmp = explode("/* WCF_STYLE_CUSTOM_USER_MODIFICATIONS */\n", $variables, 2);
155
156 return [
157 'preset' => $tmp[0],
158 'custom' => isset($tmp[1]) ? $tmp[1] : ''
159 ];
160 }
161
162 /**
163 * Joins the less variables.
164 *
165 * @param string $preset
166 * @param string $custom
167 * @return string
168 * @since 3.0
169 */
170 public static function joinLessVariables($preset, $custom) {
171 if (empty($custom)) {
172 return $preset;
173 }
174
175 return $preset . "/* WCF_STYLE_CUSTOM_USER_MODIFICATIONS */\n" . $custom;
176 }
177 }