annotate vendor/zendframework/zend-feed/src/PubSubHubbub/AbstractCallback.php @ 4:a9cd425dd02b

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:11:55 +0000
parents 5311817fb629
children
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@0 3 * Zend Framework (http://framework.zend.com/)
Chris@0 4 *
Chris@0 5 * @link http://github.com/zendframework/zf2 for the canonical source repository
Chris@0 6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
Chris@0 7 * @license http://framework.zend.com/license/new-bsd New BSD License
Chris@0 8 */
Chris@0 9
Chris@0 10 namespace Zend\Feed\PubSubHubbub;
Chris@0 11
Chris@0 12 use Traversable;
Chris@0 13 use Zend\Http\PhpEnvironment\Response as PhpResponse;
Chris@0 14 use Zend\Stdlib\ArrayUtils;
Chris@0 15
Chris@0 16 abstract class AbstractCallback implements CallbackInterface
Chris@0 17 {
Chris@0 18 /**
Chris@0 19 * An instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistenceInterface
Chris@0 20 * used to background save any verification tokens associated with a subscription
Chris@0 21 * or other.
Chris@0 22 *
Chris@0 23 * @var Model\SubscriptionPersistenceInterface
Chris@0 24 */
Chris@0 25 protected $storage = null;
Chris@0 26
Chris@0 27 /**
Chris@0 28 * An instance of a class handling Http Responses. This is implemented in
Chris@0 29 * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with
Chris@0 30 * (i.e. not inherited from) Zend\Controller\Response\Http.
Chris@0 31 *
Chris@0 32 * @var HttpResponse|PhpResponse
Chris@0 33 */
Chris@0 34 protected $httpResponse = null;
Chris@0 35
Chris@0 36 /**
Chris@2 37 * The input stream to use when retrieving the request body. Defaults to
Chris@2 38 * php://input, but can be set to another value in order to force usage
Chris@2 39 * of another input method. This should primarily be used for testing
Chris@2 40 * purposes.
Chris@2 41 *
Chris@2 42 * @var string|resource String indicates a filename or stream to open;
Chris@2 43 * resource indicates an already created stream to use.
Chris@2 44 */
Chris@2 45 protected $inputStream = 'php://input';
Chris@2 46
Chris@2 47 /**
Chris@0 48 * The number of Subscribers for which any updates are on behalf of.
Chris@0 49 *
Chris@0 50 * @var int
Chris@0 51 */
Chris@0 52 protected $subscriberCount = 1;
Chris@0 53
Chris@0 54 /**
Chris@0 55 * Constructor; accepts an array or Traversable object to preset
Chris@0 56 * options for the Subscriber without calling all supported setter
Chris@0 57 * methods in turn.
Chris@0 58 *
Chris@0 59 * @param array|Traversable $options Options array or Traversable object
Chris@0 60 */
Chris@0 61 public function __construct($options = null)
Chris@0 62 {
Chris@0 63 if ($options !== null) {
Chris@0 64 $this->setOptions($options);
Chris@0 65 }
Chris@0 66 }
Chris@0 67
Chris@0 68 /**
Chris@0 69 * Process any injected configuration options
Chris@0 70 *
Chris@0 71 * @param array|Traversable $options Options array or Traversable object
Chris@0 72 * @return AbstractCallback
Chris@0 73 * @throws Exception\InvalidArgumentException
Chris@0 74 */
Chris@0 75 public function setOptions($options)
Chris@0 76 {
Chris@0 77 if ($options instanceof Traversable) {
Chris@0 78 $options = ArrayUtils::iteratorToArray($options);
Chris@0 79 }
Chris@0 80
Chris@2 81 if (! is_array($options)) {
Chris@0 82 throw new Exception\InvalidArgumentException('Array or Traversable object'
Chris@0 83 . 'expected, got ' . gettype($options));
Chris@0 84 }
Chris@0 85
Chris@0 86 if (is_array($options)) {
Chris@0 87 $this->setOptions($options);
Chris@0 88 }
Chris@0 89
Chris@0 90 if (array_key_exists('storage', $options)) {
Chris@0 91 $this->setStorage($options['storage']);
Chris@0 92 }
Chris@0 93 return $this;
Chris@0 94 }
Chris@0 95
Chris@0 96 /**
Chris@0 97 * Send the response, including all headers.
Chris@0 98 * If you wish to handle this via Zend\Http, use the getter methods
Chris@0 99 * to retrieve any data needed to be set on your HTTP Response object, or
Chris@0 100 * simply give this object the HTTP Response instance to work with for you!
Chris@0 101 *
Chris@0 102 * @return void
Chris@0 103 */
Chris@0 104 public function sendResponse()
Chris@0 105 {
Chris@0 106 $this->getHttpResponse()->send();
Chris@0 107 }
Chris@0 108
Chris@0 109 /**
Chris@0 110 * Sets an instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used
Chris@0 111 * to background save any verification tokens associated with a subscription
Chris@0 112 * or other.
Chris@0 113 *
Chris@0 114 * @param Model\SubscriptionPersistenceInterface $storage
Chris@0 115 * @return AbstractCallback
Chris@0 116 */
Chris@0 117 public function setStorage(Model\SubscriptionPersistenceInterface $storage)
Chris@0 118 {
Chris@0 119 $this->storage = $storage;
Chris@0 120 return $this;
Chris@0 121 }
Chris@0 122
Chris@0 123 /**
Chris@0 124 * Gets an instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used
Chris@0 125 * to background save any verification tokens associated with a subscription
Chris@0 126 * or other.
Chris@0 127 *
Chris@0 128 * @return Model\SubscriptionPersistenceInterface
Chris@0 129 * @throws Exception\RuntimeException
Chris@0 130 */
Chris@0 131 public function getStorage()
Chris@0 132 {
Chris@0 133 if ($this->storage === null) {
Chris@0 134 throw new Exception\RuntimeException('No storage object has been'
Chris@0 135 . ' set that subclasses Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence');
Chris@0 136 }
Chris@0 137 return $this->storage;
Chris@0 138 }
Chris@0 139
Chris@0 140 /**
Chris@0 141 * An instance of a class handling Http Responses. This is implemented in
Chris@0 142 * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with
Chris@0 143 * (i.e. not inherited from) Zend\Controller\Response\Http.
Chris@0 144 *
Chris@0 145 * @param HttpResponse|PhpResponse $httpResponse
Chris@0 146 * @return AbstractCallback
Chris@0 147 * @throws Exception\InvalidArgumentException
Chris@0 148 */
Chris@0 149 public function setHttpResponse($httpResponse)
Chris@0 150 {
Chris@2 151 if (! $httpResponse instanceof HttpResponse && ! $httpResponse instanceof PhpResponse) {
Chris@0 152 throw new Exception\InvalidArgumentException('HTTP Response object must'
Chris@0 153 . ' implement one of Zend\Feed\Pubsubhubbub\HttpResponse or'
Chris@0 154 . ' Zend\Http\PhpEnvironment\Response');
Chris@0 155 }
Chris@0 156 $this->httpResponse = $httpResponse;
Chris@0 157 return $this;
Chris@0 158 }
Chris@0 159
Chris@0 160 /**
Chris@0 161 * An instance of a class handling Http Responses. This is implemented in
Chris@0 162 * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with
Chris@0 163 * (i.e. not inherited from) Zend\Controller\Response\Http.
Chris@0 164 *
Chris@0 165 * @return HttpResponse|PhpResponse
Chris@0 166 */
Chris@0 167 public function getHttpResponse()
Chris@0 168 {
Chris@0 169 if ($this->httpResponse === null) {
Chris@0 170 $this->httpResponse = new HttpResponse;
Chris@0 171 }
Chris@0 172 return $this->httpResponse;
Chris@0 173 }
Chris@0 174
Chris@0 175 /**
Chris@0 176 * Sets the number of Subscribers for which any updates are on behalf of.
Chris@0 177 * In other words, is this class serving one or more subscribers? How many?
Chris@0 178 * Defaults to 1 if left unchanged.
Chris@0 179 *
Chris@0 180 * @param string|int $count
Chris@0 181 * @return AbstractCallback
Chris@0 182 * @throws Exception\InvalidArgumentException
Chris@0 183 */
Chris@0 184 public function setSubscriberCount($count)
Chris@0 185 {
Chris@0 186 $count = intval($count);
Chris@0 187 if ($count <= 0) {
Chris@0 188 throw new Exception\InvalidArgumentException('Subscriber count must be'
Chris@0 189 . ' greater than zero');
Chris@0 190 }
Chris@0 191 $this->subscriberCount = $count;
Chris@0 192 return $this;
Chris@0 193 }
Chris@0 194
Chris@0 195 /**
Chris@0 196 * Gets the number of Subscribers for which any updates are on behalf of.
Chris@0 197 * In other words, is this class serving one or more subscribers? How many?
Chris@0 198 *
Chris@0 199 * @return int
Chris@0 200 */
Chris@0 201 public function getSubscriberCount()
Chris@0 202 {
Chris@0 203 return $this->subscriberCount;
Chris@0 204 }
Chris@0 205
Chris@0 206 /**
Chris@0 207 * Attempt to detect the callback URL (specifically the path forward)
Chris@0 208 * @return string
Chris@0 209 */
Chris@2 210 // @codingStandardsIgnoreStart
Chris@0 211 protected function _detectCallbackUrl()
Chris@0 212 {
Chris@2 213 // @codingStandardsIgnoreEnd
Chris@4 214 $callbackUrl = null;
Chris@4 215
Chris@4 216 // IIS7 with URL Rewrite: make sure we get the unencoded url
Chris@4 217 // (double slash problem).
Chris@4 218 $iisUrlRewritten = isset($_SERVER['IIS_WasUrlRewritten']) ? $_SERVER['IIS_WasUrlRewritten'] : null;
Chris@4 219 $unencodedUrl = isset($_SERVER['UNENCODED_URL']) ? $_SERVER['UNENCODED_URL'] : null;
Chris@4 220 if ('1' == $iisUrlRewritten && ! empty($unencodedUrl)) {
Chris@4 221 return $unencodedUrl;
Chris@0 222 }
Chris@4 223
Chris@4 224 // HTTP proxy requests setup request URI with scheme and host [and port]
Chris@4 225 // + the URL path, only use URL path.
Chris@4 226 if (isset($_SERVER['REQUEST_URI'])) {
Chris@4 227 $callbackUrl = $this->buildCallbackUrlFromRequestUri();
Chris@4 228 }
Chris@4 229
Chris@4 230 if (null !== $callbackUrl) {
Chris@4 231 return $callbackUrl;
Chris@4 232 }
Chris@4 233
Chris@4 234 if (isset($_SERVER['ORIG_PATH_INFO'])) {
Chris@4 235 return $this->buildCallbackUrlFromOrigPathInfo();
Chris@4 236 }
Chris@4 237
Chris@4 238 return '';
Chris@0 239 }
Chris@0 240
Chris@0 241 /**
Chris@0 242 * Get the HTTP host
Chris@0 243 *
Chris@0 244 * @return string
Chris@0 245 */
Chris@2 246 // @codingStandardsIgnoreStart
Chris@0 247 protected function _getHttpHost()
Chris@0 248 {
Chris@2 249 // @codingStandardsIgnoreEnd
Chris@2 250 if (! empty($_SERVER['HTTP_HOST'])) {
Chris@0 251 return $_SERVER['HTTP_HOST'];
Chris@0 252 }
Chris@4 253
Chris@4 254 $https = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : null;
Chris@4 255 $scheme = $https === 'on' ? 'https' : 'http';
Chris@4 256 $name = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
Chris@4 257 $port = isset($_SERVER['SERVER_PORT']) ? (int) $_SERVER['SERVER_PORT'] : 80;
Chris@4 258
Chris@4 259 if (($scheme === 'http' && $port === 80)
Chris@4 260 || ($scheme === 'https' && $port === 443)
Chris@0 261 ) {
Chris@0 262 return $name;
Chris@0 263 }
Chris@0 264
Chris@4 265 return sprintf('%s:%d', $name, $port);
Chris@0 266 }
Chris@0 267
Chris@0 268 /**
Chris@0 269 * Retrieve a Header value from either $_SERVER or Apache
Chris@0 270 *
Chris@0 271 * @param string $header
Chris@0 272 * @return bool|string
Chris@0 273 */
Chris@2 274 // @codingStandardsIgnoreStart
Chris@0 275 protected function _getHeader($header)
Chris@0 276 {
Chris@2 277 // @codingStandardsIgnoreEnd
Chris@0 278 $temp = strtoupper(str_replace('-', '_', $header));
Chris@2 279 if (! empty($_SERVER[$temp])) {
Chris@0 280 return $_SERVER[$temp];
Chris@0 281 }
Chris@0 282 $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
Chris@2 283 if (! empty($_SERVER[$temp])) {
Chris@0 284 return $_SERVER[$temp];
Chris@0 285 }
Chris@0 286 if (function_exists('apache_request_headers')) {
Chris@0 287 $headers = apache_request_headers();
Chris@2 288 if (! empty($headers[$header])) {
Chris@0 289 return $headers[$header];
Chris@0 290 }
Chris@0 291 }
Chris@0 292 return false;
Chris@0 293 }
Chris@0 294
Chris@0 295 /**
Chris@0 296 * Return the raw body of the request
Chris@0 297 *
Chris@0 298 * @return string|false Raw body, or false if not present
Chris@0 299 */
Chris@2 300 // @codingStandardsIgnoreStart
Chris@0 301 protected function _getRawBody()
Chris@0 302 {
Chris@2 303 // @codingStandardsIgnoreEnd
Chris@2 304 $body = is_resource($this->inputStream)
Chris@2 305 ? stream_get_contents($this->inputStream)
Chris@2 306 : file_get_contents($this->inputStream);
Chris@2 307
Chris@2 308 return strlen(trim($body)) > 0 ? $body : false;
Chris@0 309 }
Chris@4 310
Chris@4 311 /**
Chris@4 312 * Build the callback URL from the REQUEST_URI server parameter.
Chris@4 313 *
Chris@4 314 * @return string
Chris@4 315 */
Chris@4 316 private function buildCallbackUrlFromRequestUri()
Chris@4 317 {
Chris@4 318 $callbackUrl = $_SERVER['REQUEST_URI'];
Chris@4 319 $https = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : null;
Chris@4 320 $scheme = $https === 'on' ? 'https' : 'http';
Chris@4 321 if ($https === 'on') {
Chris@4 322 $scheme = 'https';
Chris@4 323 }
Chris@4 324 $schemeAndHttpHost = $scheme . '://' . $this->_getHttpHost();
Chris@4 325 if (strpos($callbackUrl, $schemeAndHttpHost) === 0) {
Chris@4 326 $callbackUrl = substr($callbackUrl, strlen($schemeAndHttpHost));
Chris@4 327 }
Chris@4 328 return $callbackUrl;
Chris@4 329 }
Chris@4 330
Chris@4 331 /**
Chris@4 332 * Build the callback URL from the ORIG_PATH_INFO server parameter.
Chris@4 333 *
Chris@4 334 * @return string
Chris@4 335 */
Chris@4 336 private function buildCallbackUrlFromOrigPathInfo()
Chris@4 337 {
Chris@4 338 $callbackUrl = $_SERVER['ORIG_PATH_INFO'];
Chris@4 339 if (! empty($_SERVER['QUERY_STRING'])) {
Chris@4 340 $callbackUrl .= '?' . $_SERVER['QUERY_STRING'];
Chris@4 341 }
Chris@4 342 return $callbackUrl;
Chris@4 343 }
Chris@0 344 }