PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.10.0
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.10.0
4.10.0 4.9.5 4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Utils / DatabaseOptions.php
wp-staging / Framework / Utils Last commit date
Cache 8 months ago DBPermissions.php 10 months ago DataEncoder.php 11 months ago DatabaseOptions.php 5 days ago Env.php 1 week ago Escape.php 10 months ago Glob.php 2 years ago Hooks.php 4 months ago Math.php 10 months ago PluginInfo.php 7 months ago Sanitize.php 4 months ago ServerVars.php 2 years ago SlashMode.php 5 years ago Strings.php 8 months ago Times.php 7 months ago Urls.php 1 month ago Version.php 1 year ago WpDefaultDirectories.php 2 years ago
DatabaseOptions.php
183 lines
1 <?php
2
3 namespace WPStaging\Framework\Utils;
4
5 use Throwable;
6 use WPStaging\Framework\Adapter\Database;
7 use WPStaging\Framework\Traits\SerializeTrait;
8 use wpdb;
9
10 use function WPStaging\functions\debug_log;
11
12 /**
13 * Class DatabaseOptions
14 *
15 * Provides direct, cache-free access to the WordPress options table.
16 * This bypasses the wp_options caching layer (e.g., object cache, transients)
17 * to allow raw interaction with the database, which is useful authentication of login links.
18 *
19 * @package WPStaging\Framework\Utils
20 */
21 class DatabaseOptions
22 {
23 use SerializeTrait;
24
25 /** @var wpdb */
26 private $db;
27
28 /** @var string */
29 private $optionsTable;
30
31 /**
32 * @param Database $database
33 */
34 public function __construct(Database $database)
35 {
36 $this->db = $database->getWpdb();
37 $this->optionsTable = $database->getPrefix() . 'options';
38 }
39
40 /**
41 * @param string $optionName
42 * @param mixed $defaultValue
43 * @return mixed
44 */
45 public function getOption(string $optionName, $defaultValue = false)
46 {
47 if (!$this->optionExists($optionName)) {
48 return $defaultValue;
49 }
50
51 $sql = $this->db->prepare(
52 "SELECT option_value FROM `{$this->optionsTable}` WHERE option_name = %s LIMIT 1",
53 $optionName
54 );
55
56 $result = $this->db->get_var($sql);
57
58 if ($result === null) {
59 return $defaultValue;
60 }
61
62 $rejected = false;
63 $value = $this->safeMaybeUnserialize($result, [], $rejected);
64
65 if ($rejected) {
66 debug_log(sprintf('Refused to unserialize database option "%s". Falling back to the default value.', $optionName));
67
68 return $defaultValue;
69 }
70
71 return $value;
72 }
73
74 /**
75 * @param string $optionName
76 * @param mixed $optionValue
77 * @param bool $autoload
78 * @return bool
79 */
80 public function updateOption(string $optionName, $optionValue, bool $autoload = true): bool
81 {
82 try {
83 $serializedValue = serialize($optionValue);
84 $autoloadValue = $autoload ? 'yes' : 'no';
85 if ($this->optionExists($optionName)) {
86 $sql = $this->db->prepare(
87 "UPDATE `{$this->optionsTable}`
88 SET option_value = %s, autoload = %s
89 WHERE option_name = %s",
90 $serializedValue,
91 $autoloadValue,
92 $optionName
93 );
94 } else {
95 $sql = $this->db->prepare(
96 "INSERT INTO `{$this->optionsTable}` (option_name, option_value, autoload)
97 VALUES (%s, %s, %s)",
98 $optionName,
99 $serializedValue,
100 $autoloadValue
101 );
102 }
103
104 $result = $this->db->query($sql);
105 if ($result === false) {
106 debug_log(sprintf('Failed to update database option "%s". DB Error: %s', $optionName, $this->getLastDbError()));
107
108 return false;
109 }
110
111 $this->clearOptionCache($optionName);
112
113 return true;
114 } catch (Throwable $ex) {
115 debug_log(sprintf('Exception while updating database option "%s": %s', $optionName, $ex->getMessage()));
116
117 return false;
118 }
119 }
120
121 /**
122 * @param string $optionName
123 * @return bool
124 */
125 public function deleteOption(string $optionName): bool
126 {
127 if (!$this->optionExists($optionName)) {
128 return false;
129 }
130
131 $sql = $this->db->prepare(
132 "DELETE FROM `{$this->optionsTable}` WHERE option_name = %s LIMIT 1",
133 $optionName
134 );
135
136 $result = $this->db->query($sql);
137 if ($result === false) {
138 return false;
139 }
140
141 $this->clearOptionCache($optionName);
142
143 return true;
144 }
145
146 /**
147 * @param string $optionName
148 * @return bool
149 */
150 private function optionExists(string $optionName): bool
151 {
152 $sql = $this->db->prepare(
153 "SELECT 1 FROM `{$this->optionsTable}` WHERE option_name = %s LIMIT 1",
154 $optionName
155 );
156
157 return (bool) $this->db->get_var($sql);
158 }
159
160 /**
161 * @return string
162 */
163 private function getLastDbError(): string
164 {
165 return !empty($this->db->last_error) ? $this->db->last_error : 'Unknown database error';
166 }
167
168 /**
169 * @param string $optionName
170 * @return void
171 */
172 private function clearOptionCache(string $optionName)
173 {
174 if (!function_exists('wp_cache_delete')) {
175 return;
176 }
177
178 wp_cache_delete($optionName, 'options');
179 wp_cache_delete('alloptions', 'options');
180 wp_cache_delete('notoptions', 'options');
181 }
182 }
183