ConnectionParameters.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. namespace Predis;
  3. use Predis\Options\IOption;
  4. use Predis\Options\Option;
  5. use Predis\Options\CustomOption;
  6. class ConnectionParameters {
  7. private $_parameters;
  8. private $_userDefined;
  9. private static $_sharedOptions;
  10. public function __construct($parameters = array()) {
  11. $extractor = is_array($parameters) ? 'filter' : 'parseURI';
  12. $this->_parameters = $this->$extractor($parameters);
  13. $this->_userDefined = array_fill_keys(array_keys($this->_parameters), true);
  14. }
  15. private static function paramsExtractor($params, $kv) {
  16. @list($k, $v) = explode('=', $kv);
  17. $params[$k] = $v;
  18. return $params;
  19. }
  20. private static function getSharedOptions() {
  21. if (isset(self::$_sharedOptions)) {
  22. return self::$_sharedOptions;
  23. }
  24. $optEmpty = new Option();
  25. $optBoolFalse = new CustomOption(array(
  26. 'validate' => function($value) { return (bool) $value; },
  27. 'default' => function() { return false; },
  28. ));
  29. $optBoolTrue = new CustomOption(array(
  30. 'validate' => function($value) { return (bool) $value; },
  31. 'default' => function() { return true; },
  32. ));
  33. self::$_sharedOptions = array(
  34. 'scheme' => new CustomOption(array(
  35. 'default' => function() { return 'tcp'; },
  36. )),
  37. 'host' => new CustomOption(array(
  38. 'default' => function() { return '127.0.0.1'; },
  39. )),
  40. 'port' => new CustomOption(array(
  41. 'validate' => function($value) { return (int) $value; },
  42. 'default' => function() { return 6379; },
  43. )),
  44. 'path' => $optEmpty,
  45. 'database' => $optEmpty,
  46. 'password' => $optEmpty,
  47. 'connection_async' => $optBoolFalse,
  48. 'connection_persistent' => $optBoolFalse,
  49. 'connection_timeout' => new CustomOption(array(
  50. 'validate' => function($value) { return (float) $value; },
  51. 'default' => function() { return 5; },
  52. )),
  53. 'read_write_timeout' => new CustomOption(array(
  54. 'validate' => function($value) { return (float) $value; },
  55. )),
  56. 'alias' => $optEmpty,
  57. 'weight' => $optEmpty,
  58. 'iterable_multibulk' => $optBoolFalse,
  59. 'throw_errors' => $optBoolTrue,
  60. );
  61. return self::$_sharedOptions;
  62. }
  63. public static function define($parameter, IOption $handler) {
  64. self::getSharedOptions();
  65. self::$_sharedOptions[$parameter] = $handler;
  66. }
  67. public static function undefine($parameter) {
  68. self::getSharedOptions();
  69. unset(self::$_sharedOptions[$parameter]);
  70. }
  71. protected function parseURI($uri) {
  72. if (!is_string($uri)) {
  73. throw new \InvalidArgumentException('URI must be a string');
  74. }
  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. $parsed = @parse_url($uri);
  80. if ($parsed === false || !isset($parsed['host'])) {
  81. throw new \InvalidArgumentException("Invalid URI: $uri");
  82. }
  83. if (array_key_exists('query', $parsed)) {
  84. $query = explode('&', $parsed['query']);
  85. $parsed = array_reduce($query, 'self::paramsExtractor', $parsed);
  86. }
  87. unset($parsed['query']);
  88. return $this->filter($parsed);
  89. }
  90. protected function filter(Array $parameters) {
  91. $handlers = self::getSharedOptions();
  92. foreach ($parameters as $parameter => $value) {
  93. if (isset($handlers[$parameter])) {
  94. $parameters[$parameter] = $handlers[$parameter]($value);
  95. }
  96. }
  97. return $parameters;
  98. }
  99. private function tryInitializeValue($parameter) {
  100. if (isset(self::$_sharedOptions[$parameter])) {
  101. $value = self::$_sharedOptions[$parameter]->getDefault();
  102. $this->_parameters[$parameter] = $value;
  103. return $value;
  104. }
  105. }
  106. public function __get($parameter) {
  107. if (isset($this->_parameters[$parameter])) {
  108. return $this->_parameters[$parameter];
  109. }
  110. return $this->tryInitializeValue($parameter);
  111. }
  112. public function __isset($parameter) {
  113. return isset($this->_userDefined[$parameter]);
  114. }
  115. public function __toString() {
  116. $str = null;
  117. if ($this->scheme === 'unix') {
  118. $str = "{$this->scheme}://{$this->path}";
  119. }
  120. else {
  121. $str = "{$this->scheme}://{$this->host}:{$this->port}";
  122. }
  123. $query = array();
  124. $reject = array('scheme', 'host', 'port', 'password', 'path');
  125. foreach ($this->_parameters as $k => $v) {
  126. if (in_array($k, $reject) || !isset($this->_userDefined[$k])) {
  127. continue;
  128. }
  129. $query[] = $k . '=' . ($v === false ? '0' : $v);
  130. }
  131. return count($query) > 0 ? ($str . '/?' . implode('&', $query)) : $str;
  132. }
  133. public function toArray() {
  134. return $this->_parameters;
  135. }
  136. }