Next major version 2 with PHP 8.1, Symfony 6, Tabler UI, 2FA ... (#2902)

This commit is contained in:
Kevin Papst
2022-12-31 21:19:55 +01:00
committed by GitHub
parent 95e06746bd
commit 90a0fd8a22
2164 changed files with 83700 additions and 86426 deletions

View File

@@ -14,16 +14,13 @@ use App\Entity\Project;
final class ActivityFormTypeQuery extends BaseFormTypeQuery
{
/**
* @var Activity|null
*/
private $activityToIgnore;
private ?Activity $activityToIgnore = null;
/**
* @param Activity|int|array|null $activity
* @param Project|int|array|null $project
* @param Activity|array<Activity>|int|null $activity
* @param Project|array<Project>|int|null $project
*/
public function __construct($activity = null, $project = null)
public function __construct(Activity|array|int|null $activity = null, Project|array|int|null $project = null)
{
if (null !== $activity) {
if (!\is_array($activity)) {

View File

@@ -16,20 +16,16 @@ use App\Entity\Project;
*/
class ActivityQuery extends ProjectQuery
{
public const ACTIVITY_ORDER_ALLOWED = ['id', 'name', 'comment', 'customer', 'project', 'budget', 'timeBudget', 'visible'];
public const ACTIVITY_ORDER_ALLOWED = [
'name', 'description' => 'comment', 'customer', 'project', 'budget', 'timeBudget', 'visible'
];
/**
* @var array<Project|int>
* @var array<Project>
*/
private $projects = [];
/**
* @var bool
*/
private $globalsOnly = false;
/**
* @var bool
*/
private $excludeGlobals = false;
private array $projects = [];
private bool $globalsOnly = false;
private bool $excludeGlobals = false;
public function __construct()
{
@@ -42,77 +38,45 @@ class ActivityQuery extends ProjectQuery
]);
}
/**
* @return bool
*/
public function isGlobalsOnly(): bool
{
return (bool) $this->globalsOnly;
return $this->globalsOnly;
}
/**
* @param bool $globalsOnly
* @return self
*/
public function setGlobalsOnly($globalsOnly): self
public function setGlobalsOnly(bool $globalsOnly): self
{
$this->globalsOnly = (bool) $globalsOnly;
$this->globalsOnly = $globalsOnly;
return $this;
}
public function isExcludeGlobals(): bool
{
return (bool) $this->excludeGlobals;
return $this->excludeGlobals;
}
public function setExcludeGlobals(bool $excludeGlobals): self
{
$this->excludeGlobals = (bool) $excludeGlobals;
$this->excludeGlobals = $excludeGlobals;
return $this;
}
/**
* @return Project|int|null
* @deprecated since 1.9 - use getProjects() instead - will be removed with 2.0
*/
public function getProject()
{
if (\count($this->projects) > 0) {
return $this->projects[0];
}
return null;
}
/**
* @param Project|int|null $project
* @return self
* @deprecated since 1.9 - use setProjects() or addProject() instead - will be removed with 2.0
*/
public function setProject($project = null): self
{
if (null === $project) {
$this->projects = [];
} else {
$this->projects = [$project];
}
return $this;
}
/**
* @param Project|int $project
* @return self
*/
public function addProject($project): self
public function addProject(Project $project): self
{
$this->projects[] = $project;
return $this;
}
/**
* @param array<Project> $projects
* @return $this
*/
public function setProjects(array $projects): self
{
$this->projects = $projects;
@@ -120,11 +84,26 @@ class ActivityQuery extends ProjectQuery
return $this;
}
/**
* @return array<Project>
*/
public function getProjects(): array
{
return $this->projects;
}
/**
* @return array<int>
*/
public function getProjectIds(): array
{
return array_values(array_filter(array_unique(array_map(function (Project $project) {
return $project->getId();
}, $this->projects)), function ($id) {
return $id !== null;
}));
}
public function hasProjects(): bool
{
return !empty($this->projects);

View File

@@ -18,79 +18,39 @@ use App\Entity\User;
abstract class BaseFormTypeQuery
{
/**
* @var array
* @var array<Activity|int>
*/
private $activities = [];
private array $activities = [];
/**
* @var array
* @var array<Project|int>
*/
private $projects = [];
private array $projects = [];
/**
* @var array
* @var array<Customer|int>
*/
private $customers = [];
/**
* @var User
*/
private $user;
private array $customers = [];
private ?User $user = null;
/**
* @var array<Team>
*/
private $teams = [];
private array $teams = [];
/**
* @return Activity|int|null
* @deprecated since 1.9 - use getActivities() instead - will be removed with 2.0
*/
public function getActivity()
public function addActivity(Activity|int $activity): void
{
if (\count($this->activities) > 0) {
return $this->activities[0];
}
return null;
$this->activities[] = $activity;
}
/**
* @param Activity|int|null $activity
* @return self
* @deprecated since 1.9 - use setActivities() or addActivity() instead - will be removed with 2.0
* @param array<Activity|int> $activities
*/
public function setActivity($activity): self
{
if (null === $activity) {
$this->activities = [];
} else {
$this->activities = [$activity];
}
return $this;
}
/**
* @param Activity|int $activity
* @return self
*/
public function addActivity($activity): self
{
if (null !== $activity) {
$this->activities[] = $activity;
}
return $this;
}
/**
* @param Activity[]|int[] $activities
* @return self
*/
public function setActivities(array $activities): self
public function setActivities(array $activities): void
{
$this->activities = $activities;
return $this;
}
/**
* @return array<Activity|int>
*/
public function getActivities(): array
{
return $this->activities;
@@ -98,64 +58,24 @@ abstract class BaseFormTypeQuery
public function hasActivities(): bool
{
return !empty($this->activities);
return \count($this->activities) > 0;
}
/**
* @return Project|int|null
* @deprecated since 1.9 - use getProjects() instead - will be removed with 2.0
*/
public function getProject()
public function addProject(Project|int $project): void
{
if (\count($this->projects) > 0) {
return $this->projects[0];
}
return null;
$this->projects[] = $project;
}
/**
* @param Project|int|null $project
* @return self
* @deprecated since 1.9 - use addProject() instead - will be removed with 2.0
* @param array<Project|int> $projects
*/
public function setProject($project): self
{
if (null === $project) {
$this->projects = [];
} else {
$this->projects = [$project];
}
return $this;
}
/**
* @param Project|int $project
* @return self
*/
public function addProject($project): self
{
if (null !== $project) {
$this->projects[] = $project;
}
return $this;
}
/**
* @param Project[]|int[] $projects
* @return self
*/
public function setProjects(array $projects): self
public function setProjects(array $projects): void
{
$this->projects = $projects;
return $this;
}
/**
* @return array
* @return array<Project|int>
*/
public function getProjects(): array
{
@@ -164,60 +84,25 @@ abstract class BaseFormTypeQuery
public function hasProjects(): bool
{
return !empty($this->projects);
return \count($this->projects) > 0;
}
/**
* @return Customer|int|null
* @deprecated since 1.9 - use getCustomers() instead - will be removed with 2.0
* @param array<Customer|int> $customers
*/
public function getCustomer()
{
if (\count($this->customers) > 0) {
return $this->customers[0];
}
return null;
}
/**
* @param Customer|int|null $customer
* @return self
* @deprecated since 1.9 - use addCustomer() instead - will be removed with 2.0
*/
public function setCustomer($customer): self
{
if (null === $customer) {
$this->customers = [];
} else {
$this->customers = [$customer];
}
return $this;
}
/**
* @param Customer[]|int[] $customers
* @return self
*/
public function setCustomers(array $customers): self
public function setCustomers(array $customers): void
{
$this->customers = $customers;
}
return $this;
public function addCustomer(Customer|int $customer): void
{
$this->customers[] = $customer;
}
/**
* @param Customer|int $customer
* @return self
* @return array<Customer|int>
*/
public function addCustomer($customer): self
{
$this->customers[] = $customer;
return $this;
}
public function getCustomers(): array
{
return $this->customers;
@@ -225,7 +110,7 @@ abstract class BaseFormTypeQuery
public function hasCustomers(): bool
{
return !empty($this->customers);
return \count($this->customers) > 0;
}
public function getUser(): ?User
@@ -248,18 +133,15 @@ abstract class BaseFormTypeQuery
}
/**
* @param Team[] $teams
* @return self
* @param array<Team> $teams
*/
public function setTeams(array $teams): self
public function setTeams(array $teams): void
{
$this->teams = $teams;
return $this;
}
/**
* @return Team[]
* @return array<Team>
*/
public function getTeams(): array
{

View File

@@ -12,7 +12,9 @@ namespace App\Repository\Query;
use App\Entity\Bookmark;
use App\Entity\Team;
use App\Entity\User;
use App\Form\Model\DateRange;
use App\Utils\SearchTerm;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormErrorIterator;
/**
@@ -22,80 +24,33 @@ class BaseQuery
{
public const ORDER_ASC = 'ASC';
public const ORDER_DESC = 'DESC';
public const DEFAULT_PAGESIZE = 50;
/** @deprecated since 1.14 */
public const DEFAULT_PAGE = 1;
/**
* @deprecated since 1.4, will be removed with 2.0
*/
public const RESULT_TYPE_OBJECTS = 'Objects';
/**
* @deprecated since 1.4, will be removed with 2.0
*/
public const RESULT_TYPE_PAGER = 'PagerFanta';
/**
* @deprecated since 1.4, will be removed with 2.0
*/
public const RESULT_TYPE_QUERYBUILDER = 'QueryBuilder';
private $defaults = [
/** @var array<string, string|int|null|bool|array<mixed>|DateRange> */
private array $defaults = [
'page' => 1,
'pageSize' => self::DEFAULT_PAGESIZE,
'orderBy' => 'id',
'order' => self::ORDER_ASC,
'searchTerm' => null,
];
/**
* @var int
*/
private $page = 1;
/**
* @var int
*/
private $pageSize = self::DEFAULT_PAGESIZE;
/**
* @var string
*/
private $orderBy = 'id';
/**
* @var string
*/
private $order = self::ORDER_ASC;
private int $page = 1;
private int $pageSize = self::DEFAULT_PAGESIZE;
private string $orderBy = 'id';
private string $order = self::ORDER_ASC;
/**
* @var array<string, string>
*/
private $orderGroups = [];
private array $orderGroups = [];
private ?User $currentUser = null;
/**
* @var string
* @deprecated since 1.4, will be removed with 2.0
* @var array<Team>
*/
private $resultType = self::RESULT_TYPE_PAGER;
/**
* @var User
*/
private $currentUser;
/**
* @var Team[]
*/
private $teams = [];
/**
* @var SearchTerm|null
*/
private $searchTerm;
/**
* @var Bookmark|null
*/
private $bookmark;
/**
* @var string|null
*/
private $name;
/**
* @var bool
*/
private $bookmarkSearch = false;
private array $teams = [];
private ?SearchTerm $searchTerm = null;
private ?Bookmark $bookmark = null;
private ?string $name = null;
private bool $bookmarkSearch = false;
/**
* @param Team[] $teams
@@ -140,29 +95,22 @@ class BaseQuery
* @param User $user
* @return self
*/
public function setCurrentUser(User $user)
public function setCurrentUser(?User $user): self
{
$this->currentUser = $user;
return $this;
}
/**
* @return int
*/
public function getPage()
public function getPage(): int
{
return $this->page;
}
/**
* @param int $page
* @return self
*/
public function setPage($page)
public function setPage(?int $page): self
{
if ($page !== null && (int) $page > 0) {
$this->page = (int) $page;
if ($page !== null && $page > 0) {
$this->page = $page;
}
return $this;
@@ -173,14 +121,10 @@ class BaseQuery
return $this->pageSize;
}
/**
* @param int $pageSize
* @return self
*/
public function setPageSize($pageSize)
public function setPageSize(?int $pageSize): self
{
if ($pageSize !== null && (int) $pageSize > 0) {
$this->pageSize = (int) $pageSize;
if ($pageSize !== null && $pageSize > 0) {
$this->pageSize = $pageSize;
}
return $this;
@@ -226,17 +170,6 @@ class BaseQuery
return $this->orderGroups;
}
/**
* @deprecated since 1.0
* @return string
*/
public function getResultType()
{
@trigger_error('BaseQuery::getResultType() is deprecated and will be removed with 2.0', E_USER_DEPRECATED);
return $this->resultType;
}
public function hasSearchTerm(): bool
{
return null !== $this->searchTerm;
@@ -247,18 +180,14 @@ class BaseQuery
return $this->searchTerm;
}
/**
* @param SearchTerm|null $searchTerm
* @return self
*/
public function setSearchTerm(?SearchTerm $searchTerm)
public function setSearchTerm(?SearchTerm $searchTerm): self
{
$this->searchTerm = $searchTerm;
return $this;
}
protected function set($name, $value)
protected function set(string $name, mixed $value): void
{
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
@@ -267,7 +196,7 @@ class BaseQuery
return;
}
if (substr($name, -1) === 's') {
if (str_ends_with($name, 's')) {
$method = 'add' . ucfirst(substr($name, 0, \strlen($name) - 1));
if (method_exists($this, $method) && \is_array($value)) {
foreach ($value as $v) {
@@ -283,7 +212,7 @@ class BaseQuery
}
}
protected function get($name)
protected function get(string $name): mixed
{
$methods = ['get' . ucfirst($name), 'is' . ucfirst($name), 'has' . ucfirst($name)];
foreach ($methods as $method) {
@@ -295,15 +224,17 @@ class BaseQuery
if (property_exists($this, $name)) {
return $this->{$name};
}
return null;
}
/**
* You have to add ALL user facing form fields as default!
*
* @param array $defaults
* @param array<string, string|int|null|bool|array<mixed>|DateRange> $defaults
* @return self
*/
protected function setDefaults(array $defaults)
protected function setDefaults(array $defaults): self
{
$this->defaults = array_merge($this->defaults, $defaults);
foreach ($this->defaults as $key => $value) {
@@ -314,14 +245,14 @@ class BaseQuery
}
/**
* @param FormErrorIterator $errors
* @return self
* @param FormErrorIterator<FormError> $errors
* @return $this
*/
public function resetByFormError(FormErrorIterator $errors)
public function resetByFormError(FormErrorIterator $errors): self
{
foreach ($errors as $error) {
$key = $error->getOrigin()->getName();
if (\array_key_exists($key, $this->defaults)) {
$key = $error->getOrigin()?->getName();
if ($key !== null && \array_key_exists($key, $this->defaults)) {
$this->set($key, $this->defaults[$key]);
}
}
@@ -399,7 +330,7 @@ class BaseQuery
$currentValue = $this->get($filter);
if (\is_object($currentValue)) {
if ($currentValue != $expectedValue) {
if ($currentValue !== $expectedValue) {
return false;
}
} else {

View File

@@ -11,10 +11,7 @@ namespace App\Repository\Query;
trait BillableTrait
{
/**
* @var bool|null
*/
private $billable = null;
private ?bool $billable = null;
public function getBillable(): ?bool
{

View File

@@ -16,16 +16,13 @@ use App\Entity\Customer;
*/
final class CustomerFormTypeQuery extends BaseFormTypeQuery
{
/**
* @var Customer|null
*/
private $customerToIgnore;
private $allowCustomerPreselect = false;
private ?Customer $customerToIgnore = null;
private bool $allowCustomerPreselect = false;
/**
* @param Customer|int|null $customer
* @param Customer|array<Customer>|int|null $customer
*/
public function __construct($customer = null)
public function __construct(Customer|array|int|null $customer = null)
{
if (null !== $customer) {
if (!\is_array($customer)) {

View File

@@ -9,15 +9,12 @@
namespace App\Repository\Query;
/**
* Can be used for advanced queries with the: CustomerRepository
*/
class CustomerQuery extends BaseQuery implements VisibilityInterface
{
use VisibilityTrait;
public const CUSTOMER_ORDER_ALLOWED = [
'id', 'name', 'comment', 'country', 'number', 'homepage', 'email', 'mobile', 'fax',
'name', 'description' => 'comment', 'country', 'number', 'homepage', 'email', 'mobile', 'fax',
'phone', 'currency', 'address', 'contact', 'company', 'vat_id', 'budget', 'timeBudget', 'visible'
];

View File

@@ -13,18 +13,11 @@ use App\Form\Model\DateRange;
trait DateRangeTrait
{
/**
* @var DateRange
*/
protected $dateRange;
protected ?DateRange $dateRange = null;
public function getBegin(): ?\DateTime
{
if (null === $this->dateRange) {
return null;
}
return $this->dateRange->getBegin();
return $this->dateRange?->getBegin();
}
public function setBegin(\DateTime $begin): void
@@ -34,11 +27,7 @@ trait DateRangeTrait
public function getEnd(): ?\DateTime
{
if (null === $this->dateRange) {
return null;
}
return $this->dateRange->getEnd();
return $this->dateRange?->getEnd();
}
public function setEnd(\DateTime $end): void

View File

@@ -11,22 +11,16 @@ namespace App\Repository\Query;
class ExportQuery extends TimesheetQuery
{
/**
* @var string
*/
private $renderer;
/**
* @var bool
*/
private $markAsExported = false;
private ?string $renderer = null;
private bool $markAsExported = true;
public function __construct()
{
parent::__construct();
$this->setDefaults([
'order' => ExportQuery::ORDER_ASC,
'state' => ExportQuery::STATE_STOPPED,
'exported' => ExportQuery::STATE_NOT_EXPORTED,
'order' => BaseQuery::ORDER_ASC,
'state' => TimesheetQuery::STATE_STOPPED,
'exported' => TimesheetQuery::STATE_NOT_EXPORTED,
]);
}
@@ -47,8 +41,11 @@ class ExportQuery extends TimesheetQuery
return $this->markAsExported;
}
public function setMarkAsExported(bool $markAsExported): ExportQuery
public function setMarkAsExported(?bool $markAsExported): ExportQuery
{
if ($markAsExported === null) {
$markAsExported = false;
}
$this->markAsExported = $markAsExported;
return $this;

View File

@@ -30,11 +30,11 @@ class InvoiceArchiveQuery extends BaseQuery
* Filter for invoice status (by default all)
* @var string[]
*/
private $status = [];
private array $status = [];
/**
* @var Customer[]
*/
private $customers = [];
private array $customers = [];
public function __construct()
{

View File

@@ -9,31 +9,29 @@
namespace App\Repository\Query;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\InvoiceTemplate;
use App\Entity\Project;
/**
* Find items (eg timesheets) for creating a new invoice.
* Find items (e.g. timesheets) for creating a new invoice.
*/
class InvoiceQuery extends TimesheetQuery
{
/**
* @var InvoiceTemplate
*/
private $template;
/**
* @var bool
*/
private $markAsExported = true;
private ?InvoiceTemplate $template = null;
private ?\DateTime $invoiceDate = null;
private bool $allowTemplateOverwrite = true;
public function __construct()
{
parent::__construct();
$this->setDefaults([
'order' => InvoiceQuery::ORDER_ASC,
'exported' => InvoiceQuery::STATE_NOT_EXPORTED,
'order' => self::ORDER_ASC,
'exported' => self::STATE_NOT_EXPORTED,
'state' => self::STATE_STOPPED,
'billable' => true,
'markAsExported' => true,
'invoiceDate' => null,
]);
}
@@ -49,15 +47,68 @@ class InvoiceQuery extends TimesheetQuery
return $this;
}
public function isMarkAsExported(): bool
/**
* Helper method, because many templates access {{ model.query.customer }} directly.
*
* @return Customer|null
*/
public function getCustomer(): ?Customer
{
return $this->markAsExported;
$customers = $this->getCustomers();
if (\count($customers) === 1) {
return $customers[0];
}
return null;
}
public function setMarkAsExported(bool $markAsExported): InvoiceQuery
/**
* Helper method, because many templates access {{ model.query.project }} directly.
*
* @return Project|null
*/
public function getProject(): ?Project
{
$this->markAsExported = $markAsExported;
$projects = $this->getProjects();
if (\count($projects) === 1) {
return $projects[0];
}
return $this;
return null;
}
/**
* Helper method, because many templates access {{ model.query.activity }} directly.
*
* @return Activity|null
*/
public function getActivity(): ?Activity
{
$activities = $this->getActivities();
if (\count($activities) === 1) {
return $activities[0];
}
return null;
}
public function getInvoiceDate(): ?\DateTime
{
return $this->invoiceDate;
}
public function setInvoiceDate(?\DateTime $invoiceDate): void
{
$this->invoiceDate = $invoiceDate;
}
public function isAllowTemplateOverwrite(): bool
{
return $this->allowTemplateOverwrite;
}
public function setAllowTemplateOverwrite(bool $allowTemplateOverwrite): void
{
$this->allowTemplateOverwrite = $allowTemplateOverwrite;
}
}

View File

@@ -14,26 +14,17 @@ use App\Entity\Project;
final class ProjectFormTypeQuery extends BaseFormTypeQuery
{
/**
* @var \DateTime|null
*/
private $projectStart;
/**
* @var \DateTime|null
*/
private $projectEnd;
/**
* @var Project|null
*/
private $projectToIgnore;
private $ignoreDate = false;
private $withCustomer = false;
private ?\DateTime $projectStart = null;
private ?\DateTime $projectEnd = null;
private ?Project $projectToIgnore = null;
private bool $ignoreDate = false;
private bool $withCustomer = false;
/**
* @param Project|int|null|array<int>|array<Project> $project
* @param Customer|int|null|array<int>|array<Customer> $customer
* @param Project|array<Project>|int|null $project
* @param Customer|array<Customer>|int|null $customer
*/
public function __construct($project = null, $customer = null)
public function __construct(Project|array|int|null $project = null, Customer|array|int|null $customer = null)
{
if (null !== $project) {
if (!\is_array($project)) {
@@ -49,13 +40,12 @@ final class ProjectFormTypeQuery extends BaseFormTypeQuery
$this->setCustomers($customer);
}
$this->projectStart = $this->projectEnd = new \DateTime();
$this->projectStart = new \DateTime();
$this->projectEnd = clone $this->projectStart;
}
/**
* Whether customers should be joined
*
* @return bool
*/
public function withCustomer(): bool
{
@@ -64,17 +54,12 @@ final class ProjectFormTypeQuery extends BaseFormTypeQuery
/**
* Directly join the customer
*
* @param bool $withCustomer
*/
public function setWithCustomer(bool $withCustomer): void
{
$this->withCustomer = $withCustomer;
}
/**
* @return Project|null
*/
public function getProjectToIgnore(): ?Project
{
return $this->projectToIgnore;

View File

@@ -11,33 +11,22 @@ namespace App\Repository\Query;
use App\Entity\Customer;
/**
* Can be used for advanced queries with the: ProjectRepository
*/
class ProjectQuery extends BaseQuery implements VisibilityInterface
{
use VisibilityTrait;
public const PROJECT_ORDER_ALLOWED = [
'id', 'name', 'comment', 'customer', 'orderNumber', 'orderDate', 'project_start', 'project_end', 'budget', 'timeBudget', 'visible'
'name', 'description' => 'comment', 'customer', 'orderNumber', 'orderDate',
'project_start', 'project_end', 'budget', 'timeBudget', 'visible'
];
/**
* @var array<Customer|int>
* @var array<Customer>
*/
private $customers = [];
/**
* @var \DateTime|null
*/
private $projectStart;
/**
* @var \DateTime|null
*/
private $projectEnd;
/**
* @var null|bool
*/
private $globalActivities = null;
private array $customers = [];
private ?\DateTime $projectStart = null;
private ?\DateTime $projectEnd = null;
private ?bool $globalActivities = null;
public function __construct()
{
@@ -51,46 +40,17 @@ class ProjectQuery extends BaseQuery implements VisibilityInterface
]);
}
/**
* @return Customer|int|null
* @deprecated since 1.9 - use getCustomers() instead - will be removed with 2.0
*/
public function getCustomer()
{
if (\count($this->customers) > 0) {
return $this->customers[0];
}
return null;
}
/**
* @param Customer|int|null $customer
* @return $this
* @deprecated since 1.9 - use setCustomers() or addCustomer() instead - will be removed with 2.0
*/
public function setCustomer($customer = null)
{
if (null === $customer) {
$this->customers = [];
} else {
$this->customers = [$customer];
}
return $this;
}
/**
* @param Customer|int $customer
* @return $this
*/
public function addCustomer($customer)
public function addCustomer(Customer $customer): self
{
$this->customers[] = $customer;
return $this;
}
/**
* @param array<Customer> $customers
* @return $this
*/
public function setCustomers(array $customers): self
{
$this->customers = $customers;
@@ -98,11 +58,26 @@ class ProjectQuery extends BaseQuery implements VisibilityInterface
return $this;
}
/**
* @return array<Customer>
*/
public function getCustomers(): array
{
return $this->customers;
}
/**
* @return array<int>
*/
public function getCustomerIds(): array
{
return array_filter(array_values(array_unique(array_map(function (Customer $customer) {
return $customer->getId();
}, $this->customers))), function ($id) {
return $id !== null;
});
}
public function hasCustomers(): bool
{
return !empty($this->customers);

View File

@@ -11,7 +11,7 @@ namespace App\Repository\Query;
class TagQuery extends BaseQuery
{
public const TAG_ORDER_ALLOWED = ['id', 'name', 'amount'];
public const TAG_ORDER_ALLOWED = ['name', 'amount'];
public function __construct()
{

View File

@@ -13,12 +13,12 @@ use App\Entity\User;
class TeamQuery extends BaseQuery
{
public const TEAM_ORDER_ALLOWED = ['id', 'name'];
public const TEAM_ORDER_ALLOWED = ['name'];
/**
* @var User[]
*/
private $users = [];
private array $users = [];
public function __construct()
{

View File

@@ -14,9 +14,6 @@ use App\Entity\Tag;
use App\Entity\User;
use App\Form\Model\DateRange;
/**
* Can be used for advanced timesheet repository queries.
*/
class TimesheetQuery extends ActivityQuery implements BillableInterface
{
use BillableTrait;
@@ -30,38 +27,21 @@ class TimesheetQuery extends ActivityQuery implements BillableInterface
public const TIMESHEET_ORDER_ALLOWED = ['begin', 'end', 'duration', 'rate', 'hourlyRate', 'customer', 'project', 'activity', 'description'];
private ?User $timesheetUser = null;
/** @var array<Activity> */
private array $activities = [];
private int $state = self::STATE_ALL;
private int $exported = self::STATE_ALL;
private ?int $maxResults = null;
private ?\DateTime $modifiedAfter = null;
/**
* @var User|null
* @var array<Tag>
*/
protected $timesheetUser;
private array $tags = [];
/**
* @var array
* @var array<User>
*/
private $activities = [];
/**
* @var int
*/
protected $state = self::STATE_ALL;
/**
* @var int
*/
protected $exported = self::STATE_ALL;
/**
* @var \DateTime|null
*/
private $modifiedAfter;
/**
* @var iterable
*/
protected $tags = [];
/**
* @var User[]
*/
private $users = [];
/**
* @var int|null
*/
private $maxResults;
private array $users = [];
public function __construct(bool $resetTimes = true)
{
@@ -114,67 +94,42 @@ class TimesheetQuery extends ActivityQuery implements BillableInterface
}
/**
* Limit the data exclusively to the user (eg. users own timesheets).
*
* @return User|int|null
* Limit the data exclusively to the user.
*/
public function getUser()
public function getUser(): ?User
{
return $this->timesheetUser;
}
/**
* Limit the data exclusively to the user (eg. users own timesheets).
*
* @param User|int|null $user
* @return TimesheetQuery
* Limit the data exclusively to the user.
*/
public function setUser($user = null)
public function setUser(?User $user): void
{
$this->timesheetUser = $user;
return $this;
}
/**
* @return Activity|int|null
* @deprecated since 1.9 - use getActivities() instead - will be removed with 2.0
* @return array<int>
*/
public function getActivity()
public function getActivityIds(): array
{
if (\count($this->activities) > 0) {
return $this->activities[0];
}
return null;
return array_values(array_filter(array_unique(array_map(function (Activity $activity) {
return $activity->getId();
}, $this->activities)), function ($id) {
return $id !== null;
}));
}
/**
* @return array<Activity>
*/
public function getActivities(): array
{
return $this->activities;
}
/**
* @param Activity|int|null $activity
* @return $this
* @deprecated since 1.9 - use setActivities() or addActivity() instead - will be removed with 2.0
*/
public function setActivity($activity)
{
if (null === $activity) {
$this->activities = [];
} else {
$this->activities = [$activity];
}
return $this;
}
/**
* @param Activity|int $activity
* @return $this
*/
public function addActivity($activity): TimesheetQuery
public function addActivity(Activity $activity): TimesheetQuery
{
$this->activities[] = $activity;
@@ -182,8 +137,7 @@ class TimesheetQuery extends ActivityQuery implements BillableInterface
}
/**
* @param Activity[]|int[] $activities
* @return $this
* @param array<Activity> $activities
*/
public function setActivities(array $activities): TimesheetQuery
{
@@ -214,7 +168,6 @@ class TimesheetQuery extends ActivityQuery implements BillableInterface
public function setState(int $state): TimesheetQuery
{
$state = (int) $state;
if (\in_array($state, [self::STATE_ALL, self::STATE_RUNNING, self::STATE_STOPPED], true)) {
$this->state = $state;
}
@@ -237,39 +190,33 @@ class TimesheetQuery extends ActivityQuery implements BillableInterface
return $this->exported === self::STATE_NOT_EXPORTED;
}
public function setExported(int $exported): TimesheetQuery
public function setExported(int $exported): void
{
$exported = (int) $exported;
if (\in_array($exported, [self::STATE_ALL, self::STATE_EXPORTED, self::STATE_NOT_EXPORTED], true)) {
$this->exported = $exported;
if (!\in_array($exported, [self::STATE_ALL, self::STATE_EXPORTED, self::STATE_NOT_EXPORTED], true)) {
throw new \InvalidArgumentException('Unknown export state given');
}
return $this;
$this->exported = $exported;
}
public function getTags(bool $allowUnknown = false): iterable
/**
* @return array<Tag>
*/
public function getTags(): array
{
if (empty($this->tags)) {
return [];
}
$result = [];
foreach ($this->tags as $tag) {
if (!$allowUnknown && $tag instanceof Tag && null === $tag->getId()) {
continue;
}
$result[] = $tag;
}
return $result;
return array_values($this->tags);
}
public function setTags(iterable $tags): TimesheetQuery
public function removeTag(Tag $tag): void
{
$this->tags = $tags;
if (isset($this->tags[$tag->getId()])) {
unset($this->tags[$tag->getId()]);
}
}
return $this;
public function addTag(Tag $tag): void
{
$this->tags[$tag->getId()] = $tag;
}
public function getModifiedAfter(): ?\DateTime

View File

@@ -21,23 +21,20 @@ final class UserFormTypeQuery extends BaseFormTypeQuery
/**
* @var User[]
*/
private $includeUsers = [];
private array $includeUsers = [];
/**
* @var User[]
*/
private $ignoredUsers = [];
private array $ignoredUsers = [];
/**
* Sets a list of users which must be included in the result always.
*
* @param array $users
* @return UserFormTypeQuery
* @param array<User> $users
*/
public function setUsersAlwaysIncluded(array $users): UserFormTypeQuery
public function setUsersAlwaysIncluded(array $users): void
{
$this->includeUsers = $users;
return $this;
}
/**

View File

@@ -18,23 +18,22 @@ class UserQuery extends BaseQuery implements VisibilityInterface
{
use VisibilityTrait;
public const USER_ORDER_ALLOWED = ['id', 'alias', 'username', 'title', 'email'];
public const USER_ORDER_ALLOWED = ['alias', 'user', 'username', 'title', 'email'];
/**
* @var string|null
*/
private $role;
private ?string $role = null;
/**
* @var Team[]
*/
private $searchTeams = [];
private array $searchTeams = [];
private ?bool $systemAccount = null;
public function __construct()
{
$this->setDefaults([
'orderBy' => 'username',
'orderBy' => 'user',
'searchTeams' => [],
'visibility' => VisibilityInterface::SHOW_VISIBLE,
'systemAccount' => null,
]);
}
@@ -65,4 +64,14 @@ class UserQuery extends BaseQuery implements VisibilityInterface
return $this;
}
public function getSystemAccount(): ?bool
{
return $this->systemAccount;
}
public function setSystemAccount(?bool $systemAccount): void
{
$this->systemAccount = $systemAccount;
}
}

View File

@@ -23,9 +23,5 @@ interface VisibilityInterface
public function getVisibility(): int;
/**
* @param int $visibility
* @return mixed
*/
public function setVisibility($visibility);
public function setVisibility(int $visibility): void;
}

View File

@@ -1,20 +0,0 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Repository\Query;
/**
* Query class for Repositories with a visibility field.
*
* @deprecated since 1.7, will be removed with 2.0
*/
class VisibilityQuery extends BaseQuery implements VisibilityInterface
{
use VisibilityTrait;
}

View File

@@ -11,24 +11,19 @@ namespace App\Repository\Query;
trait VisibilityTrait
{
/**
* @var int
*/
private $visibility = VisibilityInterface::SHOW_VISIBLE;
private int $visibility = VisibilityInterface::SHOW_VISIBLE;
public function getVisibility(): int
{
return $this->visibility;
}
public function setVisibility($visibility)
public function setVisibility(int $visibility): void
{
$visibility = (int) $visibility;
if (\in_array($visibility, VisibilityInterface::ALLOWED_VISIBILITY_STATES, true)) {
$this->visibility = $visibility;
if (!\in_array($visibility, VisibilityInterface::ALLOWED_VISIBILITY_STATES, true)) {
throw new \InvalidArgumentException('Unknown visibility given');
}
return $this;
$this->visibility = $visibility;
}
public function isShowHidden(): bool