Chris@0: setOptions($options); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Process any injected configuration options Chris@0: * Chris@0: * @param array|Traversable $options Options array or Traversable object Chris@0: * @return AbstractCallback Chris@0: * @throws Exception\InvalidArgumentException Chris@0: */ Chris@0: public function setOptions($options) Chris@0: { Chris@0: if ($options instanceof Traversable) { Chris@0: $options = ArrayUtils::iteratorToArray($options); Chris@0: } Chris@0: Chris@12: if (! is_array($options)) { Chris@0: throw new Exception\InvalidArgumentException('Array or Traversable object' Chris@0: . 'expected, got ' . gettype($options)); Chris@0: } Chris@0: Chris@0: if (is_array($options)) { Chris@0: $this->setOptions($options); Chris@0: } Chris@0: Chris@0: if (array_key_exists('storage', $options)) { Chris@0: $this->setStorage($options['storage']); Chris@0: } Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Send the response, including all headers. Chris@0: * If you wish to handle this via Zend\Http, use the getter methods Chris@0: * to retrieve any data needed to be set on your HTTP Response object, or Chris@0: * simply give this object the HTTP Response instance to work with for you! Chris@0: * Chris@0: * @return void Chris@0: */ Chris@0: public function sendResponse() Chris@0: { Chris@0: $this->getHttpResponse()->send(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Sets an instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used Chris@0: * to background save any verification tokens associated with a subscription Chris@0: * or other. Chris@0: * Chris@0: * @param Model\SubscriptionPersistenceInterface $storage Chris@0: * @return AbstractCallback Chris@0: */ Chris@0: public function setStorage(Model\SubscriptionPersistenceInterface $storage) Chris@0: { Chris@0: $this->storage = $storage; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets an instance of Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence used Chris@0: * to background save any verification tokens associated with a subscription Chris@0: * or other. Chris@0: * Chris@0: * @return Model\SubscriptionPersistenceInterface Chris@0: * @throws Exception\RuntimeException Chris@0: */ Chris@0: public function getStorage() Chris@0: { Chris@0: if ($this->storage === null) { Chris@0: throw new Exception\RuntimeException('No storage object has been' Chris@0: . ' set that subclasses Zend\Feed\Pubsubhubbub\Model\SubscriptionPersistence'); Chris@0: } Chris@0: return $this->storage; Chris@0: } Chris@0: Chris@0: /** Chris@0: * An instance of a class handling Http Responses. This is implemented in Chris@0: * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with Chris@0: * (i.e. not inherited from) Zend\Controller\Response\Http. Chris@0: * Chris@0: * @param HttpResponse|PhpResponse $httpResponse Chris@0: * @return AbstractCallback Chris@0: * @throws Exception\InvalidArgumentException Chris@0: */ Chris@0: public function setHttpResponse($httpResponse) Chris@0: { Chris@12: if (! $httpResponse instanceof HttpResponse && ! $httpResponse instanceof PhpResponse) { Chris@0: throw new Exception\InvalidArgumentException('HTTP Response object must' Chris@0: . ' implement one of Zend\Feed\Pubsubhubbub\HttpResponse or' Chris@0: . ' Zend\Http\PhpEnvironment\Response'); Chris@0: } Chris@0: $this->httpResponse = $httpResponse; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@0: * An instance of a class handling Http Responses. This is implemented in Chris@0: * Zend\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with Chris@0: * (i.e. not inherited from) Zend\Controller\Response\Http. Chris@0: * Chris@0: * @return HttpResponse|PhpResponse Chris@0: */ Chris@0: public function getHttpResponse() Chris@0: { Chris@0: if ($this->httpResponse === null) { Chris@0: $this->httpResponse = new HttpResponse; Chris@0: } Chris@0: return $this->httpResponse; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Sets the number of Subscribers for which any updates are on behalf of. Chris@0: * In other words, is this class serving one or more subscribers? How many? Chris@0: * Defaults to 1 if left unchanged. Chris@0: * Chris@0: * @param string|int $count Chris@0: * @return AbstractCallback Chris@0: * @throws Exception\InvalidArgumentException Chris@0: */ Chris@0: public function setSubscriberCount($count) Chris@0: { Chris@0: $count = intval($count); Chris@0: if ($count <= 0) { Chris@0: throw new Exception\InvalidArgumentException('Subscriber count must be' Chris@0: . ' greater than zero'); Chris@0: } Chris@0: $this->subscriberCount = $count; Chris@0: return $this; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the number of Subscribers for which any updates are on behalf of. Chris@0: * In other words, is this class serving one or more subscribers? How many? Chris@0: * Chris@0: * @return int Chris@0: */ Chris@0: public function getSubscriberCount() Chris@0: { Chris@0: return $this->subscriberCount; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Attempt to detect the callback URL (specifically the path forward) Chris@0: * @return string Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _detectCallbackUrl() Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@17: $callbackUrl = null; Chris@17: Chris@17: // IIS7 with URL Rewrite: make sure we get the unencoded url Chris@17: // (double slash problem). Chris@17: $iisUrlRewritten = isset($_SERVER['IIS_WasUrlRewritten']) ? $_SERVER['IIS_WasUrlRewritten'] : null; Chris@17: $unencodedUrl = isset($_SERVER['UNENCODED_URL']) ? $_SERVER['UNENCODED_URL'] : null; Chris@17: if ('1' == $iisUrlRewritten && ! empty($unencodedUrl)) { Chris@17: return $unencodedUrl; Chris@0: } Chris@17: Chris@17: // HTTP proxy requests setup request URI with scheme and host [and port] Chris@17: // + the URL path, only use URL path. Chris@17: if (isset($_SERVER['REQUEST_URI'])) { Chris@17: $callbackUrl = $this->buildCallbackUrlFromRequestUri(); Chris@17: } Chris@17: Chris@17: if (null !== $callbackUrl) { Chris@17: return $callbackUrl; Chris@17: } Chris@17: Chris@17: if (isset($_SERVER['ORIG_PATH_INFO'])) { Chris@17: return $this->buildCallbackUrlFromOrigPathInfo(); Chris@17: } Chris@17: Chris@17: return ''; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the HTTP host Chris@0: * Chris@0: * @return string Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _getHttpHost() Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@12: if (! empty($_SERVER['HTTP_HOST'])) { Chris@0: return $_SERVER['HTTP_HOST']; Chris@0: } Chris@17: Chris@17: $https = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : null; Chris@17: $scheme = $https === 'on' ? 'https' : 'http'; Chris@17: $name = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : ''; Chris@17: $port = isset($_SERVER['SERVER_PORT']) ? (int) $_SERVER['SERVER_PORT'] : 80; Chris@17: Chris@17: if (($scheme === 'http' && $port === 80) Chris@17: || ($scheme === 'https' && $port === 443) Chris@0: ) { Chris@0: return $name; Chris@0: } Chris@0: Chris@17: return sprintf('%s:%d', $name, $port); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Retrieve a Header value from either $_SERVER or Apache Chris@0: * Chris@0: * @param string $header Chris@0: * @return bool|string Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _getHeader($header) Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@0: $temp = strtoupper(str_replace('-', '_', $header)); Chris@12: if (! empty($_SERVER[$temp])) { Chris@0: return $_SERVER[$temp]; Chris@0: } Chris@0: $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header)); Chris@12: if (! empty($_SERVER[$temp])) { Chris@0: return $_SERVER[$temp]; Chris@0: } Chris@0: if (function_exists('apache_request_headers')) { Chris@0: $headers = apache_request_headers(); Chris@12: if (! empty($headers[$header])) { Chris@0: return $headers[$header]; Chris@0: } Chris@0: } Chris@0: return false; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Return the raw body of the request Chris@0: * Chris@0: * @return string|false Raw body, or false if not present Chris@0: */ Chris@12: // @codingStandardsIgnoreStart Chris@0: protected function _getRawBody() Chris@0: { Chris@12: // @codingStandardsIgnoreEnd Chris@16: $body = is_resource($this->inputStream) Chris@16: ? stream_get_contents($this->inputStream) Chris@16: : file_get_contents($this->inputStream); Chris@16: Chris@16: return strlen(trim($body)) > 0 ? $body : false; Chris@0: } Chris@17: Chris@17: /** Chris@17: * Build the callback URL from the REQUEST_URI server parameter. Chris@17: * Chris@17: * @return string Chris@17: */ Chris@17: private function buildCallbackUrlFromRequestUri() Chris@17: { Chris@17: $callbackUrl = $_SERVER['REQUEST_URI']; Chris@17: $https = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : null; Chris@17: $scheme = $https === 'on' ? 'https' : 'http'; Chris@17: if ($https === 'on') { Chris@17: $scheme = 'https'; Chris@17: } Chris@17: $schemeAndHttpHost = $scheme . '://' . $this->_getHttpHost(); Chris@17: if (strpos($callbackUrl, $schemeAndHttpHost) === 0) { Chris@17: $callbackUrl = substr($callbackUrl, strlen($schemeAndHttpHost)); Chris@17: } Chris@17: return $callbackUrl; Chris@17: } Chris@17: Chris@17: /** Chris@17: * Build the callback URL from the ORIG_PATH_INFO server parameter. Chris@17: * Chris@17: * @return string Chris@17: */ Chris@17: private function buildCallbackUrlFromOrigPathInfo() Chris@17: { Chris@17: $callbackUrl = $_SERVER['ORIG_PATH_INFO']; Chris@17: if (! empty($_SERVER['QUERY_STRING'])) { Chris@17: $callbackUrl .= '?' . $_SERVER['QUERY_STRING']; Chris@17: } Chris@17: return $callbackUrl; Chris@17: } Chris@0: }