get_var($wpdb->prepare('SELECT GET_LOCK(%s, %d)', $lock, (int) $timeout))) { return false; } $stored = $wpdb->get_var($wpdb->prepare("SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", $option)); if (self::differs($seen, $stored)) { $wpdb->query($wpdb->prepare('SELECT RELEASE_LOCK(%s)', $lock)); wp_cache_delete($option, 'options'); wp_cache_delete('notoptions', 'options'); return false; } self::$held[$option] = $lock; add_action("update_option_{$option}", array(__CLASS__, 'on_update'), 10, 3); add_action("add_option_{$option}", array(__CLASS__, 'on_add'), 10, 1); if (!has_action('shutdown', array(__CLASS__, 'release_all'))) { add_action('shutdown', array(__CLASS__, 'release_all')); } return true; } public static function release($option) { global $wpdb; $option = (string) $option; if (!isset(self::$held[$option])) { return; } $lock = self::$held[$option]; unset(self::$held[$option]); remove_action("update_option_{$option}", array(__CLASS__, 'on_update'), 10); remove_action("add_option_{$option}", array(__CLASS__, 'on_add'), 10); $wpdb->query($wpdb->prepare('SELECT RELEASE_LOCK(%s)', $lock)); } public static function release_all() { foreach (array_keys(self::$held) as $option) { self::release($option); } } public static function on_update($old_value, $value, $option) { self::release($option); } public static function on_add($option) { self::release($option); } public static function held($option) { return isset(self::$held[(string) $option]); } public static function name($option) { global $wpdb; return 'aieo_schema_' . md5((defined('DB_NAME') ? DB_NAME : '') . '.' . $wpdb->options . '.' . $option); } private static function differs($seen, $stored) { if (null === $seen || null === $stored) { return (null === $seen) !== (null === $stored); } return (string) $stored !== (string) maybe_serialize($seen); } } }