ConnectionParameters.php 5.4 KB

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