client = $client instanceof Akkedli_V2_Binding_Status ? $client : new Akkedli_V2_Binding_Status(); $this->clock = is_callable($clock) ? $clock : 'time'; $this->readiness = $readiness; add_action(self::HOOK, array($this, 'run')); } public static function schedule_current() { $state = Akkedli_Connector_State::load(); if (!is_array($state) || 'v2_pending' !== $state['mode'] || $state['automatic_stopped']) return false; $now = time(); if ($state['attempt_count'] >= 8 || $now - $state['poll_started_at'] >= 900) { return Akkedli_V2_Binding_Transition::stop($state); } if ($state['next_attempt_at'] <= $now) { if (!Akkedli_V2_Binding_Transition::apply($state, array('kind' => 'retry'), true, $now)) return false; $state = Akkedli_Connector_State::load(); if (!is_array($state) || 'v2_pending' !== $state['mode'] || $state['automatic_stopped']) return true; } $target = $state['next_attempt_at']; $scheduled = wp_next_scheduled(self::HOOK); if ($scheduled && $scheduled === $target) return true; if ($scheduled) wp_unschedule_event($scheduled, self::HOOK); return false !== wp_schedule_single_event($target, self::HOOK); } public function run() { return $this->execute(true); } public function check_manual() { return $this->execute(false); } private function execute($automatic) { $owner = Akkedli_Enrollment_Lock::acquire(); if (!is_string($owner)) return 'busy'; try { $state = Akkedli_Connector_State::load(); if (!is_array($state) || 'v2_pending' !== $state['mode']) return 'stale'; $now = call_user_func($this->clock); if ($automatic) { if ($state['automatic_stopped'] || $state['attempt_count'] >= 8 || $now - $state['poll_started_at'] >= 900) { Akkedli_V2_Binding_Transition::stop($state); return 'expired'; } if ($now < $state['next_attempt_at']) { self::schedule_current(); return 'early'; } $reserved = $state; $reserved['attempt_count']++; $reserved['next_attempt_at'] = 0; if (!Akkedli_Connector_State::replace($reserved, $state)) return 'stale'; $state = $reserved; } $result = $this->client->check($state); if (!Akkedli_V2_Binding_Transition::apply( $state, $result, $automatic, $now, $this->readiness )) return 'stale'; $outcome = 'status' === $result['kind'] ? $result['status'] : $result['kind']; if ('verified' === $outcome && 'v2' !== Akkedli_Connector_State::status()) $outcome = 'retry'; if ($automatic || in_array($outcome, array('pending', 'retry'), true)) self::schedule_current(); return $outcome; } finally { Akkedli_Enrollment_Lock::release($owner); } } }