<?php
/*
* Author: Dominik Piekarski <code@dompie.de>
* Created at: 2020/10/13 12:23
*/
declare(strict_types=1);
namespace App\Dto;
use App\Dictionary\Content;
use App\Dictionary\SearchType;
use App\Form\Search\GlobalSearch;
use Symfony\Component\HttpFoundation\InputBag;
class SearchOptions
{
private const DEFAULT_SUGGEST_SEARCH = false;
private const DEFAULT_SEARCH_TYPE = SearchType::ALL;
private const DEFAULT_PAGE = 1;
private const DEFAULT_PER_PAGE = 9;
public const DEFAULT_REGION = SearchType::ALL;
public const DEFAULT_AGE = SearchType::ALL;
public const DEFAULT_MIN_AGE = 18;
public const DEFAULT_MAX_AGE = 127;
public const DEFAULT_ONLINE = SearchType::ALL;
public const ONLINE_ONLY = 'on';
public const ONLINE_LIVECAM = 'livecam';
public const DEFAULT_GENDER = SearchType::ALL;
public const DEFAULT_MEMBER_TYPE = SearchType::ALL;
public const MEMBER_TYPE_AMATEUR = 'amateur';
public const MEMBER_TYPE_MEMBER = 'member';
private const DEFAULT_TERM = '';
public const DEFAULT_VIDEO_RESOLUTION = 0;
public const DEFAULT_SINCE = 0;
public const DEFAULT_MIN_RATING = 0.0;
public const DEFAULT_MAX_RATING = 5.0;
public const DEFAULT_MIN_DURATION = 0;
public const DEFAULT_MAX_DURATION = 32000;
private const MAX_PER_PAGE = 200;
private const MAX_TERM_LENGTH = 200;
public const DEFAULT_MIN_IMAGES = 10;
public const DEFAULT_MAX_IMAGES = 300;
public array $options = [];
public function __construct()
{
$this->initDefaults();
}
public function setSuggestSearch(bool $do = self::DEFAULT_SUGGEST_SEARCH): self
{
$this->options['isSuggest'] = $do;
return $this;
}
public function isSuggestSearch(): bool
{
return $this->options['isSuggest'] ?? self::DEFAULT_SUGGEST_SEARCH;
}
public function getOnline(): string
{
return $this->options['online'] ?? self::DEFAULT_ONLINE;
}
public function isOnlineOnly(): bool
{
return $this->getOnline() === self::ONLINE_ONLY;
}
public function isWebcamOnly(): bool
{
return $this->getOnline() === self::ONLINE_LIVECAM;
}
public function setOnline(string $online): self
{
$this->options['online'] = $online;
return $this;
}
public function hasOnlineFilter(): bool
{
return $this->getOnline() !== self::DEFAULT_ONLINE;
}
public function setProfilePhotoOnly(string $value): self
{
$this->options['withProfilePhotoOnly'] = true;
return $this;
}
public function getProfilePhotoOnly(): bool
{
return $this->options['withProfilePhotoOnly'] ?? false;
}
public function isProfilePhotoOnly(): bool
{
return $this->getProfilePhotoOnly();
}
public function getTerm(bool $lowercase = true): string
{
$term = $this->options['term'] ?? self::DEFAULT_TERM;
if ($lowercase) {
return mb_strtolower($term);
}
return $term;
}
public function setTerm($term = ''): self
{
$this->options['term'] = mb_substr((string)$term, 0, self::MAX_TERM_LENGTH);
return $this;
}
public function getSearchType(): string
{
return $this->options['searchType'] ?? self::DEFAULT_SEARCH_TYPE;
}
public function setSearchType(string $searchType = self::DEFAULT_SEARCH_TYPE): self
{
$this->options['searchType'] = $searchType;
return $this;
}
public function getMemberType(): string
{
return $this->options['memberType'] ?? self::DEFAULT_MEMBER_TYPE;
}
public function setMemberType(string $memberType = self::DEFAULT_MEMBER_TYPE): self
{
$this->options['memberType'] = $memberType;
return $this;
}
public function hasMemberTypeFilter(): bool
{
return $this->getMemberType() !== self::DEFAULT_MEMBER_TYPE;
}
public function isAmateurOnly(): bool
{
return $this->getMemberType() === self::MEMBER_TYPE_AMATEUR;
}
public function getMemberSex(): string
{
return $this->options['memberSex'] ?? self::DEFAULT_GENDER;
}
public function setMemberSex(string $memberSex = self::DEFAULT_GENDER): self
{
$this->options['memberSex'] = $memberSex;
return $this;
}
public function hasMemberSexFilter(): bool
{
return $this->getMemberSex() !== self::DEFAULT_GENDER;
}
public function getRegion(): string
{
return $this->options['region'] ?? self::DEFAULT_REGION;
}
public function setRegion(?string $region): self
{
$this->options['region'] = $region;
return $this;
}
public function hasRegionFilter(): bool
{
return $this->getRegion() !== self::DEFAULT_REGION;
}
public function setPage(int $page): self
{
$this->options['page'] = $page;
return $this;
}
public function getPage(): int
{
return $this->options['page'] ?? self::DEFAULT_PAGE;
}
public function setPerPage(int $perPage = self::DEFAULT_PER_PAGE): self
{
$this->options['perPage'] = $perPage > self::MAX_PER_PAGE ? self::MAX_PER_PAGE : $perPage;
return $this;
}
public function getPerPage(): int
{
return $this->options['perPage'] ?? self::DEFAULT_PER_PAGE;
}
public function fromGlobalSearch(InputBag $bag): void
{
$formBlockPrefix = GlobalSearch::BLOCK_PREFIX;
if (!$bag->has($formBlockPrefix)) {
$this->initDefaults();
return;
}
$params = $bag->get($formBlockPrefix);
$searchType = self::DEFAULT_SEARCH_TYPE;
if (isset($params['searchType']) && in_array((string)$params['searchType'], [SearchType::IMAGESET, SearchType::VIDEO, SearchType::MEMBER, SearchType::ALL], true)) {
$searchType = (string)$params['searchType'];
}
$this->setPage($bag->getInt('page', self::DEFAULT_PAGE));
$this->setPerPage($bag->getInt('perPage', self::DEFAULT_PER_PAGE));
$this->setSearchType($searchType);
$this->setTerm($params['term'] ?? self::DEFAULT_TERM);
}
public function fromQuery(InputBag $bag): void
{
$params = $bag->all();
$searchType = self::DEFAULT_SEARCH_TYPE;
if (isset($params['searchType']) && in_array((string)$params['searchType'], [SearchType::IMAGESET, SearchType::VIDEO, SearchType::MEMBER, SearchType::ALL], true)) {
$searchType = (string)$params['searchType'];
}
$this->pageFromQuery($bag);
$this->setPerPage($bag->getInt('perPage', self::DEFAULT_PER_PAGE));
$this->setSearchType($searchType);
$this->setTerm($params['term'] ?? self::DEFAULT_TERM);
}
public function pageFromQuery(InputBag $bag): void
{
$this->setPage($bag->getInt('page', self::DEFAULT_PAGE));
}
public function applySorting(InputBag $bag): self
{
switch ($bag->get('o')) {
case 'newest':
$this->setOrderByNewest('desc');
break;
case 'rating':
$this->setOrderByRating('desc');
break;
case 'duration':
$this->setOrderByDuration('asc');
break;
case 'daily':
$this->setOrderByDaily();
break;
}
return $this;
}
/*
* Video resolution
*/
public function getResolution(): int
{
return $this->options['resolution'] ?? self::DEFAULT_VIDEO_RESOLUTION;
}
public function setResolution(int $resolution): self
{
$this->options['resolution'] = $resolution;
return $this;
}
public function isResolution360p(): bool
{
return $this->getResolution() === Content::VIDEO_360;
}
public function isResolution720p(): bool
{
return $this->getResolution() === Content::VIDEO_720;
}
public function isResolution1080p(): bool
{
return $this->getResolution() === Content::VIDEO_1080;
}
public function getSince(): int
{
return $this->options['since'] ?? self::DEFAULT_SINCE;
}
public function setSince(int $since): self
{
$this->options['since'] = $since;
return $this;
}
public function hasSinceFilter(): bool
{
return $this->getSince() !== self::DEFAULT_SINCE;
}
public function setMinRating(?float $rating): self
{
$this->options['minRating'] = $rating;
return $this;
}
public function getMinRating(): ?float
{
return $this->options['minRating'] ?? self::DEFAULT_MIN_RATING;
}
public function setMaxRating(?float $rating): self
{
$this->options['maxRating'] = $rating;
return $this;
}
public function getMaxRating(): ?float
{
return $this->options['maxRating'] ?? self::DEFAULT_MAX_RATING;
}
public function hasRatingFilter(): bool
{
return $this->getMinRating() !== self::DEFAULT_MIN_RATING || $this->getMaxRating() !== self::DEFAULT_MAX_RATING;
}
public function setMinAge(int $age): self
{
$this->options['minAge'] = $age < self::DEFAULT_MIN_AGE ? self::DEFAULT_MIN_AGE : $age;
return $this;
}
public function getMinAge(): int
{
if (!isset($this->options['minAge']) || $this->options['minAge'] < self::DEFAULT_MIN_AGE) {
return self::DEFAULT_MIN_AGE;
}
return $this->options['minAge'];
}
public function setMaxAge(int $age): self
{
$this->options['maxAge'] = $age > self::DEFAULT_MAX_AGE ? self::DEFAULT_MAX_AGE : $age;
return $this;
}
public function getMaxAge(): int
{
return $this->options['maxAge'] ?? self::DEFAULT_MAX_AGE;
}
public function hasAgeFilter(): bool
{
return $this->getMinAge() !== self::DEFAULT_MIN_AGE || $this->getMaxAge() !== self::DEFAULT_MAX_AGE;
}
public function setMinLength(?int $length): self
{
$this->options['minLength'] = $length;
return $this;
}
public function getMinLength(): int
{
return $this->options['minLength'] ?? self::DEFAULT_MIN_DURATION;
}
public function setMaxLength(int $length): self
{
$this->options['maxLength'] = $length > self::DEFAULT_MAX_DURATION ? self::DEFAULT_MAX_DURATION : $length;
return $this;
}
public function getMaxLength(): ?int
{
return $this->options['maxLength'] ?? self::DEFAULT_MAX_DURATION;
}
public function hasLengthFilter(): bool
{
return $this->getMinLength() !== self::DEFAULT_MIN_DURATION || $this->getMaxLength() !== self::DEFAULT_MAX_DURATION;
}
public function getMinImages(): int
{
return $this->options['minImages'] ?? self::DEFAULT_MIN_IMAGES;
}
public function setMinImages(int $minImages): self
{
$this->options['minImages'] = $minImages;
return $this;
}
public function hasImagesFilter(): bool
{
return $this->getMinImages() >= self::DEFAULT_MIN_IMAGES || $this->getMaxImages() !== self::DEFAULT_MAX_IMAGES;
}
public function getMaxImages(): int
{
return $this->options['maxImages'] ?? self::DEFAULT_MAX_IMAGES;
}
public function setMaxImages(int $maxImages): self
{
$this->options['maxImages'] = $maxImages;
return $this;
}
public function initDefaults(): self
{
$this->options = [];
$this->setTerm(self::DEFAULT_TERM);
return $this;
}
public function setOrderByNewest(?string $direction): self
{
if ($direction) {
$this->options['orderBy']['since'] = $direction === 'asc' ? 'asc' : 'desc';
}
return $this;
}
public function getOrderByNewest(): ?string
{
return $this->options['orderBy']['since'] ?? null;
}
public function setOrderByRating(?string $direction): self
{
if ($direction) {
$this->options['orderBy']['rating'] = $direction === 'asc' ? 'asc' : 'desc';
}
return $this;
}
public function getOrderByRating(): ?string
{
return $this->options['orderBy']['rating'] ?? null;
}
public function setOrderByDuration(?string $direction = 'asc'): self
{
if ($direction) {
$this->options['orderBy']['duration'] = $direction === 'desc' ? 'desc' : 'asc';
}
return $this;
}
public function getOrderByDuration(): ?string
{
return $this->options['orderBy']['duration'] ?? null;
}
public function getOrderByDefault(): bool
{
return $this->getOrderByDaily() === false &&
is_string($this->getOrderByRating()) === false &&
is_string($this->getOrderByNewest()) === false &&
is_string($this->getOrderByDuration()) === false;
}
/**
* Every day another random order
* @return $this
*/
public function setOrderByDaily(): self
{
$this->options['orderBy']['daily'] = true;
return $this;
}
public function getOrderByDaily(): bool
{
return $this->options['orderBy']['daily'] ?? false;
}
}