diff options
author | Remi Collet <remi@remirepo.net> | 2024-09-23 07:58:36 +0200 |
---|---|---|
committer | Remi Collet <remi@php.net> | 2024-09-23 07:58:36 +0200 |
commit | 15d4185b94390810af1b5ad52160cd5dd6c03f58 (patch) | |
tree | a70b8f6475bf7d94fa9e03117dd8b42422f9161a /SessionHelpers.php | |
parent | 5b1e772c6b5e68509728752a7b963a89dc03baf5 (diff) |
test build for upcoming 6.1.0RC2
Diffstat (limited to 'SessionHelpers.php')
-rw-r--r-- | SessionHelpers.php | 353 |
1 files changed, 0 insertions, 353 deletions
diff --git a/SessionHelpers.php b/SessionHelpers.php deleted file mode 100644 index 90ae73b..0000000 --- a/SessionHelpers.php +++ /dev/null @@ -1,353 +0,0 @@ -<?php - -namespace SessionHelpers; - -class PhpSpawner { - protected static function appendPhpArgs(string $php): string { - $modules = shell_exec("$php --no-php-ini -m"); - - /* Determine if we need to specifically add extensions */ - $extensions = array_filter( - ['igbinary', 'msgpack', 'json', 'redis'], - function ($module) use ($modules) { - return strpos($modules, $module) === false; - } - ); - - /* If any are needed add them to the command */ - if ($extensions) { - $php .= ' --no-php-ini'; - foreach ($extensions as $extension) { - /* We want to use the locally built redis extension */ - if ($extension == 'redis') { - $path = dirname(__DIR__) . '/modules/redis'; - if (is_file("{$path}.so")) - $extension = $path; - } - - $php .= " -dextension=$extension.so"; - } - } - - return $php; - } - - /** - * Return command to launch PHP with built extension enabled - * taking care of environment (TEST_PHP_EXECUTABLE and TEST_PHP_ARGS) - * - * @param string $script - * - * @return string - */ - public static function cmd(string $script): string { - static $cmd = NULL; - - if ( ! $cmd) { - $cmd = getenv('TEST_PHP_EXECUTABLE') ?: PHP_BINARY; - - if ($test_args = getenv('TEST_PHP_ARGS')) { - $cmd .= ' ' . $test_args; - } else { - $cmd = self::appendPhpArgs($cmd); - } - } - - return $cmd . ' ' . __DIR__ . '/' . $script . ' '; - } -} - -class Runner { - const start_script = 'startSession.php'; - const regenerate_id_script = 'regenerateSessionId.php'; - const get_data_script = 'getSessionData.php'; - - private $required = ['host', 'handler', 'id']; - - private $args = [ - 'handler' => null, - 'save-path' => null, - 'id' => null, - 'sleep' => 0, - 'max-execution-time' => 300, - 'locking-enabled' => true, - 'lock-wait-time' => null, - 'lock-retries' => -1, - 'lock-expires' => 0, - 'data' => '', - 'lifetime' => 1440, - 'compression' => 'none', - ]; - - private $prefix = NULL; - private $output_file; - private $exit_code = -1; - private $cmd = NULL; - private $pid; - private $output; - - public function __construct() { - $this->args['id'] = $this->createId(); - } - - public function getExitCode(): int { - return $this->exit_code; - } - - public function getCmd(): ?string { - return $this->cmd; - } - - public function getId(): ?string { - return $this->args['id']; - } - - public function prefix(string $prefix): self { - $this->prefix = $prefix; - return $this; - } - - public function getSessionKey(): string { - return $this->prefix . $this->getId(); - } - - public function getSessionLockKey(): string { - return $this->getSessionKey() . '_LOCK'; - } - - protected function set($setting, $v): self { - $this->args[$setting] = $v; - return $this; - } - - public function handler(string $handler): self { - return $this->set('handler', $handler); - } - - public function savePath(string $path): self { - return $this->set('save-path', $path); - } - - public function id(string $id): self { - return $this->set('id', $id); - } - - public function sleep(int $sleep): self { - return $this->set('sleep', $sleep); - } - - public function maxExecutionTime(int $time): self { - return $this->set('max-execution-time', $time); - } - - public function lockingEnabled(bool $enabled): self { - return $this->set('locking-enabled', $enabled); - } - - public function lockWaitTime(int $time): self { - return $this->set('lock-wait-time', $time); - } - - public function lockRetries(int $retries): self { - return $this->set('lock-retries', $retries); - } - - public function lockExpires(int $expires): self { - return $this->set('lock-expires', $expires); - } - - public function data(string $data): self { - return $this->set('data', $data); - } - - public function lifetime(int $lifetime): self { - return $this->set('lifetime', $lifetime); - } - - public function compression(string $compression): self { - return $this->set('compression', $compression); - } - - protected function validateArgs(array $required) { - foreach ($required as $req) { - if ( ! isset($this->args[$req]) || $this->args[$req] === null) - throw new \Exception("Command requires '$req' arg"); - } - } - - private function createId(): string { - if (function_exists('session_create_id')) - return session_create_id(); - - return uniqid(); - } - - private function getTmpFileName() { - return '/tmp/sessiontmp.txt'; - return tempnam(sys_get_temp_dir(), 'session'); - } - - /* - * @param $client Redis client - * @param string $max_wait_sec - * - * Sometimes we want to block until a session lock has been detected - * This is better and faster than arbitrarily sleeping. If we don't - * detect the session key within the specified maximum number of - * seconds, the function returns failure. - * - * @return bool - */ - public function waitForLockKey($redis, $max_wait_sec) { - $now = microtime(true); - - do { - if ($redis->exists($this->getSessionLockKey())) - return true; - usleep(10000); - } while (microtime(true) <= $now + $max_wait_sec); - - return false; - } - - private function appendCmdArgs(array $args): string { - $append = []; - - foreach ($args as $arg => $val) { - if ( ! $val) - continue; - - if (is_string($val)) - $val = escapeshellarg($val); - - $append[] = "--$arg"; - $append[] = $val; - } - - return implode(' ', $append); - } - - private function buildPhpCmd(string $script, array $args): string { - return PhpSpawner::cmd($script) . ' ' . $this->appendCmdArgs($args); - } - - private function startSessionCmd(): string { - return $this->buildPhpCmd(self::start_script, $this->args); - } - - public function output(?int $timeout = NULL): ?string { - if ($this->output) { - var_dump("early return"); - return $this->output; - } - - if ( ! $this->output_file || ! $this->pid) { - throw new \Exception("Process was not started in the background"); - } - - $st = microtime(true); - - do { - if (pcntl_waitpid($this->pid, $exit_code, WNOHANG) == 0) - break; - usleep(100000); - } while ((microtime(true) - $st) < $timeout); - - if ( ! file_exists($this->output_file)) - return ""; - - $this->output = file_get_contents($this->output_file); - $this->output_file = NULL; - $this->exit_code = $exit_code; - $this->pid = NULL; - - return $this->output; - } - - public function execBg(): bool { - if ($this->cmd) - throw new \Exception("Command already executed!"); - - $output_file = $this->getTmpFileName(); - - $this->cmd = $this->startSessionCmd(); - $this->cmd .= " >$output_file 2>&1 & echo $!"; - - $pid = exec($this->cmd, $output, $exit_code); - $this->exit_code = $exit_code; - - if ($this->exit_code || !is_numeric($pid)) - return false; - - $this->pid = (int)$pid; - $this->output_file = $output_file; - - return true; - } - - public function execFg() { - if ($this->cmd) - throw new \Exception("Command already executed!"); - - $this->cmd = $this->startSessionCmd() . ' 2>&1'; - - exec($this->cmd, $output, $exit_code); - $this->exit_code = $exit_code; - $this->output = implode("\n", array_filter($output)); - - return $this->output; - } - - private function regenerateIdCmd($locking, $destroy, $proxy): string { - $this->validateArgs(['handler', 'id', 'save-path']); - - $args = [ - 'handler' => $this->args['handler'], - 'save-path' => $this->args['save-path'], - 'id' => $this->args['id'], - 'locking-enabled' => !!$locking, - 'destroy' => !!$destroy, - 'proxy' => !!$proxy, - ]; - - return $this->buildPhpCmd(self::regenerate_id_script, $args); - } - - public function regenerateId($locking = false, $destroy = false, $proxy = false) { - if ( ! $this->cmd) - throw new \Exception("Cannot regenerate id before starting session!"); - - $cmd = $this->regenerateIdCmd($locking, $destroy, $proxy); - - exec($cmd, $output, $exit_code); - - if ($exit_code != 0) - return false; - - return $output[0]; - } - - private function getDataCmd(?int $lifetime): string { - $this->validateArgs(['handler', 'save-path', 'id']); - - $args = [ - 'handler' => $this->args['handler'], - 'save-path' => $this->args['save-path'], - 'id' => $this->args['id'], - 'lifetime' => is_int($lifetime) ? $lifetime : $this->args['lifetime'], - ]; - - return $this->buildPhpCmd(self::get_data_script, $args); - } - - public function getData(?int $lifetime = NULL): string { - $cmd = $this->getDataCmd($lifetime); - - exec($cmd, $output, $exit_code); - if ($exit_code != 0) { - return implode("\n", $output); - } - - return $output[0]; - } -} |