Imbo\Http\Response\ResponseFormatter::negotiate PHP Метод

negotiate() публичный Метод

Perform content negotiation by looking the the current URL and the Accept request header
public negotiate ( Imbo\EventManager\EventInterface $event )
$event Imbo\EventManager\EventInterface The event instance
    public function negotiate(EventInterface $event)
    {
        $request = $event->getRequest();
        $response = $event->getResponse();
        $formatter = null;
        $extension = $request->getExtension();
        $routeName = (string) $request->getRoute();
        $config = $event->getConfig();
        $contentNegotiateImages = $config['contentNegotiateImages'];
        $model = $response->getModel();
        if (!$extension && !$contentNegotiateImages && $model instanceof Model\Image) {
            // Configuration is telling us not to use content negotiation for images,
            // instead we want to use the original format of the image
            $mime = $model->getMimeType();
            $formatter = $this->supportedTypes[$mime];
        } else {
            if ($extension && !($model instanceof Model\Error && ($routeName === 'image' || $routeName === 'globalshorturl'))) {
                // The user agent wants a specific type. Skip content negotiation completely, but not
                // if the request is against the image resource (or the global short url resource), and
                // ended up as an error, because then Imbo would try to render the error as an image.
                $mime = $this->defaultMimeType;
                if (isset($this->extensionsToMimeType[$extension])) {
                    $mime = $this->extensionsToMimeType[$extension];
                }
                $formatter = $this->supportedTypes[$mime];
            } else {
                // Set Vary to Accept since we are doing content negotiation based on Accept
                $response->setVary('Accept', false);
                // No extension have been provided
                $acceptableTypes = [];
                foreach (AcceptHeader::fromString($request->headers->get('Accept', '*/*'))->all() as $item) {
                    $acceptableTypes[$item->getValue()] = $item->getQuality();
                }
                $match = false;
                $maxQ = 0;
                // Specify which types to check for since all models can't be formatted by all
                // formatters
                $modelClass = get_class($model);
                $modelType = strtolower(substr($modelClass, strrpos($modelClass, '\\') + 1));
                $types = $this->defaultModelTypes;
                if (isset($this->modelTypes[$modelType])) {
                    $types = $this->modelTypes[$modelType];
                }
                // If we are dealing with images we want to make sure the original mime type of the
                // image is checked first. If the client does not really have any preference with
                // regards to the mime type (*/* or image/*) this results in the original mime type of
                // the image being sent.
                if ($model instanceof Model\Image) {
                    $original = $model->getMimeType();
                    if ($types[0] !== $original) {
                        $types = array_filter($types, function ($type) use($original) {
                            return $type !== $original;
                        });
                        array_unshift($types, $original);
                    }
                }
                foreach ($types as $mime) {
                    if (($q = $this->contentNegotiation->isAcceptable($mime, $acceptableTypes)) && $q > $maxQ) {
                        $maxQ = $q;
                        $match = true;
                        $formatter = $this->supportedTypes[$mime];
                    }
                }
                if (!$match && !$event->hasArgument('noStrict')) {
                    // No types matched with strict mode enabled. The client does not want any of Imbo's
                    // supported types. Y U NO ACCEPT MY TYPES?! FFFFUUUUUUU!
                    throw new Exception\RuntimeException('Not acceptable', 406);
                } else {
                    if (!$match) {
                        // There was no match but we don't want to be an ass about it. Send a response
                        // anyway (allowed according to RFC2616, section 10.4.7)
                        $formatter = $this->supportedTypes[$this->defaultMimeType];
                    }
                }
            }
        }
        $this->formatter = $formatter;
    }

Usage Example

Пример #1
0
 /**
  * @covers Imbo\Http\Response\ResponseFormatter::negotiate
  */
 public function testDoesNotForceContentNegotiationOnErrorModelsWhenResourceIsNotAnImage()
 {
     $route = new Route();
     $route->setName('user');
     $this->request->expects($this->once())->method('getExtension')->will($this->returnValue('json'));
     $this->request->expects($this->once())->method('getRoute')->will($this->returnValue($route));
     $this->response->expects($this->never())->method('setVary');
     $this->response->expects($this->once())->method('getModel')->will($this->returnValue($this->getMock('Imbo\\Model\\Error')));
     $this->responseFormatter->negotiate($this->event);
     $this->assertSame('json', $this->responseFormatter->getFormatter());
 }