|
8 | 8 | */
|
9 | 9 | class Resque_Redis
|
10 | 10 | {
|
11 |
| - /** |
12 |
| - * Redis namespace |
13 |
| - * @var string |
14 |
| - */ |
15 |
| - private static $defaultNamespace = 'resque:'; |
| 11 | + /** |
| 12 | + * Redis namespace |
| 13 | + * @var string |
| 14 | + */ |
| 15 | + private static $defaultNamespace = 'resque:'; |
| 16 | + |
| 17 | + /** |
| 18 | + * A default host to connect to |
| 19 | + */ |
| 20 | + const DEFAULT_HOST = 'localhost'; |
| 21 | + |
| 22 | + /** |
| 23 | + * The default Redis port |
| 24 | + */ |
| 25 | + const DEFAULT_PORT = 6379; |
| 26 | + |
| 27 | + /** |
| 28 | + * The default Redis Database number |
| 29 | + */ |
| 30 | + const DEFAULT_DATABASE = 0; |
16 | 31 |
|
17 |
| - private $server; |
18 |
| - private $database; |
| 32 | + private $server; |
| 33 | + private $database; |
19 | 34 |
|
20 | 35 | /**
|
21 | 36 | * @var array List of all commands in Redis that supply a key as their
|
@@ -92,47 +107,89 @@ public static function prefix($namespace)
|
92 | 107 | self::$defaultNamespace = $namespace;
|
93 | 108 | }
|
94 | 109 |
|
95 |
| - public function __construct($server, $database = null) |
| 110 | + /** |
| 111 | + * @param string|array $server A DSN or array |
| 112 | + * @param int $database A database number to select |
| 113 | + */ |
| 114 | + public function __construct($server, $database = null) |
96 | 115 | {
|
97 | 116 | $this->server = $server;
|
98 | 117 | $this->database = $database;
|
99 | 118 |
|
100 | 119 | if (is_array($this->server)) {
|
101 | 120 | $this->driver = new Credis_Cluster($server);
|
102 |
| - } |
103 |
| - else { |
104 |
| - $port = null; |
105 |
| - $password = null; |
106 |
| - $host = $server; |
107 |
| - |
108 |
| - // If not a UNIX socket path or tcp:// formatted connections string |
109 |
| - // assume host:port combination. |
110 |
| - if (strpos($server, '/') === false) { |
111 |
| - $parts = explode(':', $server); |
112 |
| - if (isset($parts[1])) { |
113 |
| - $port = $parts[1]; |
114 |
| - } |
115 |
| - $host = $parts[0]; |
116 |
| - }else if (strpos($server, 'redis://') !== false){ |
117 |
| - // Redis format is: |
118 |
| - // redis://[user]:[password]@[host]:[port] |
119 |
| - list($userpwd,$hostport) = explode('@', $server); |
120 |
| - $userpwd = substr($userpwd, strpos($userpwd, 'redis://')+8); |
121 |
| - list($host, $port) = explode(':', $hostport); |
122 |
| - list($user, $password) = explode(':', $userpwd); |
123 |
| - } |
124 |
| - |
125 |
| - $this->driver = new Credis_Client($host, $port); |
126 |
| - if (isset($password)){ |
| 121 | + |
| 122 | + } else { |
| 123 | + |
| 124 | + list($host, $port, $dsnDatabase, $user, $password, $options) = $this->parseDsn($server); |
| 125 | + // $user is are unused here |
| 126 | + |
| 127 | + // Look for known Credis_Client options |
| 128 | + $timeout = isset($options['timeout']) ? intval($options['timeout']) : null; |
| 129 | + $persistent = isset($options['persistent']) ? $options['persistent'] : ''; |
| 130 | + |
| 131 | + $this->driver = new Credis_Client($host, $port, $timeout, $persistent); |
| 132 | + if ($password){ |
127 | 133 | $this->driver->auth($password);
|
128 | 134 | }
|
| 135 | + |
| 136 | + // If the `$database` constructor argument is not set, use the value from the DSN. |
| 137 | + if (is_null($database)) { |
| 138 | + $database = $dsnDatabase; |
| 139 | + } |
129 | 140 | }
|
130 | 141 |
|
131 | 142 | if ($this->database !== null) {
|
132 | 143 | $this->driver->select($database);
|
133 | 144 | }
|
134 | 145 | }
|
135 | 146 |
|
| 147 | + /** |
| 148 | + * Parse a DSN string |
| 149 | + * @param string $dsn |
| 150 | + * @return array [host, port, db, user, pass, options] |
| 151 | + */ |
| 152 | + public function parseDsn($dsn) |
| 153 | + { |
| 154 | + $validSchemes = array('redis', 'tcp'); |
| 155 | + if ($dsn == '') { |
| 156 | + // Use a sensible default for an empty DNS string |
| 157 | + $dsn = 'redis://' . self::DEFAULT_HOST; |
| 158 | + } |
| 159 | + $parts = parse_url($dsn); |
| 160 | + if (isset($parts['scheme']) && ! in_array($parts['scheme'], $validSchemes)) { |
| 161 | + throw new \InvalidArgumentException("Invalid DSN. Supported schemes are " . implode(', ', $validSchemes)); |
| 162 | + } |
| 163 | + |
| 164 | + // Allow simple 'hostname' format, which parse_url treats as a path, not host. |
| 165 | + if ( ! isset($parts['host'])) { |
| 166 | + $parts = array('host' => $parts['path']); |
| 167 | + } |
| 168 | + |
| 169 | + $port = isset($parts['port']) ? intval($parts['port']) : self::DEFAULT_PORT; |
| 170 | + |
| 171 | + $database = self::DEFAULT_DATABASE; |
| 172 | + if (isset($parts['path'])) { |
| 173 | + // Strip non-digit chars from path |
| 174 | + $database = intval(preg_replace('/[^0-9]/', '', $parts['path'])); |
| 175 | + } |
| 176 | + |
| 177 | + $options = array(); |
| 178 | + if (isset($parts['query'])) { |
| 179 | + // Parse the query string into an array |
| 180 | + parse_str($parts['query'], $options); |
| 181 | + } |
| 182 | + |
| 183 | + return array( |
| 184 | + $parts['host'], |
| 185 | + $port, |
| 186 | + $database, |
| 187 | + isset($parts['user']) ? $parts['user'] : false, |
| 188 | + isset($parts['pass']) ? $parts['pass'] : false, |
| 189 | + $options, |
| 190 | + ); |
| 191 | + } |
| 192 | + |
136 | 193 | /**
|
137 | 194 | * Magic method to handle all function requests and prefix key based
|
138 | 195 | * operations with the {self::$defaultNamespace} key prefix.
|
|
0 commit comments