CurlMultiRequest.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. <?php
  2. /**
  3. * Licensed to Jasig under one or more contributor license
  4. * agreements. See the NOTICE file distributed with this work for
  5. * additional information regarding copyright ownership.
  6. *
  7. * Jasig licenses this file to you under the Apache License,
  8. * Version 2.0 (the "License"); you may not use this file except in
  9. * compliance with the License. You may obtain a copy of the License at:
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * PHP Version 5
  20. *
  21. * @file CAS/Request/AbstractRequest.php
  22. * @category Authentication
  23. * @package PhpCAS
  24. * @author Adam Franco <afranco@middlebury.edu>
  25. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
  26. * @link https://wiki.jasig.org/display/CASC/phpCAS
  27. */
  28. /**
  29. * This interface defines a class library for performing multiple web requests
  30. * in batches. Implementations of this interface may perform requests serially
  31. * or in parallel.
  32. *
  33. * @class CAS_Request_CurlMultiRequest
  34. * @category Authentication
  35. * @package PhpCAS
  36. * @author Adam Franco <afranco@middlebury.edu>
  37. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
  38. * @link https://wiki.jasig.org/display/CASC/phpCAS
  39. */
  40. class CAS_Request_CurlMultiRequest
  41. implements CAS_Request_MultiRequestInterface
  42. {
  43. private $_requests = array();
  44. private $_sent = false;
  45. /*********************************************************
  46. * Add Requests
  47. *********************************************************/
  48. /**
  49. * Add a new Request to this batch.
  50. * Note, implementations will likely restrict requests to their own concrete
  51. * class hierarchy.
  52. *
  53. * @param CAS_Request_RequestInterface $request reqest to add
  54. *
  55. * @return void
  56. * @throws CAS_OutOfSequenceException If called after the Request has been sent.
  57. * @throws CAS_InvalidArgumentException If passed a Request of the wrong
  58. * implmentation.
  59. */
  60. public function addRequest (CAS_Request_RequestInterface $request)
  61. {
  62. if ($this->_sent) {
  63. throw new CAS_OutOfSequenceException(
  64. 'Request has already been sent cannot '.__METHOD__
  65. );
  66. }
  67. if (!$request instanceof CAS_Request_CurlRequest) {
  68. throw new CAS_InvalidArgumentException(
  69. 'As a CAS_Request_CurlMultiRequest, I can only work with CAS_Request_CurlRequest objects.'
  70. );
  71. }
  72. $this->_requests[] = $request;
  73. }
  74. /**
  75. * Retrieve the number of requests added to this batch.
  76. *
  77. * @return int number of request elements
  78. * @throws CAS_OutOfSequenceException if the request has already been sent
  79. */
  80. public function getNumRequests()
  81. {
  82. if ($this->_sent) {
  83. throw new CAS_OutOfSequenceException(
  84. 'Request has already been sent cannot '.__METHOD__
  85. );
  86. }
  87. return count($this->_requests);
  88. }
  89. /*********************************************************
  90. * 2. Send the Request
  91. *********************************************************/
  92. /**
  93. * Perform the request. After sending, all requests will have their
  94. * responses poulated.
  95. *
  96. * @return bool TRUE on success, FALSE on failure.
  97. * @throws CAS_OutOfSequenceException If called multiple times.
  98. */
  99. public function send ()
  100. {
  101. if ($this->_sent) {
  102. throw new CAS_OutOfSequenceException(
  103. 'Request has already been sent cannot send again.'
  104. );
  105. }
  106. if (!count($this->_requests)) {
  107. throw new CAS_OutOfSequenceException(
  108. 'At least one request must be added via addRequest() before the multi-request can be sent.'
  109. );
  110. }
  111. $this->_sent = true;
  112. // Initialize our handles and configure all requests.
  113. $handles = array();
  114. $multiHandle = curl_multi_init();
  115. foreach ($this->_requests as $i => $request) {
  116. $handle = $request->initAndConfigure();
  117. curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
  118. $handles[$i] = $handle;
  119. curl_multi_add_handle($multiHandle, $handle);
  120. }
  121. // Execute the requests in parallel.
  122. do {
  123. curl_multi_exec($multiHandle, $running);
  124. } while ($running > 0);
  125. // Populate all of the responses or errors back into the request objects.
  126. foreach ($this->_requests as $i => $request) {
  127. $buf = curl_multi_getcontent($handles[$i]);
  128. $request->_storeResponseBody($buf);
  129. curl_multi_remove_handle($multiHandle, $handles[$i]);
  130. curl_close($handles[$i]);
  131. }
  132. curl_multi_close($multiHandle);
  133. }
  134. }