class-wp-paused-extensions-storage.php (4923B)
1 <?php 2 /** 3 * Error Protection API: WP_Paused_Extensions_Storage class 4 * 5 * @package WordPress 6 * @since 5.2.0 7 */ 8 9 /** 10 * Core class used for storing paused extensions. 11 * 12 * @since 5.2.0 13 */ 14 class WP_Paused_Extensions_Storage { 15 16 /** 17 * Type of extension. Used to key extension storage. 18 * 19 * @since 5.2.0 20 * @var string 21 */ 22 protected $type; 23 24 /** 25 * Constructor. 26 * 27 * @since 5.2.0 28 * 29 * @param string $extension_type Extension type. Either 'plugin' or 'theme'. 30 */ 31 public function __construct( $extension_type ) { 32 $this->type = $extension_type; 33 } 34 35 /** 36 * Records an extension error. 37 * 38 * Only one error is stored per extension, with subsequent errors for the same extension overriding the 39 * previously stored error. 40 * 41 * @since 5.2.0 42 * 43 * @param string $extension Plugin or theme directory name. 44 * @param array $error { 45 * Error that was triggered. 46 * 47 * @type string $type The error type. 48 * @type string $file The name of the file in which the error occurred. 49 * @type string $line The line number in which the error occurred. 50 * @type string $message The error message. 51 * } 52 * @return bool True on success, false on failure. 53 */ 54 public function set( $extension, $error ) { 55 if ( ! $this->is_api_loaded() ) { 56 return false; 57 } 58 59 $option_name = $this->get_option_name(); 60 61 if ( ! $option_name ) { 62 return false; 63 } 64 65 $paused_extensions = (array) get_option( $option_name, array() ); 66 67 // Do not update if the error is already stored. 68 if ( isset( $paused_extensions[ $this->type ][ $extension ] ) && $paused_extensions[ $this->type ][ $extension ] === $error ) { 69 return true; 70 } 71 72 $paused_extensions[ $this->type ][ $extension ] = $error; 73 74 return update_option( $option_name, $paused_extensions ); 75 } 76 77 /** 78 * Forgets a previously recorded extension error. 79 * 80 * @since 5.2.0 81 * 82 * @param string $extension Plugin or theme directory name. 83 * @return bool True on success, false on failure. 84 */ 85 public function delete( $extension ) { 86 if ( ! $this->is_api_loaded() ) { 87 return false; 88 } 89 90 $option_name = $this->get_option_name(); 91 92 if ( ! $option_name ) { 93 return false; 94 } 95 96 $paused_extensions = (array) get_option( $option_name, array() ); 97 98 // Do not delete if no error is stored. 99 if ( ! isset( $paused_extensions[ $this->type ][ $extension ] ) ) { 100 return true; 101 } 102 103 unset( $paused_extensions[ $this->type ][ $extension ] ); 104 105 if ( empty( $paused_extensions[ $this->type ] ) ) { 106 unset( $paused_extensions[ $this->type ] ); 107 } 108 109 // Clean up the entire option if we're removing the only error. 110 if ( ! $paused_extensions ) { 111 return delete_option( $option_name ); 112 } 113 114 return update_option( $option_name, $paused_extensions ); 115 } 116 117 /** 118 * Gets the error for an extension, if paused. 119 * 120 * @since 5.2.0 121 * 122 * @param string $extension Plugin or theme directory name. 123 * @return array|null Error that is stored, or null if the extension is not paused. 124 */ 125 public function get( $extension ) { 126 if ( ! $this->is_api_loaded() ) { 127 return null; 128 } 129 130 $paused_extensions = $this->get_all(); 131 132 if ( ! isset( $paused_extensions[ $extension ] ) ) { 133 return null; 134 } 135 136 return $paused_extensions[ $extension ]; 137 } 138 139 /** 140 * Gets the paused extensions with their errors. 141 * 142 * @since 5.2.0 143 * 144 * @return array Associative array of extension slugs to the error recorded. 145 */ 146 public function get_all() { 147 if ( ! $this->is_api_loaded() ) { 148 return array(); 149 } 150 151 $option_name = $this->get_option_name(); 152 153 if ( ! $option_name ) { 154 return array(); 155 } 156 157 $paused_extensions = (array) get_option( $option_name, array() ); 158 159 return isset( $paused_extensions[ $this->type ] ) ? $paused_extensions[ $this->type ] : array(); 160 } 161 162 /** 163 * Remove all paused extensions. 164 * 165 * @since 5.2.0 166 * 167 * @return bool 168 */ 169 public function delete_all() { 170 if ( ! $this->is_api_loaded() ) { 171 return false; 172 } 173 174 $option_name = $this->get_option_name(); 175 176 if ( ! $option_name ) { 177 return false; 178 } 179 180 $paused_extensions = (array) get_option( $option_name, array() ); 181 182 unset( $paused_extensions[ $this->type ] ); 183 184 if ( ! $paused_extensions ) { 185 return delete_option( $option_name ); 186 } 187 188 return update_option( $option_name, $paused_extensions ); 189 } 190 191 /** 192 * Checks whether the underlying API to store paused extensions is loaded. 193 * 194 * @since 5.2.0 195 * 196 * @return bool True if the API is loaded, false otherwise. 197 */ 198 protected function is_api_loaded() { 199 return function_exists( 'get_option' ); 200 } 201 202 /** 203 * Get the option name for storing paused extensions. 204 * 205 * @since 5.2.0 206 * 207 * @return string 208 */ 209 protected function get_option_name() { 210 if ( ! wp_recovery_mode()->is_active() ) { 211 return ''; 212 } 213 214 $session_id = wp_recovery_mode()->get_session_id(); 215 if ( empty( $session_id ) ) { 216 return ''; 217 } 218 219 return "{$session_id}_paused_extensions"; 220 } 221 }