PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.2
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.2
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 7 months ago DBPermissions.php 9 months ago DataEncoder.php 10 months ago DatabaseOptions.php 2 weeks ago Escape.php 9 months ago Glob.php 2 years ago Hooks.php 2 months ago Math.php 9 months ago PluginInfo.php 5 months ago Sanitize.php 2 months ago ServerVars.php 2 years ago SlashMode.php 5 years ago Strings.php 7 months ago Times.php 5 months ago Urls.php 2 weeks ago Version.php 1 year ago WpDefaultDirectories.php 2 years ago
DatabaseOptions.php
187 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 return $this->maybeUnserialize($result);
63 }
64
65 /**
66 * @param string $optionName
67 * @param mixed $optionValue
68 * @param bool $autoload
69 * @return bool
70 */
71 public function updateOption(string $optionName, $optionValue, bool $autoload = true): bool
72 {
73 try {
74 $serializedValue = serialize($optionValue);
75 $autoloadValue = $autoload ? 'yes' : 'no';
76 if ($this->optionExists($optionName)) {
77 $sql = $this->db->prepare(
78 "UPDATE `{$this->optionsTable}`
79 SET option_value = %s, autoload = %s
80 WHERE option_name = %s",
81 $serializedValue,
82 $autoloadValue,
83 $optionName
84 );
85 } else {
86 $sql = $this->db->prepare(
87 "INSERT INTO `{$this->optionsTable}` (option_name, option_value, autoload)
88 VALUES (%s, %s, %s)",
89 $optionName,
90 $serializedValue,
91 $autoloadValue
92 );
93 }
94
95 $result = $this->db->query($sql);
96 if ($result === false) {
97 debug_log(sprintf('Failed to update database option "%s". DB Error: %s', $optionName, $this->getLastDbError()));
98
99 return false;
100 }
101
102 $this->clearOptionCache($optionName);
103
104 return true;
105 } catch (Throwable $ex) {
106 debug_log(sprintf('Exception while updating database option "%s": %s', $optionName, $ex->getMessage()));
107
108 return false;
109 }
110 }
111
112 /**
113 * @param string $optionName
114 * @return bool
115 */
116 public function deleteOption(string $optionName): bool
117 {
118 if (!$this->optionExists($optionName)) {
119 return false;
120 }
121
122 $sql = $this->db->prepare(
123 "DELETE FROM `{$this->optionsTable}` WHERE option_name = %s LIMIT 1",
124 $optionName
125 );
126
127 $result = $this->db->query($sql);
128 if ($result === false) {
129 return false;
130 }
131
132 $this->clearOptionCache($optionName);
133
134 return true;
135 }
136
137 /**
138 * @param string $optionName
139 * @return bool
140 */
141 private function optionExists(string $optionName): bool
142 {
143 $sql = $this->db->prepare(
144 "SELECT 1 FROM `{$this->optionsTable}` WHERE option_name = %s LIMIT 1",
145 $optionName
146 );
147
148 return (bool) $this->db->get_var($sql);
149 }
150
151 /**
152 * @param string $value
153 * @return mixed
154 */
155 private function maybeUnserialize(string $value)
156 {
157 if ($this->isSerialized($value)) {
158 return @unserialize($value);
159 }
160
161 return $value;
162 }
163
164 /**
165 * @return string
166 */
167 private function getLastDbError(): string
168 {
169 return !empty($this->db->last_error) ? $this->db->last_error : 'Unknown database error';
170 }
171
172 /**
173 * @param string $optionName
174 * @return void
175 */
176 private function clearOptionCache(string $optionName)
177 {
178 if (!function_exists('wp_cache_delete')) {
179 return;
180 }
181
182 wp_cache_delete($optionName, 'options');
183 wp_cache_delete('alloptions', 'options');
184 wp_cache_delete('notoptions', 'options');
185 }
186 }
187