Merge branch '3.1' into 5.2
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / DatabaseObjectEditor.class.php
1 <?php
2 namespace wcf\data;
3 use wcf\system\database\util\PreparedStatementConditionBuilder;
4 use wcf\system\WCF;
5
6 /**
7 * Basic implementation for object editors following the decorator pattern.
8 *
9 * @author Marcel Werk
10 * @copyright 2001-2019 WoltLab GmbH
11 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
12 * @package WoltLabSuite\Core\Data
13 */
14 abstract class DatabaseObjectEditor extends DatabaseObjectDecorator implements IEditableObject {
15 /**
16 * @inheritDoc
17 */
18 public static function create(array $parameters = []) {
19 $keys = $values = '';
20 $statementParameters = [];
21 foreach ($parameters as $key => $value) {
22 if (!empty($keys)) {
23 $keys .= ',';
24 $values .= ',';
25 }
26
27 $keys .= $key;
28 $values .= '?';
29 $statementParameters[] = $value;
30 }
31
32 // save object
33 $sql = "INSERT INTO ".static::getDatabaseTableName()."
34 (".$keys.")
35 VALUES (".$values.")";
36 $statement = WCF::getDB()->prepareStatement($sql);
37 $statement->execute($statementParameters);
38
39 // return new object
40 if (static::getDatabaseTableIndexIsIdentity()) {
41 $id = WCF::getDB()->getInsertID(static::getDatabaseTableName(), static::getDatabaseTableIndexName());
42 }
43 else {
44 $id = $parameters[static::getDatabaseTableIndexName()];
45 }
46 return new static::$baseClass($id);
47 }
48
49 /**
50 * @inheritDoc
51 */
52 public function update(array $parameters = []) {
53 if (empty($parameters)) return;
54
55 $updateSQL = '';
56 $statementParameters = [];
57 foreach ($parameters as $key => $value) {
58 if (!empty($updateSQL)) $updateSQL .= ', ';
59 $updateSQL .= $key . ' = ?';
60 $statementParameters[] = $value;
61 }
62 $statementParameters[] = $this->getObjectID();
63
64 $sql = "UPDATE ".static::getDatabaseTableName()."
65 SET ".$updateSQL."
66 WHERE ".static::getDatabaseTableIndexName()." = ?";
67 $statement = WCF::getDB()->prepareStatement($sql);
68 $statement->execute($statementParameters);
69 }
70
71 /**
72 * @inheritDoc
73 */
74 public function updateCounters(array $counters = []) {
75 if (empty($counters)) return;
76
77 $updateSQL = '';
78 $statementParameters = [];
79 foreach ($counters as $key => $value) {
80 if (!empty($updateSQL)) $updateSQL .= ', ';
81 $updateSQL .= $key . ' = ' . $key . ' + ?';
82 $statementParameters[] = $value;
83 }
84 $statementParameters[] = $this->getObjectID();
85
86 $sql = "UPDATE ".static::getDatabaseTableName()."
87 SET ".$updateSQL."
88 WHERE ".static::getDatabaseTableIndexName()." = ?";
89 $statement = WCF::getDB()->prepareStatement($sql);
90 $statement->execute($statementParameters);
91 }
92
93 /**
94 * @inheritDoc
95 */
96 public function delete() {
97 static::deleteAll([$this->getObjectID()]);
98 }
99
100 /**
101 * @inheritDoc
102 */
103 public static function deleteAll(array $objectIDs = []) {
104 $affectedCount = 0;
105
106 $itemsPerLoop = 1000;
107 $loopCount = ceil(count($objectIDs) / $itemsPerLoop);
108
109 WCF::getDB()->beginTransaction();
110 for ($i = 0; $i < $loopCount; $i++) {
111 $batchObjectIDs = array_slice($objectIDs, $i * $itemsPerLoop, $itemsPerLoop);
112
113 $conditionBuilder = new PreparedStatementConditionBuilder();
114 $conditionBuilder->add(static::getDatabaseTableIndexName() . ' IN (?)', [$batchObjectIDs]);
115
116 $sql = "DELETE FROM " . static::getDatabaseTableName() . "
117 " . $conditionBuilder;
118 $statement = WCF::getDB()->prepareStatement($sql);
119 $statement->execute($conditionBuilder->getParameters());
120 $affectedCount += $statement->getAffectedRows();
121 }
122 WCF::getDB()->commitTransaction();
123
124 return $affectedCount;
125 }
126 }