Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/neomerx/json-api/src/Http/Headers/MediaType.php
<?php declare(strict_types=1);

namespace
Neomerx\JsonApi\Http\Headers;

/**
 * Copyright 2015-2019 info@neomerx.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use Neomerx\JsonApi\Contracts\Http\Headers\MediaTypeInterface;
use
Neomerx\JsonApi\Exceptions\InvalidArgumentException;

/**
 * @package Neomerx\JsonApi
 */
class MediaType implements MediaTypeInterface
{
   
/**
     * @var string
     */
   
private $type;

   
/**
     * @var string
     */
   
private $subType;

   
/**
     * @var string?
     */
   
private $mediaType = null;

   
/**
     * @var array<string,string>|null
     */
   
private $parameters;

   
/**
     * A list of parameter names for case-insensitive compare. Keys must be lower-cased.
     *
     * @var array
     */
   
protected const PARAMETER_NAMES = [
       
'charset' => true,
    ];

   
/**
     * @param string $type
     * @param string $subType
     * @param array<string,string>|null $parameters
     */
   
public function __construct(string $type, string $subType, array $parameters = null)
    {
       
$type = \trim($type);
        if (empty(
$type) === true) {
            throw new
InvalidArgumentException('type');
        }

       
$subType = \trim($subType);
        if (empty(
$subType) === true) {
            throw new
InvalidArgumentException('subType');
        }

       
$this->type       = $type;
       
$this->subType    = $subType;
       
$this->parameters = $parameters;
    }

   
/**
     * @inheritdoc
     */
   
public function getType(): string
   
{
        return
$this->type;
    }

   
/**
     * @inheritdoc
     */
   
public function getSubType(): string
   
{
        return
$this->subType;
    }

   
/**
     * @inheritdoc
     */
   
public function getMediaType(): string
   
{
        if (
$this->mediaType === null) {
           
$this->mediaType = $this->type . '/' . $this->getSubType();
        }

        return
$this->mediaType;
    }

   
/**
     * @inheritdoc
     */
   
public function getParameters(): ?array
    {
        return
$this->parameters;
    }

   
/**
     * @inheritdoc
     */
   
public function matchesTo(MediaTypeInterface $mediaType): bool
   
{
        return
           
$this->isTypeMatches($mediaType) &&
           
$this->isSubTypeMatches($mediaType) &&
           
$this->isMediaParametersMatch($mediaType);
    }

   
/**
     * @inheritdoc
     */
   
public function equalsTo(MediaTypeInterface $mediaType): bool
   
{
        return
           
$this->isTypeEquals($mediaType) &&
           
$this->isSubTypeEquals($mediaType) &&
           
$this->isMediaParametersEqual($mediaType);
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function isTypeMatches(MediaTypeInterface $mediaType): bool
   
{
        return
$mediaType->getType() === '*' || $this->isTypeEquals($mediaType);
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function isTypeEquals(MediaTypeInterface $mediaType): bool
   
{
       
// Type, subtype and param name should be compared case-insensitive
        // https://tools.ietf.org/html/rfc7231#section-3.1.1.1
       
return \strcasecmp($this->type, $mediaType->getType()) === 0;
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function isSubTypeMatches(MediaTypeInterface $mediaType): bool
   
{
        return
$mediaType->getSubType() === '*' || $this->isSubTypeEquals($mediaType);
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function isSubTypeEquals(MediaTypeInterface $mediaType): bool
   
{
       
// Type, subtype and param name should be compared case-insensitive
        // https://tools.ietf.org/html/rfc7231#section-3.1.1.1
       
return \strcasecmp($this->getSubType(), $mediaType->getSubType()) === 0;
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function isMediaParametersMatch(MediaTypeInterface $mediaType): bool
   
{
        if (
$this->bothMediaTypeParamsEmpty($mediaType) === true) {
            return
true;
        } elseif (
$this->bothMediaTypeParamsNotEmptyAndEqualInSize($mediaType)) {
           
// Type, subtype and param name should be compared case-insensitive
            // https://tools.ietf.org/html/rfc7231#section-3.1.1.1
           
$ourParameters       = \array_change_key_case($this->parameters);
           
$parametersToCompare = \array_change_key_case($mediaType->getParameters());

           
// if at least one name are different they are not equal
           
if (empty(\array_diff_key($ourParameters, $parametersToCompare)) === false) {
                return
false;
            }

           
// If we are here we have to compare values. Also some of the values should be compared case-insensitive
            // according to https://tools.ietf.org/html/rfc7231#section-3.1.1.1
            // > 'Parameter values might or might not be case-sensitive, depending on
            // the semantics of the parameter name.'
           
foreach ($ourParameters as $name => $value) {
                if (
$this->paramValuesMatch($name, $value, $parametersToCompare[$name]) === false) {
                    return
false;
                }
            }

            return
true;
        }

        return
false;
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function isMediaParametersEqual(MediaTypeInterface $mediaType): bool
   
{
        if (
$this->bothMediaTypeParamsEmpty($mediaType) === true) {
            return
true;
        } elseif (
$this->bothMediaTypeParamsNotEmptyAndEqualInSize($mediaType)) {
           
// Type, subtype and param name should be compared case-insensitive
            // https://tools.ietf.org/html/rfc7231#section-3.1.1.1
           
$ourParameters       = \array_change_key_case($this->parameters);
           
$parametersToCompare = \array_change_key_case($mediaType->getParameters());

           
// if at least one name are different they are not equal
           
if (empty(\array_diff_key($ourParameters, $parametersToCompare)) === false) {
                return
false;
            }

           
// If we are here we have to compare values. Also some of the values should be compared case-insensitive
            // according to https://tools.ietf.org/html/rfc7231#section-3.1.1.1
            // > 'Parameter values might or might not be case-sensitive, depending on
            // the semantics of the parameter name.'
           
foreach ($ourParameters as $name => $value) {
                if (
$this->paramValuesEqual($name, $value, $parametersToCompare[$name]) === false) {
                    return
false;
                }
            }

            return
true;
        }

        return
false;
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function bothMediaTypeParamsEmpty(MediaTypeInterface $mediaType): bool
   
{
        return
$this->parameters === null && $mediaType->getParameters() === null;
    }

   
/**
     * @param MediaTypeInterface $mediaType
     *
     * @return bool
     */
   
private function bothMediaTypeParamsNotEmptyAndEqualInSize(MediaTypeInterface $mediaType): bool
   
{
       
$pr1 = $this->parameters;
       
$pr2 = $mediaType->getParameters();

        return (empty(
$pr1) === false && empty($pr2) === false) && (\count($pr1) === \count($pr2));
    }

   
/**
     * @param string $name
     *
     * @return bool
     */
   
private function isParamCaseInsensitive(string $name): bool
   
{
        return isset(static::
PARAMETER_NAMES[$name]);
    }

   
/**
     * @param string $name
     * @param string $value
     * @param string $valueToCompare
     *
     * @return bool
     */
   
private function paramValuesEqual(string $name, string $value, string $valueToCompare): bool
   
{
       
$valuesEqual = $this->isParamCaseInsensitive($name) === true ?
            \
strcasecmp($value, $valueToCompare) === 0 : $value === $valueToCompare;

        return
$valuesEqual;
    }

   
/**
     * @param string $name
     * @param string $value
     * @param string $valueToCompare
     *
     * @return bool
     */
   
private function paramValuesMatch(string $name, string $value, string $valueToCompare): bool
   
{
       
$valuesEqual = $valueToCompare === '*' || $this->paramValuesEqual($name, $value, $valueToCompare);

        return
$valuesEqual;
    }
}