| Server IP : 167.235.67.158 / Your IP : 216.73.216.95 Web Server : Apache System : Linux ubuntu-8gb-nbg1-1 6.8.0-111-generic #111-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 11 23:16:02 UTC 2026 x86_64 User : upstairsbar.co.uk ( 982) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/pawsandpatience.co.uk/wp-content/plugins/wp-smushit/core/threads/ |
Upload File : |
<?php
namespace Smush\Core\Threads;
/**
* Base class for thread-safe JSON option storage.
*
* Subclasses target a specific JSON data structure (object, scalar array, object array).
* The option identity and storage scope are fixed at construction time.
*/
abstract class JSON_Data {
/** @var string WP option name. */
protected $option_id;
/** @var bool When true, data lives in wp_sitemeta (multisite); otherwise wp_options. */
protected $site_option;
/**
* @var bool When true, the underlying JSON structure is created automatically before
* every write operation. When false, the caller must invoke init() explicitly
* before any writes; if the row does not exist the operation returns 0/false,
* allowing callers to detect a concurrent delete and abort.
*/
protected $auto_initialize;
/**
* @param string $option_id WP option name.
* @param bool $auto_initialize Auto-create the JSON structure before writes. Default true.
*/
public function __construct( $option_id, $auto_initialize = true ) {
$this->option_id = $option_id;
$this->auto_initialize = $auto_initialize;
}
/**
* Explicitly initialize the underlying JSON structure.
*
* Must be called before any write operation when auto_initialize is false.
* Safe to call multiple times — uses INSERT … ON DUPLICATE KEY UPDATE.
*
* @return int|false
*/
abstract public function init();
/**
* Call init() only when auto_initialize is enabled.
* Used internally by write operations.
*/
protected function maybe_init() {
if ( $this->auto_initialize ) {
$this->init();
}
}
/**
* Delete the option row entirely.
*
* @return int|false Affected rows or false on error.
*/
public function delete() {
global $wpdb;
list( $table, $column ) = $this->get_table_columns();
return $wpdb->delete( $table, array( $column => $this->option_id ), '%s' );
}
/**
* Read the stored value.
*
* @param mixed $default Returned when the option is missing or non-JSON.
*
* @return mixed
*/
public function get( $default = false ) {
return $this->get_value_from_db( $default );
}
/**
* Overwrite the entire stored value with a JSON blob.
*
* NOT concurrent-write safe. Two concurrent callers will race and one write
* will be lost. Use field-level methods (set_values, increment_values, etc.)
* for concurrent-write-safe updates.
*
* @param mixed $value Must be JSON-serialisable.
*
* @return int|false Affected rows or false on error.
*/
public function unsafe_set( $value ) {
return $this->set_value_in_db( $value );
}
// -------------------------------------------------------------------------
// Internal helpers
// -------------------------------------------------------------------------
protected function get_value_from_db( $default ) {
global $wpdb;
list( $table, $column, $value_column, $key_column ) = $this->get_table_columns();
$row = $wpdb->get_row( $wpdb->prepare( "
SELECT *
FROM {$table}
WHERE {$column} = %s
ORDER BY {$key_column} ASC
LIMIT 1
", $this->option_id ) );
if ( empty( $row->$value_column ) || ! is_object( $row ) ) {
return $default;
}
$decoded = json_decode( $row->$value_column, true );
if ( is_null( $decoded ) ) {
return $default;
}
return $decoded;
}
protected function set_value_in_db( $value ) {
global $wpdb;
list( $table, $column, $value_column ) = $this->get_table_columns();
$json = wp_json_encode( $value );
$prepared_id = $wpdb->prepare( '%s', $this->option_id );
$prepared_value = $wpdb->prepare( '%s', $json );
return $wpdb->query(
"INSERT INTO {$table} (`{$column}`, `{$value_column}`)
VALUES ({$prepared_id}, {$prepared_value})
ON DUPLICATE KEY UPDATE `{$value_column}` = {$prepared_value}"
);
}
/**
* Returns [ $table, $column, $value_column, $key_column ].
*
* @return array
*/
protected function get_table_columns() {
global $wpdb;
$table = $wpdb->options;
$column = 'option_name';
$value_column = 'option_value';
$key_column = 'option_id';
return array( $table, $column, $value_column, $key_column );
}
protected function initialize_json_array_option() {
global $wpdb;
list( $table, $column, $value_column ) = $this->get_table_columns();
return $wpdb->query( $wpdb->prepare(
"INSERT INTO {$table} (`{$column}`, `{$value_column}`)
VALUES (%s, '[]')
ON DUPLICATE KEY UPDATE
`{$value_column}` = IF(JSON_VALID(`{$value_column}`), `{$value_column}`, '[]')",
$this->option_id
) );
}
protected function initialize_json_object_option() {
global $wpdb;
list( $table, $column, $value_column ) = $this->get_table_columns();
return $wpdb->query( $wpdb->prepare(
"INSERT INTO {$table} (`{$column}`, `{$value_column}`)
VALUES (%s, '{}')
ON DUPLICATE KEY UPDATE
`{$value_column}` = IF(JSON_VALID(`{$value_column}`), `{$value_column}`, '{}')",
$this->option_id
) );
}
}