Allowed to set and update the forwardQuery param on short URLs

This commit is contained in:
Alejandro Celaya 2021-10-02 10:02:43 +02:00
parent 1ed6458b39
commit 8212d3c540
7 changed files with 106 additions and 98 deletions

View file

@ -0,0 +1,48 @@
{
"type": "object",
"properties": {
"longUrl": {
"description": "The long URL this short URL will redirect to",
"type": "string"
},
"validSince": {
"description": "The date (in ISO-8601 format) from which this short code will be valid",
"type": "string",
"nullable": true
},
"validUntil": {
"description": "The date (in ISO-8601 format) until which this short code will be valid",
"type": "string",
"nullable": true
},
"maxVisits": {
"description": "The maximum number of allowed visits for this short code",
"type": "number",
"nullable": true
},
"validateUrl": {
"description": "Tells if the long URL (if provided) should or should not be validated as a reachable URL. If not provided, it will fall back to app-level config",
"type": "boolean"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The list of tags to set to the short URL."
},
"title": {
"type": "string",
"description": "A descriptive title of the short URL.",
"nullable": true
},
"crawlable": {
"type": "boolean",
"description": "Tells if this URL will be included as 'Allow' in Shlink's robots.txt."
},
"forwardQuery": {
"type": "boolean",
"description": "Tells if the query params should be forwarded from the short URL to the long one, as explained in [the docs](https://shlink.io/documentation/some-features/#query-params-forwarding)."
}
}
}

View file

@ -225,63 +225,37 @@
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"longUrl"
],
"properties": {
"longUrl": {
"description": "The URL to parse",
"type": "string"
"allOf": [
{
"$ref": "../definitions/ShortUrlEdition.json"
},
"tags": {
"description": "The URL to parse",
"type": "array",
"items": {
"type": "string"
{
"type": "object",
"required": ["longUrl"],
"properties": {
"customSlug": {
"description": "A unique custom slug to be used instead of the generated short code",
"type": "string"
},
"findIfExists": {
"description": "Will force existing matching URL to be returned if found, instead of creating a new one",
"type": "boolean"
},
"domain": {
"description": "The domain to which the short URL will be attached",
"type": "string"
},
"shortCodeLength": {
"description": "The length for generated short code. It has to be at least 4 and defaults to 5. It will be ignored when customSlug is provided",
"type": "number"
},
"validateUrl": {
"description": "Tells if the long URL should or should not be validated as a reachable URL. If not provided, it will fall back to app-level config",
"type": "boolean"
}
}
},
"validSince": {
"description": "The date (in ISO-8601 format) from which this short code will be valid",
"type": "string"
},
"validUntil": {
"description": "The date (in ISO-8601 format) until which this short code will be valid",
"type": "string"
},
"customSlug": {
"description": "A unique custom slug to be used instead of the generated short code",
"type": "string"
},
"maxVisits": {
"description": "The maximum number of allowed visits for this short code",
"type": "number"
},
"findIfExists": {
"description": "Will force existing matching URL to be returned if found, instead of creating a new one",
"type": "boolean"
},
"domain": {
"description": "The domain to which the short URL will be attached",
"type": "string"
},
"shortCodeLength": {
"description": "The length for generated short code. It has to be at least 4 and defaults to 5. It will be ignored when customSlug is provided",
"type": "number"
},
"validateUrl": {
"description": "Tells if the long URL should or should not be validated as a reachable URL. If not provided, it will fall back to app-level config",
"type": "boolean"
},
"title": {
"type": "string",
"description": "A descriptive title of the short URL."
},
"crawlable": {
"type": "boolean",
"description": "Tells if this URL will be included as 'Allow' in Shlink's robots.txt."
}
}
]
}
}
}

View file

@ -112,48 +112,7 @@
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"longUrl": {
"description": "The long URL this short URL will redirect to",
"type": "string"
},
"validSince": {
"description": "The date (in ISO-8601 format) from which this short code will be valid",
"type": "string",
"nullable": true
},
"validUntil": {
"description": "The date (in ISO-8601 format) until which this short code will be valid",
"type": "string",
"nullable": true
},
"maxVisits": {
"description": "The maximum number of allowed visits for this short code",
"type": "number",
"nullable": true
},
"validateUrl": {
"description": "Tells if the long URL (if provided) should or should not be validated as a reachable URL. If not provided, it will fall back to app-level config",
"type": "boolean"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The list of tags to set to the short URL."
},
"title": {
"type": "string",
"description": "A descriptive title of the short URL.",
"nullable": true
},
"crawlable": {
"type": "boolean",
"description": "Tells if this URL will be included as 'Allow' in Shlink's robots.txt."
}
}
"$ref": "../definitions/ShortUrlEdition.json"
}
}
}

View file

