TextProtocol.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <?php
  2. namespace Predis\Protocols;
  3. use Predis\ICommand;
  4. use Predis\CommunicationException;
  5. use Predis\Network\IConnectionComposable;
  6. use Predis\Iterators\MultiBulkResponseSimple;
  7. class TextProtocol implements IRedisProtocol {
  8. const NEWLINE = "\r\n";
  9. const OK = 'OK';
  10. const ERROR = 'ERR';
  11. const QUEUED = 'QUEUED';
  12. const NULL = 'nil';
  13. const PREFIX_STATUS = '+';
  14. const PREFIX_ERROR = '-';
  15. const PREFIX_INTEGER = ':';
  16. const PREFIX_BULK = '$';
  17. const PREFIX_MULTI_BULK = '*';
  18. const BUFFER_SIZE = 4096;
  19. private $_mbiterable, $_throwErrors, $_serializer;
  20. public function __construct() {
  21. $this->_mbiterable = false;
  22. $this->_throwErrors = true;
  23. $this->_serializer = new TextCommandSerializer();
  24. }
  25. public function write(IConnectionComposable $connection, ICommand $command) {
  26. $connection->writeBytes($this->_serializer->serialize($command));
  27. }
  28. public function read(IConnectionComposable $connection) {
  29. $chunk = $connection->readLine();
  30. $prefix = $chunk[0];
  31. $payload = substr($chunk, 1);
  32. switch ($prefix) {
  33. case '+': // inline
  34. switch ($payload) {
  35. case 'OK':
  36. return true;
  37. case 'QUEUED':
  38. return new ResponseQueued();
  39. default:
  40. return $payload;
  41. }
  42. case '$': // bulk
  43. $size = (int) $payload;
  44. if ($size === -1) {
  45. return null;
  46. }
  47. return substr($connection->readBytes($size + 2), 0, -2);
  48. case '*': // multi bulk
  49. $count = (int) $payload;
  50. if ($count === -1) {
  51. return null;
  52. }
  53. if ($this->_mbiterable == true) {
  54. return new MultiBulkResponseSimple($connection, $count);
  55. }
  56. $multibulk = array();
  57. for ($i = 0; $i < $count; $i++) {
  58. $multibulk[$i] = $this->read($connection);
  59. }
  60. return $multibulk;
  61. case ':': // integer
  62. return (int) $payload;
  63. case '-': // error
  64. $errorMessage = substr($payload, 4);
  65. if ($this->_throwErrors) {
  66. throw new \Predis\ServerException($errorMessage);
  67. }
  68. return new \Predis\ResponseError($errorMessage);
  69. default:
  70. throw new CommunicationException(
  71. $connection, "Unknown prefix: '$prefix'"
  72. );
  73. }
  74. }
  75. public function setOption($option, $value) {
  76. switch ($option) {
  77. case 'iterable_multibulk':
  78. $this->_mbiterable = (bool) $value;
  79. break;
  80. case 'throw_errors':
  81. $this->_throwErrors = (bool) $value;
  82. break;
  83. }
  84. }
  85. }