get_var( $wpdb->prepare( "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s", $name ) ); if ( time() - $held_since < (int) $ttl ) { return false; } // Stale: delete only the exact stale row, then race for the lock once more. // phpcs:ignore WordPress.DB.DirectDatabaseQuery $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name = %s AND option_value = %s", $name, (string) $held_since ) ); return self::insert( $name ); } /** * Releases the lock. * * @param string $name Option name of the lock. */ public static function release( $name ) { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery $wpdb->delete( $wpdb->options, array( 'option_name' => $name ) ); self::flush_cache( $name ); } /** * Atomic insert of the lock row. * * @param string $name Option name. * @return bool Whether this request created the row. */ private static function insert( $name ) { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery $inserted = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->options} (option_name, option_value, autoload) VALUES (%s, %s, 'no')", $name, (string) time() ) ); self::flush_cache( $name ); return 1 === (int) $inserted; } /** * Keeps the options cache consistent with the direct queries. * * @param string $name Option name. */ private static function flush_cache( $name ) { wp_cache_delete( $name, 'options' ); wp_cache_delete( 'notoptions', 'options' ); } }