@ -81,6 +81,7 @@ class ShortUrl extends AbstractEntity
$instance->title = $meta->getTitle();
$instance->titleWasAutoResolved = $meta->titleWasAutoResolved();
$instance->crawlable = $meta->isCrawlable();
$instance->forwardQuery = $meta->forwardQuery();
return $instance;
}
@ -244,6 +245,9 @@ class ShortUrl extends AbstractEntity
$this->title = $shortUrlEdit->title();
$this->titleWasAutoResolved = $shortUrlEdit->titleWasAutoResolved();
}
if ($shortUrlEdit->forwardQueryWasProvided()) {
$this->forwardQuery = $shortUrlEdit->forwardQuery();
}
}
/**

View file

@ -32,6 +32,8 @@ final class ShortUrlEdit implements TitleResolutionModelInterface
private ?bool $validateUrl = null;
private bool $crawlablePropWasProvided = false;
private bool $crawlable = false;
private bool $forwardQueryPropWasProvided = false;
private bool $forwardQuery = true;
private function __construct()
{
@ -64,6 +66,7 @@ final class ShortUrlEdit implements TitleResolutionModelInterface
$this->tagsPropWasProvided = array_key_exists(ShortUrlInputFilter::TAGS, $data);
$this->titlePropWasProvided = array_key_exists(ShortUrlInputFilter::TITLE, $data);
$this->crawlablePropWasProvided = array_key_exists(ShortUrlInputFilter::CRAWLABLE, $data);
$this->forwardQueryPropWasProvided = array_key_exists(ShortUrlInputFilter::FORWARD_QUERY, $data);
$this->longUrl = $inputFilter->getValue(ShortUrlInputFilter::LONG_URL);
$this->validSince = parseDateField($inputFilter->getValue(ShortUrlInputFilter::VALID_SINCE));
@ -73,6 +76,7 @@ final class ShortUrlEdit implements TitleResolutionModelInterface
$this->tags = $inputFilter->getValue(ShortUrlInputFilter::TAGS);
$this->title = $inputFilter->getValue(ShortUrlInputFilter::TITLE);
$this->crawlable = $inputFilter->getValue(ShortUrlInputFilter::CRAWLABLE);
$this->forwardQuery = getOptionalBoolFromInputFilter($inputFilter, ShortUrlInputFilter::FORWARD_QUERY) ?? true;
}
public function longUrl(): ?string
@ -176,4 +180,14 @@ final class ShortUrlEdit implements TitleResolutionModelInterface
{
return $this->crawlablePropWasProvided;
}
public function forwardQuery(): bool
{
return $this->forwardQuery;
}
public function forwardQueryWasProvided(): bool
{
return $this->forwardQueryPropWasProvided;
}
}

View file

@ -32,6 +32,7 @@ final class ShortUrlMeta implements TitleResolutionModelInterface
private ?string $title = null;
private bool $titleWasAutoResolved = false;
private bool $crawlable = false;
private bool $forwardQuery = true;
private function __construct()
{
@ -82,6 +83,7 @@ final class ShortUrlMeta implements TitleResolutionModelInterface
$this->tags = $inputFilter->getValue(ShortUrlInputFilter::TAGS);
$this->title = $inputFilter->getValue(ShortUrlInputFilter::TITLE);
$this->crawlable = $inputFilter->getValue(ShortUrlInputFilter::CRAWLABLE);
$this->forwardQuery = getOptionalBoolFromInputFilter($inputFilter, ShortUrlInputFilter::FORWARD_QUERY) ?? true;
}
public function getLongUrl(): string
@ -195,4 +197,9 @@ final class ShortUrlMeta implements TitleResolutionModelInterface
{
return $this->crawlable;
}
public function forwardQuery(): bool
{
return $this->forwardQuery;
}
}

View file

@ -33,6 +33,7 @@ class ShortUrlInputFilter extends InputFilter
public const TAGS = 'tags';
public const TITLE = 'title';
public const CRAWLABLE = 'crawlable';
public const FORWARD_QUERY = 'forwardQuery';
private function __construct(array $data, bool $requireLongUrl)
{
@ -89,9 +90,10 @@ class ShortUrlInputFilter extends InputFilter
$this->add($this->createBooleanInput(self::FIND_IF_EXISTS, false));
// This cannot be defined as a boolean input because it can actually have 3 values, true, false and null.
// Defining it as boolean will make null fall back to false, which is not the desired behavior.
// These cannot be defined as a boolean inputs, because they can actually have 3 values: true, false and null.
// Defining them as boolean will make null fall back to false, which is not the desired behavior.
$this->add($this->createInput(self::VALIDATE_URL, false));
$this->add($this->createInput(self::FORWARD_QUERY, false));
$domain = $this->createInput(self::DOMAIN, false);
$domain->getValidatorChain()->attach(new Validation\HostAndPortValidator());