database = $database; } public function pass(int $now, int $interval): ?int { $table = self::table(); // Затронутые строки: 1 — строки не было и она вставлена, 2 — метка обновлена, // 0 — окно ещё открыто и строка не изменилась. Время в будущем (часы сервера перевели // назад) — не ждать, пока догонят. $claimed = $this->database->execute( 'INSERT INTO `' . $table . '` (`id`, `logged_at`, `skipped`) VALUES (' . self::ROW_ID . ', ?, 0)' . ' ON DUPLICATE KEY UPDATE `logged_at` = IF(`logged_at` <= ? OR `logged_at` > ?, ?, `logged_at`)', [$now, $now - $interval, $now, $now], ); if ($claimed === 0) { $this->database->execute('UPDATE `' . $table . '` SET `skipped` = `skipped` + 1'); return null; } $skipped = (int) $this->database->fetchValue('SELECT `skipped` FROM `' . $table . '` LIMIT 1'); if ($skipped > 0) { $this->database->execute( 'UPDATE `' . $table . '` SET `skipped` = GREATEST(`skipped` - ?, 0)', [$skipped], ); } return $skipped; } public static function table(): string { $table = $GLOBALS['SysValue']['base'][ModuleInfo::PATH]['moneta_log_throttle'] ?? null; // Явный класс, а не \w: в cp1251-локали PHPShop \w пропустил бы кириллицу (как в OperationRepository). if (!is_string($table) || preg_match('/\A[0-9A-Za-z_]+\z/', $table) !== 1) { throw new RuntimeException('Нет таблицы счётчика журнала в конфигурации модуля.'); } return $table; } }