ConnectionParameters.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. /*
  3. * This file is part of the Predis package.
  4. *
  5. * (c) Daniele Alessandri <suppakilla@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Predis;
  11. use Predis\IConnectionParameters;
  12. use Predis\Options\IOption;
  13. class ConnectionParameters implements IConnectionParameters
  14. {
  15. private static $_defaultParameters;
  16. private static $_validators;
  17. private $_parameters;
  18. private $_userDefined;
  19. public function __construct($parameters = array())
  20. {
  21. self::ensureDefaults();
  22. if (!is_array($parameters)) {
  23. $parameters = $this->parseURI($parameters);
  24. }
  25. $this->_userDefined = array_keys($parameters);
  26. $this->_parameters = $this->filter($parameters) + self::$_defaultParameters;
  27. }
  28. private static function ensureDefaults()
  29. {
  30. if (!isset(self::$_defaultParameters)) {
  31. self::$_defaultParameters = array(
  32. 'scheme' => 'tcp',
  33. 'host' => '127.0.0.1',
  34. 'port' => 6379,
  35. 'database' => null,
  36. 'password' => null,
  37. 'connection_async' => false,
  38. 'connection_persistent' => false,
  39. 'connection_timeout' => 5.0,
  40. 'read_write_timeout' => null,
  41. 'alias' => null,
  42. 'weight' => null,
  43. 'path' => null,
  44. 'iterable_multibulk' => false,
  45. 'throw_errors' => true,
  46. );
  47. }
  48. if (!isset(self::$_validators)) {
  49. $bool = function($value) { return (bool) $value; };
  50. $float = function($value) { return (float) $value; };
  51. $int = function($value) { return (int) $value; };
  52. self::$_validators = array(
  53. 'port' => $int,
  54. 'connection_async' => $bool,
  55. 'connection_persistent' => $bool,
  56. 'connection_timeout' => $float,
  57. 'read_write_timeout' => $float,
  58. 'iterable_multibulk' => $bool,
  59. 'throw_errors' => $bool,
  60. );
  61. }
  62. }
  63. public static function define($parameter, $default, $callable = null)
  64. {
  65. self::ensureDefaults();
  66. self::$_defaultParameters[$parameter] = $default;
  67. if ($default instanceof IOption) {
  68. self::$_validators[$parameter] = $default;
  69. return;
  70. }
  71. if (!isset($callable)) {
  72. unset(self::$_validators[$parameter]);
  73. return;
  74. }
  75. if (!is_callable($callable)) {
  76. throw new \InvalidArgumentException(
  77. "The validator for $parameter must be a callable object"
  78. );
  79. }
  80. self::$_validators[$parameter] = $callable;
  81. }
  82. public static function undefine($parameter)
  83. {
  84. self::ensureDefaults();
  85. unset(self::$_defaultParameters[$parameter], self::$_validators[$parameter]);
  86. }
  87. private function parseURI($uri)
  88. {
  89. if (stripos($uri, 'unix') === 0) {
  90. // Hack to support URIs for UNIX sockets with minimal effort.
  91. $uri = str_ireplace('unix:///', 'unix://localhost/', $uri);
  92. }
  93. if (($parsed = @parse_url($uri)) === false || !isset($parsed['host'])) {
  94. throw new ClientException("Invalid URI: $uri");
  95. }
  96. if (isset($parsed['query'])) {
  97. foreach (explode('&', $parsed['query']) as $kv) {
  98. @list($k, $v) = explode('=', $kv);
  99. $parsed[$k] = $v;
  100. }
  101. unset($parsed['query']);
  102. }
  103. return $parsed;
  104. }
  105. private function filter(Array $parameters)
  106. {
  107. if (count($parameters) > 0) {
  108. $validators = array_intersect_key(self::$_validators, $parameters);
  109. foreach ($validators as $parameter => $validator) {
  110. $parameters[$parameter] = $validator($parameters[$parameter]);
  111. }
  112. }
  113. return $parameters;
  114. }
  115. public function __get($parameter)
  116. {
  117. $value = $this->_parameters[$parameter];
  118. if ($value instanceof IOption) {
  119. $this->_parameters[$parameter] = ($value = $value->getDefault());
  120. }
  121. return $value;
  122. }
  123. public function __isset($parameter)
  124. {
  125. return isset($this->_parameters[$parameter]);
  126. }
  127. public function isSetByUser($parameter)
  128. {
  129. return in_array($parameter, $this->_userDefined);
  130. }
  131. protected function getBaseURI()
  132. {
  133. if ($this->scheme === 'unix') {
  134. return "{$this->scheme}://{$this->path}";
  135. }
  136. return "{$this->scheme}://{$this->host}:{$this->port}";
  137. }
  138. protected function getDisallowedURIParts()
  139. {
  140. return array('scheme', 'host', 'port', 'password', 'path');
  141. }
  142. public function toArray()
  143. {
  144. return $this->_parameters;
  145. }
  146. public function __toString()
  147. {
  148. $query = array();
  149. $parameters = $this->toArray();
  150. $reject = $this->getDisallowedURIParts();
  151. foreach ($this->_userDefined as $param) {
  152. if (in_array($param, $reject) || !isset($parameters[$param])) {
  153. continue;
  154. }
  155. $value = $parameters[$param];
  156. $query[] = "$param=" . ($value === false ? '0' : $value);
  157. }
  158. if (count($query) === 0) {
  159. return $this->getBaseURI();
  160. }
  161. return $this->getBaseURI() . '/?' . implode('&', $query);
  162. }
  163. public function __sleep()
  164. {
  165. return array('_parameters', '_userDefined');
  166. }
  167. public function __wakeup()
  168. {
  169. self::ensureDefaults();
  170. }
  171. }