db = $db ?: new Db(); } public function acquire(Draft $draft, int $timeout = 5, bool $preserve_existing_assignments = false): bool { $draft->lockResourceAssignments(!$preserve_existing_assignments); foreach ($this->resourceIds($draft) as $resource_id) { $key = $this->lockKey($resource_id); $locked = (int) $this->db->getVar( $this->db->prepare('SELECT GET_LOCK(%s, %d)', $key, $timeout) ); if ($locked !== 1) { $this->release(); return false; } $this->locks[] = $key; } return true; } public function release(): void { foreach (array_reverse($this->locks) as $key) { $this->db->getVar( $this->db->prepare('SELECT RELEASE_LOCK(%s)', $key) ); } $this->locks = []; } /** * @return int[] */ private function resourceIds(Draft $draft): array { $ids = array_map('absint', array_values($draft->getResources())); $ids = array_values(array_unique(array_filter($ids))); sort($ids); return $ids; } private function lockKey(int $resource_id): string { return 'daytidy_' . md5($this->db->wpdb()->prefix) . '_resource_' . $resource_id; } }