Files
kimai2/src/Entity/MetaTableTypeTrait.php
Kevin Papst 5f4b6d3cfa Release 2.6.0 (#4472)
- Added: calendar entry title combination for customer, project and activity
- Added: show not_invoiced and not_exported data in detail screens
- Added: force logout if user is disabled
- Added: reduced amount of database queries on several screens
- Fixed: open-close status on work-contract screen for users without configuration
- Fixed: failsafe order/orderBy in query if manually manipulated to be null
- Fixed: unify statistic calculation (not_invoiced and not_exported) across screens
- Tech: bump packages
- Tech: Symfony 6.4
2023-12-17 16:19:50 +01:00

278 lines
7.0 KiB
PHP

<?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\Entity;
use App\Form\Type\YesNoType;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints as Assert;
trait MetaTableTypeTrait
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(name: 'id', type: 'integer')]
#[Serializer\Exclude]
private ?int $id = null;
/**
* Name of the meta (custom) field
*/
#[ORM\Column(name: 'name', type: 'string', length: 50, nullable: false)]
#[Assert\NotNull]
#[Assert\Length(min: 2, max: 50)]
#[Serializer\Expose]
#[Serializer\Groups(['Default'])]
private ?string $name = null;
/**
* Value of the meta (custom) field
*/
#[ORM\Column(name: 'value', type: 'text', length: 65535, nullable: true)]
#[Assert\Length(max: 65535)]
#[Serializer\Expose]
#[Serializer\Groups(['Default'])]
private ?string $value = null;
#[ORM\Column(name: 'visible', type: 'boolean', nullable: false, options: ['default' => false])]
#[Assert\NotNull]
private bool $visible = false;
private ?string $label = null;
private ?string $type = null;
private bool $required = false;
/**
* @var Constraint[]
*/
private array $constraints = [];
/**
* An array of options for the form element
* @var array<string, mixed>
*/
private array $options = [];
private int $order = 0;
/**
* Used for data conversion during form transformation.
*
* ATTENTION: This field can be used to temporary hold data in another format (e.g. array) during form transformation.
* TODO unclear when "array" should happen. the above statement is old and maybe we can remove the "mixed” type
*/
private mixed $data = null;
private bool $updated = false;
public function getName(): ?string
{
if (null === $this->name) {
return null;
}
return strtolower($this->name);
}
public function setName(string $name): MetaTableTypeInterface
{
$this->name = $name;
return $this;
}
public function getValue(): mixed
{
$value = $this->updated ? $this->data : $this->value;
if ($value === null) {
return null;
}
return match ($this->type) {
YesNoType::class, CheckboxType::class => (\is_string($value) || \is_int($value)) ? (bool) $value : $value,
IntegerType::class => (\is_string($value) || \is_int($value)) ? (int) $value : $value,
NumberType::class => (\is_string($value) || \is_float($value)) ? (float) $value : $value,
default => $value
};
}
/**
* Value will not be serialized before its stored, so it should be a primitive/scalar type.
*/
public function setValue(mixed $value): MetaTableTypeInterface
{
$this->data = $value;
$this->updated = true;
// unchecked checkboxes / false bool would save an empty string in the database
// those cannot be searched in the database
if (null !== $value) {
switch ($this->type) {
case YesNoType::class:
case CheckboxType::class:
if (!\is_int($value) && !\is_bool($value) && !\is_string($value)) {
throw new \InvalidArgumentException('Failed converting meta-field bool value');
} else {
$value = (string) $value;
}
}
}
if ($value === null) {
$this->value = $value;
} elseif (\is_scalar($value)) {
$this->value = (string) $value;
}
return $this;
}
public function setConstraints(array $constraints): MetaTableTypeInterface
{
$this->constraints = [];
foreach ($constraints as $constraint) {
$this->addConstraint($constraint);
}
return $this;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): MetaTableTypeInterface
{
$this->type = $type;
return $this;
}
public function addConstraint(Constraint $constraint): MetaTableTypeInterface
{
$this->constraints[] = $constraint;
return $this;
}
/**
* @return Constraint[]
*/
public function getConstraints(): array
{
return $this->constraints;
}
public function isRequired(): bool
{
return $this->required;
}
public function setIsRequired(bool $isRequired): MetaTableTypeInterface
{
$this->required = $isRequired;
return $this;
}
public function isVisible(): bool
{
return $this->visible;
}
public function setIsVisible(bool $visible): MetaTableTypeInterface
{
$this->visible = $visible;
return $this;
}
public function merge(MetaTableTypeInterface $meta): MetaTableTypeInterface
{
$this
->setConstraints($meta->getConstraints())
->setIsRequired($meta->isRequired())
->setIsVisible($meta->isVisible())
->setOptions($meta->getOptions())
->setOrder($meta->getOrder())
;
if ($meta->getLabel() !== null) {
$this->setLabel($meta->getLabel());
}
if ($meta->getType() !== null) {
$this->setType($meta->getType());
}
return $this;
}
public function getLabel(): ?string
{
if (null === $this->label) {
return $this->name;
}
return $this->label;
}
public function setLabel(?string $label): MetaTableTypeInterface
{
$this->label = $label;
return $this;
}
/**
* @param array<string, mixed> $options
* @return MetaTableTypeInterface
*/
public function setOptions(array $options): MetaTableTypeInterface
{
$this->options = $options;
return $this;
}
/**
* @return array<string, mixed>
*/
public function getOptions(): array
{
return $this->options;
}
public function getOrder(): int
{
return $this->order;
}
public function setOrder(int $order): MetaTableTypeInterface
{
$this->order = $order;
return $this;
}
public function __clone()
{
if ($this->id) {
$this->id = null;
}
}
/**
* Whether this field is defined by a plugin or just a value stored in the database.
*/
public function isDefined(): bool
{
return $this->type !== null;
}
}