Current File : /www/capitalgmcbuickregina_830/public/wp-content/plugins/wp-cerber/includes/CRB_Settings_Backup.php
<?php
/**
* Automatic backup and recovery of the plugin settings stored in the CERBER_CONFIG option.
*
* Maintains a single backup slot in the plugin key-value storage holding the last known
* valid copy of the plugin settings. The backup is refreshed after successful settings
* updates, settings imports, plugin upgrades, and once a day by the scheduled maintenance
* task. It is used to automatically restore the settings when the corruption detector in
* crb_get_settings() encounters a stored value that cannot be unserialized.
*
* The backup payload is persisted as a JSON-encoded string of the following shape:
* array{settings: array<string, mixed>, user_id: int, timestamp: int, context: string}
*
* None of the methods call crb_get_settings(), so the class is safe to use inside
* the settings loading path.
*/
final class CRB_Settings_Backup {
/**
* The key the backup payload is stored under in the plugin key-value storage.
* Private implementation detail: external code should not access the backup directly.
*/
private const BACKUP_KEY = 'cerber_settings_backup';
/**
* Backup context: a successful administrative settings update.
*/
public const CONTEXT_SETTINGS_UPDATE = 'settings_update';
/**
* Backup context: a successful settings import.
*/
public const CONTEXT_SETTINGS_IMPORT = 'settings_import';
/**
* Backup context: a plugin upgrade.
*/
public const CONTEXT_PLUGIN_UPGRADE = 'plugin_upgrade';
/**
* Backup context: a daily run of the scheduled maintenance task.
*/
public const CONTEXT_SCHEDULED_SYNC = 'scheduled_sync';
/**
* @var bool True after a restoration attempt has been made within the current request.
*/
private static $recovery_attempted = false;
/**
* Saves the currently stored plugin settings as the backup copy in the key-value storage.
*
* Reads the raw CERBER_CONFIG option and stores it together with the initiating user ID,
* the current timestamp, and the given context. Refuses to update the backup if the
* currently stored settings are missing, corrupted, or empty, so the last known valid
* backup is never overwritten with invalid settings.
*
* @param string $backup_context Non-empty code describing the operation that triggered the backup.
*
* @return bool True if the backup copy was updated. False if the context is empty, the stored settings are invalid, or the write failed.
*/
public static function sync( string $backup_context ): bool {
if ( trim( $backup_context ) === '' ) {
return false;
}
$current_settings = get_site_option( CERBER_CONFIG );
if ( ! is_array( $current_settings )
|| ! $current_settings ) {
return false;
}
$backup_payload = array(
'settings' => $current_settings,
'user_id' => (int) get_current_user_id(),
'timestamp' => time(),
'context' => $backup_context,
);
$encoded_backup = json_encode( $backup_payload );
if ( ! is_string( $encoded_backup ) ) {
return false;
}
return cerber_update_set( self::BACKUP_KEY, $encoded_backup, 0, false, 0, false );
}
/**
* Restores the plugin settings after data corruption was detected.
*
* Attempts to restore a validated backup first. If backup recovery is unavailable or
* fails, replaces the corrupted option with default settings as the final recovery path.
* Only one restoration attempt per request is performed to prevent recursive cycles.
* This method never creates a new backup and never calls crb_get_settings().
*
* @param int $corrupted_length Byte length of the corrupted raw settings value, used for diagnostics.
*
* @return array<string, mixed>|false The backup settings on successful backup recovery, false when the default-settings recovery path was taken, regardless of whether the default settings were successfully applied.
*/
public static function recover( int $corrupted_length ) {
if ( self::$recovery_attempted ) {
return false;
}
self::$recovery_attempted = true;
$encoded_backup = cerber_get_set( self::BACKUP_KEY, 0, false, false );
$failure_reason = '';
$backup_payload = array();
if ( ! $encoded_backup
|| ! is_string( $encoded_backup ) ) {
$failure_reason = 'backup_missing';
}
else {
$decoded_payload = json_decode( $encoded_backup, true );
if ( self::is_backup_payload_valid( $decoded_payload ) ) {
$backup_payload = $decoded_payload;
}
else {
$failure_reason = 'backup_invalid';
}
}
if ( ! $failure_reason
&& ! self::replace_settings( $backup_payload['settings'] ) ) {
$failure_reason = 'restore_write_failed';
}
if ( $failure_reason ) {
$default_settings_restored = self::replace_settings( crb_get_default_values() );
self::report_failure(
$failure_reason,
$corrupted_length,
$backup_payload,
$default_settings_restored
);
return false;
}
self::report_success( $backup_payload, $corrupted_length );
return $backup_payload['settings'];
}
/**
* Replaces the canonical plugin settings option with the given settings.
*
* Deletes the option first to invalidate stale WordPress option-cache state and ensure
* update_site_option() performs a real database write.
*
* @param array<string, mixed> $settings Complete settings payload to store.
*
* @return bool True when the replacement settings were stored successfully.
*/
private static function replace_settings( array $settings ): bool {
if ( ! $settings ) {
return false;
}
delete_site_option( CERBER_CONFIG );
return update_site_option( CERBER_CONFIG, $settings );
}
/**
* Validates the structure of the decoded backup payload.
*
* The writer always produces the full payload shape, so any deviation means
* the backup itself is damaged and must not be restored.
*
* @param mixed $decoded_payload Result of JSON decoding of the stored backup value.
*
* @return bool True if the payload contains non-empty settings, a positive timestamp, a non-empty context code, and a non-negative integer user ID.
*/
private static function is_backup_payload_valid( $decoded_payload ): bool {
if ( ! is_array( $decoded_payload ) ) {
return false;
}
$backup_settings = $decoded_payload['settings'] ?? false;
if ( ! is_array( $backup_settings )
|| ! $backup_settings ) {
return false;
}
$backup_timestamp = $decoded_payload['timestamp'] ?? 0;
if ( ! is_int( $backup_timestamp )
|| $backup_timestamp <= 0 ) {
return false;
}
$backup_context = $decoded_payload['context'] ?? '';
if ( ! is_string( $backup_context )
|| trim( $backup_context ) === '' ) {
return false;
}
$backup_user_id = $decoded_payload['user_id'] ?? false;
if ( ! is_int( $backup_user_id )
|| $backup_user_id < 0 ) {
return false;
}
return true;
}
/**
* Registers the successful restoration outcome in the issue registry.
*
* Removes the stale corruption issue and registers a dismissable warning advising
* the administrator to review the restored settings. The warning is also removed
* automatically when the administrator saves the plugin settings.
*
* @param array{settings: array<string, mixed>, user_id: int, timestamp: int, context: string} $backup_payload Validated backup payload that was restored.
* @param int $corrupted_length Byte length of the corrupted raw settings value.
*
* @return void
*/
private static function report_success( array $backup_payload, int $corrupted_length ): void {
CRB_Issues::delete_item( 'corrupted_settings', 'settings' );
$backup_timestamp = (int) $backup_payload['timestamp'];
$backup_date = cerber_date( $backup_timestamp, false );
$success_messages = array(
self::CONTEXT_SETTINGS_UPDATE =>
/* translators: %s is the localized date and time when the settings backup was created. */
__( 'The plugin settings stored in the website database were corrupted and could not be loaded. The settings have been automatically restored from a backup copy created on %s during a plugin settings update. Some recent changes may be missing. To resolve this issue, review the plugin settings and save them.', 'wp-cerber' ),
self::CONTEXT_SETTINGS_IMPORT =>
/* translators: %s is the localized date and time when the settings backup was created. */
__( 'The plugin settings stored in the website database were corrupted and could not be loaded. The settings have been automatically restored from a backup copy created on %s during a settings import. Some recent changes may be missing. To resolve this issue, review the plugin settings and save them.', 'wp-cerber' ),
self::CONTEXT_PLUGIN_UPGRADE =>
/* translators: %s is the localized date and time when the settings backup was created. */
__( 'The plugin settings stored in the website database were corrupted and could not be loaded. The settings have been automatically restored from a backup copy created on %s during a plugin upgrade. Some recent changes may be missing. To resolve this issue, review the plugin settings and save them.', 'wp-cerber' ),
self::CONTEXT_SCHEDULED_SYNC =>
/* translators: %s is the localized date and time when the settings backup was created. */
__( 'The plugin settings stored in the website database were corrupted and could not be loaded. The settings have been automatically restored from a backup copy created on %s during a scheduled daily synchronization. Some recent changes may be missing. To resolve this issue, review the plugin settings and save them.', 'wp-cerber' ),
);
/* translators: %s is the localized date and time when the settings backup was created. */
$fallback_message = __( 'The plugin settings stored in the website database were corrupted and could not be loaded. The settings have been automatically restored from a backup copy created on %s. Some recent changes may be missing. To resolve this issue, review the plugin settings and save them.', 'wp-cerber' );
$message = sprintf( $success_messages[ $backup_payload['context'] ] ?? $fallback_message, $backup_date );
CRB_Issues::add(
'settings_restored',
$message,
array(
'section' => 'settings',
'type' => CRB_Issues::TYPE_ONGOING,
'severity' => CRB_Issues::SEVERITY_WARNING,
'dismissable' => true,
'context' => array(
'stored_value_length' => $corrupted_length,
'backup_timestamp' => $backup_timestamp,
'backup_context' => (string) $backup_payload['context'],
'backup_user_id' => $backup_payload['user_id'],
),
)
);
}
/**
* Registers a failed backup restoration and the outcome of the default-settings recovery.
*
* Removes a possible stale restoration notice and registers a critical issue explaining
* why backup recovery failed, whether default settings were stored, and what the
* administrator should do next.
*
* @param string $failure_reason One of 'backup_missing', 'backup_invalid', 'restore_write_failed'.
* @param int $corrupted_length Byte length of the corrupted raw settings value.
* @param array{settings?: array<string, mixed>, user_id?: int, timestamp?: int, context?: string} $backup_payload Validated backup payload if it was decoded successfully, empty array otherwise.
* @param bool $default_settings_restored True if the corrupted option was replaced with default settings.
*
* @return void
*/
private static function report_failure( string $failure_reason, int $corrupted_length, array $backup_payload, bool $default_settings_restored ): void {
CRB_Issues::delete_item( 'settings_restored', 'settings' );
$failure_messages = array(
'backup_missing' => $default_settings_restored
? __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration was not possible because no backup copy of the settings was available. The corrupted configuration has been replaced with default settings. Review the plugin settings and save any required changes.', 'wp-cerber' )
: __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration was not possible because no backup copy of the settings was available. Default settings could not be saved to the database. Review the plugin settings and save any required changes.', 'wp-cerber' ),
'backup_invalid' => $default_settings_restored
? __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration was not possible because the available backup copy was invalid. The corrupted configuration has been replaced with default settings. Review the plugin settings and save any required changes.', 'wp-cerber' )
: __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration was not possible because the available backup copy was invalid. Default settings could not be saved to the database. Review the plugin settings and save any required changes.', 'wp-cerber' ),
'restore_write_failed' => $default_settings_restored
? __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration failed because the settings from the backup copy could not be written to the database. The corrupted configuration has been replaced with default settings. Review the plugin settings and save any required changes.', 'wp-cerber' )
: __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration failed because the settings from the backup copy could not be written to the database. Default settings could not be saved to the database. Review the plugin settings and save any required changes.', 'wp-cerber' ),
);
$fallback_message = $default_settings_restored
? __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration from a backup copy was not possible. The corrupted configuration has been replaced with default settings. Review the plugin settings and save any required changes.', 'wp-cerber' )
: __( 'The plugin settings stored in the website database were corrupted and could not be loaded. Automatic restoration from a backup copy was not possible. Default settings could not be saved to the database. Review the plugin settings and save any required changes.', 'wp-cerber' );
$message = $failure_messages[ $failure_reason ] ?? $fallback_message;
$issue_context = array(
'stored_value_length' => $corrupted_length,
'backup_status' => $failure_reason,
'default_restore_status' => $default_settings_restored ? 'restored' : 'write_failed',
);
if ( $backup_payload ) {
$issue_context['backup_timestamp'] = (int) ( $backup_payload['timestamp'] ?? 0 );
$issue_context['backup_context'] = (string) ( $backup_payload['context'] ?? '' );
}
CRB_Issues::add(
'corrupted_settings',
$message,
array(
'section' => 'settings',
'type' => CRB_Issues::TYPE_ONGOING,
'severity' => CRB_Issues::SEVERITY_CRITICAL,
'context' => $issue_context,
)
);
}
}
Thank you for choosing Capital GMC Buick | Regina, your premier certified Buick and GMC dealership proudly serving drivers in Regina and the surrounding communities. Whether you’re searching for a brand-new Buick or GMC vehicle or a meticulously inspected pre-owned model, we have a diverse selection to match your needs and lifestyle.
Beyond our impressive inventory, we offer a seamless and stress-free financing experience through our well-connected finance centre, where our team of experts is dedicated to securing the best loan or lease options for you, quickly, transparently, and hassle-free.
But our commitment to you doesn’t stop at the sale. Our state-of-the-art service centre is staffed with skilled Buick and GMC technicians who use the latest equipment and genuine OEM parts to keep your vehicle running at its best. From routine maintenance to complex repairs, we’ve got you covered.
Experience top-tier customer service, quality vehicles, and expert care, all in one place. Visit Capital GMC Buick | Regina today or call us at 306-205-8072 with any questions. We’re here to help!
Have a question or need assistance? Fill out the form and we will reach out to you as soon as possible.
Schedule a Visit
Let us know when you are coming and how we can assist you. We can ensure someone will be on hand to help you out at the desired date and time.
Find a Career
Have a look at our list of available positions and apply online today to join our team!
Opportunities to Grow
The auto industry is constantly changing and we want to continue to grow. We offer growth, leadership & mentorship programs to allow our staff to grow with us.
Competitive Salary
We have a significant earning potential with incentive-based pay in most roles. We also offer an employee referral bonus with paid bonuses.
Health & Dental
We offer a comprehensive benefits package including extended health, dental, and vision care. We also include paramedical, life insurance, paid sick leave, short & long-term disability coverages.
Vacation
We value our employees and want everyone to take their vacation time. We offer a minimum of 2 weeks vacation each year.
Training & Development
We have many opportunities for paid education and training in-house as well as training from the Manufacturer.
$10,000 Cash Giveaway – Terms & Conditions
All October long, stop by Capital GMC Buick Cadillac, to enter for your chance to win $10,000 cash. No purchase is required, but entries must be made in-store.
The contest is open to residents of Saskatchewan who are 18+. Dealership employees and their households are not eligible. Entries will be accepted from October 1 to October 31, 2025. A random draw will take place on November 1, 2025.
The prize is one $10,000 award, paid by cheque, and must be accepted as awarded. Winner will be contacted by phone or email and must respond within 7 days or another entry may be drawn. Odds of winning depend on the number of entries received.By entering, you agree that Capital Automotive Group may use your name and photo for winner announcements. The contest is governed by the laws of Saskatchewan.