Merge branch '6.0'
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / DatabaseObject.class.php
CommitLineData
158bd3ca 1<?php
a9229942 2
158bd3ca 3namespace wcf\data;
a9229942 4
158bd3ca
TD
5use wcf\system\WCF;
6
7/**
8 * Abstract class for all data holder classes.
a9229942
TD
9 *
10 * @author Marcel Werk
11 * @copyright 2001-2019 WoltLab GmbH
12 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
158bd3ca 13 */
a9229942
TD
14abstract class DatabaseObject implements IIDObject, IStorableObject
15{
16 /**
17 * database table for this object
18 * @var string
19 */
20 protected static $databaseTableName = '';
21
22 /**
23 * indicates if database table index is an identity column
24 * @var bool
25 */
26 protected static $databaseTableIndexIsIdentity = true;
27
28 /**
29 * name of the primary index column
30 * @var string
31 */
32 protected static $databaseTableIndexName = '';
33
34 /**
35 * sort field
36 * @var mixed
37 */
55a3a842 38 protected static $sortBy;
a9229942
TD
39
40 /**
41 * sort order
42 * @var mixed
43 */
55a3a842 44 protected static $sortOrder;
a9229942
TD
45
46 /**
47 * object data
48 * @var array
49 */
50 protected $data;
51
52 /**
53 * Creates a new instance of the DatabaseObject class.
54 *
55 * @param mixed $id
56 * @param array $row
57 * @param DatabaseObject $object
58 */
59 public function __construct($id, ?array $row = null, ?self $object = null)
60 {
61 if ($id !== null) {
62 $sql = "SELECT *
63 FROM " . static::getDatabaseTableName() . "
64 WHERE " . static::getDatabaseTableIndexName() . " = ?";
65 $statement = WCF::getDB()->prepareStatement($sql);
66 $statement->execute([$id]);
67 $row = $statement->fetchArray();
68
69 // enforce data type 'array'
70 if ($row === false) {
71 $row = [];
72 }
73 } elseif ($object !== null) {
74 $row = $object->data;
75 }
76
77 $this->handleData($row);
78 }
79
80 /**
81 * Stores the data of a database row.
82 *
83 * @param array $data
84 */
85 protected function handleData($data)
86 {
87 // provide a logical false value for - assumed numeric - primary index
88 if (!isset($data[static::getDatabaseTableIndexName()])) {
89 $data[static::getDatabaseTableIndexName()] = 0;
90 }
91
92 $this->data = $data;
93 }
94
95 /**
96 * @inheritDoc
97 */
98 public function __get($name)
99 {
62ee156d 100 return $this->data[$name] ?? null;
a9229942
TD
101 }
102
103 /**
104 * Returns the id of the object.
105 *
106 * @return int
107 */
108 public function getObjectID()
109 {
110 return $this->data[static::getDatabaseTableIndexName()];
111 }
112
113 /**
114 * @inheritDoc
115 */
116 public function __isset($name)
117 {
118 return isset($this->data[$name]);
119 }
120
121 /**
122 * @inheritDoc
123 */
124 public function getData()
125 {
126 return $this->data;
127 }
128
129 /**
130 * @inheritDoc
131 */
132 public static function getDatabaseTableName()
133 {
0befcb4a 134 $className = static::class;
a9229942
TD
135 $classParts = \explode('\\', $className);
136
137 if (static::$databaseTableName !== '') {
138 return $classParts[0] . WCF_N . '_' . static::$databaseTableName;
139 }
140
141 static $databaseTableNames = [];
142 if (!isset($databaseTableNames[$className])) {
143 $databaseTableNames[$className] = $classParts[0] . WCF_N . '_' . \strtolower(\implode(
144 '_',
145 \preg_split(
146 '~(?=[A-Z](?=[a-z]))~',
147 \array_pop($classParts),
148 -1,
149 \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY
150 )
151 ));
152 }
153
154 return $databaseTableNames[$className];
155 }
156
157 /**
158 * @inheritDoc
159 */
160 public static function getDatabaseTableAlias()
161 {
162 if (static::$databaseTableName !== '') {
163 return static::$databaseTableName;
164 }
165
0befcb4a 166 $className = static::class;
a9229942
TD
167 static $databaseTableAliases = [];
168 if (!isset($databaseTableAliases[$className])) {
169 $classParts = \explode('\\', $className);
170 $databaseTableAliases[$className] = \strtolower(\implode(
171 '_',
172 \preg_split(
173 '~(?=[A-Z](?=[a-z]))~',
174 \array_pop($classParts),
175 -1,
176 \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY
177 )
178 ));
179 }
180
181 return $databaseTableAliases[$className];
182 }
183
184 /**
185 * @inheritDoc
186 */
187 public static function getDatabaseTableIndexIsIdentity()
188 {
189 return static::$databaseTableIndexIsIdentity;
190 }
191
192 /**
193 * @inheritDoc
194 */
195 public static function getDatabaseTableIndexName()
196 {
197 if (static::$databaseTableIndexName !== '') {
198 return static::$databaseTableIndexName;
199 }
200
8145cab1 201 $className = static::class;
8ee2baf0
TD
202 static $databaseTableIndexNames = [];
203 if (!isset($databaseTableIndexNames[$className])) {
204 $classParts = \explode('\\', $className);
a9229942
TD
205 $parts = \preg_split(
206 '~(?=[A-Z](?=[a-z]))~',
8ee2baf0 207 \array_pop($classParts),
a9229942
TD
208 -1,
209 \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY
210 );
8ee2baf0 211 $databaseTableIndexNames[$className] = \strtolower(\array_pop($parts)) . 'ID';
a9229942
TD
212 }
213
8ee2baf0 214 return $databaseTableIndexNames[$className];
a9229942
TD
215 }
216
217 /**
218 * Sorts a list of database objects.
219 *
220 * @param DatabaseObject[] $objects
221 * @param mixed $sortBy
222 * @param string $sortOrder
223 * @param bool $maintainIndexAssociation
224 */
225 public static function sort(&$objects, $sortBy, $sortOrder = 'ASC', $maintainIndexAssociation = true)
226 {
227 $sortArray = $objects2 = [];
228 foreach ($objects as $idx => $obj) {
229 /** @noinspection PhpVariableVariableInspection */
230 $sortArray[$idx] = $obj->{$sortBy};
231
232 // array_multisort will drop index association if key is not a string
233 if ($maintainIndexAssociation) {
234 $objects2[$idx . 'x'] = $obj;
235 }
236 }
237
238 if ($maintainIndexAssociation) {
239 $objects = [];
e745d478
C
240 \array_multisort(
241 $sortArray,
242 $sortOrder == 'ASC' ? \SORT_ASC : \SORT_DESC,
243 \SORT_NATURAL | \SORT_FLAG_CASE,
244 $objects2
245 );
a9229942
TD
246
247 $objects = [];
248 foreach ($objects2 as $idx => $obj) {
249 $objects[\substr($idx, 0, -1)] = $obj;
250 }
251 } else {
e745d478
C
252 \array_multisort(
253 $sortArray,
254 $sortOrder == 'ASC' ? \SORT_ASC : \SORT_DESC,
255 \SORT_NATURAL | \SORT_FLAG_CASE,
256 $objects
257 );
a9229942
TD
258 }
259 }
004426c2 260}