API improvements (#1826)
This commit is contained in:
@@ -41,6 +41,11 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
*/
|
||||
class ActivityController extends BaseApiController
|
||||
{
|
||||
public const GROUPS_ENTITY = ['Default', 'Entity', 'Activity', 'Activity_Entity'];
|
||||
public const GROUPS_FORM = ['Default', 'Entity', 'Activity'];
|
||||
public const GROUPS_COLLECTION = ['Default', 'Collection', 'Activity'];
|
||||
public const GROUPS_RATE = ['Default', 'Entity', 'Activity_Rate'];
|
||||
|
||||
/**
|
||||
* @var ActivityRepository
|
||||
*/
|
||||
@@ -132,7 +137,7 @@ class ActivityController extends BaseApiController
|
||||
|
||||
$data = $this->repository->getActivitiesForQuery($query);
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Collection', 'Activity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -165,7 +170,7 @@ class ActivityController extends BaseApiController
|
||||
}
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -212,13 +217,13 @@ class ActivityController extends BaseApiController
|
||||
$this->repository->saveActivity($activity);
|
||||
|
||||
$view = new View($activity, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
$view = new View($form);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -275,7 +280,7 @@ class ActivityController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -283,7 +288,7 @@ class ActivityController extends BaseApiController
|
||||
$this->repository->saveActivity($activity);
|
||||
|
||||
$view = new View($activity, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -336,7 +341,7 @@ class ActivityController extends BaseApiController
|
||||
$this->repository->saveActivity($activity);
|
||||
|
||||
$view = new View($activity, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -379,7 +384,7 @@ class ActivityController extends BaseApiController
|
||||
$rates = $this->activityRateRepository->getRatesForActivity($activity);
|
||||
|
||||
$view = new View($rates, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'ActivityRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -490,7 +495,7 @@ class ActivityController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'ActivityRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -498,7 +503,7 @@ class ActivityController extends BaseApiController
|
||||
$this->activityRateRepository->saveRate($rate);
|
||||
|
||||
$view = new View($rate, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'ActivityRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\API;
|
||||
|
||||
use App\API\Model\I18n;
|
||||
use App\API\Model\I18nConfig;
|
||||
use App\API\Model\TimesheetConfig;
|
||||
use App\Configuration\LanguageFormattings;
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
@@ -19,6 +19,7 @@ use App\Entity\User;
|
||||
use FOS\RestBundle\Controller\Annotations as Rest;
|
||||
use FOS\RestBundle\View\View;
|
||||
use FOS\RestBundle\View\ViewHandlerInterface;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Swagger\Annotations as SWG;
|
||||
@@ -44,11 +45,6 @@ final class ConfigurationController extends BaseApiController
|
||||
*/
|
||||
private $timesheetConfiguration;
|
||||
|
||||
/**
|
||||
* @param ViewHandlerInterface $viewHandler
|
||||
* @param LanguageFormattings $formats
|
||||
* @param TimesheetConfiguration $timesheetConfiguration
|
||||
*/
|
||||
public function __construct(ViewHandlerInterface $viewHandler, LanguageFormattings $formats, TimesheetConfiguration $timesheetConfiguration)
|
||||
{
|
||||
$this->viewHandler = $viewHandler;
|
||||
@@ -62,7 +58,7 @@ final class ConfigurationController extends BaseApiController
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Returns the locale specific configurations for this user",
|
||||
* @SWG\Schema(ref="#/definitions/I18nConfig")
|
||||
* @SWG\Schema(ref=@Model(type=I18nConfig::class))
|
||||
* )
|
||||
*
|
||||
* @Rest\Get(path="/config/i18n")
|
||||
@@ -76,7 +72,7 @@ final class ConfigurationController extends BaseApiController
|
||||
$user = $this->getUser();
|
||||
$locale = $user->getLocale();
|
||||
|
||||
$model = new I18n();
|
||||
$model = new I18nConfig();
|
||||
$model
|
||||
->setFormDateTime($this->formats->getDateTimeTypeFormat($locale))
|
||||
->setFormDate($this->formats->getDateTypeFormat($locale))
|
||||
@@ -99,7 +95,7 @@ final class ConfigurationController extends BaseApiController
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Returns the instance specific timesheet configuration",
|
||||
* @SWG\Schema(ref="#/definitions/TimesheetConfig")
|
||||
* @SWG\Schema(ref=@Model(type=TimesheetConfig::class))
|
||||
* )
|
||||
*
|
||||
* @Rest\Get(path="/config/timesheet")
|
||||
|
||||
@@ -42,6 +42,11 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
*/
|
||||
class CustomerController extends BaseApiController
|
||||
{
|
||||
public const GROUPS_ENTITY = ['Default', 'Entity', 'Customer', 'Customer_Entity'];
|
||||
public const GROUPS_FORM = ['Default', 'Entity', 'Customer'];
|
||||
public const GROUPS_COLLECTION = ['Default', 'Collection', 'Customer'];
|
||||
public const GROUPS_RATE = ['Default', 'Entity', 'Customer_Rate'];
|
||||
|
||||
/**
|
||||
* @var CustomerRepository
|
||||
*/
|
||||
@@ -112,7 +117,7 @@ class CustomerController extends BaseApiController
|
||||
|
||||
$data = $this->repository->getCustomersForQuery($query);
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Collection', 'Customer']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -138,7 +143,7 @@ class CustomerController extends BaseApiController
|
||||
}
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -185,13 +190,13 @@ class CustomerController extends BaseApiController
|
||||
$this->repository->saveCustomer($customer);
|
||||
|
||||
$view = new View($customer, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
$view = new View($form);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -248,7 +253,7 @@ class CustomerController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -256,7 +261,7 @@ class CustomerController extends BaseApiController
|
||||
$this->repository->saveCustomer($customer);
|
||||
|
||||
$view = new View($customer, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -309,7 +314,7 @@ class CustomerController extends BaseApiController
|
||||
$this->repository->saveCustomer($customer);
|
||||
|
||||
$view = new View($customer, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -352,7 +357,7 @@ class CustomerController extends BaseApiController
|
||||
$rates = $this->customerRateRepository->getRatesForCustomer($customer);
|
||||
|
||||
$view = new View($rates, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'CustomerRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -463,7 +468,7 @@ class CustomerController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'CustomerRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -471,7 +476,7 @@ class CustomerController extends BaseApiController
|
||||
$this->customerRateRepository->saveRate($rate);
|
||||
|
||||
$view = new View($rate, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'CustomerRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
@@ -11,177 +11,127 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\API\Model;
|
||||
|
||||
final class I18n
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
final class I18nConfig
|
||||
{
|
||||
/**
|
||||
* Format used for 'begin' and 'end'
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $formDateTime = '';
|
||||
/**
|
||||
* Format used for toolbar queries
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $formDate = '';
|
||||
/**
|
||||
* Format used to display date-time values (see PHP function date_format)
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $dateTime = '';
|
||||
/**
|
||||
* Format used to display date values (see PHP function date_format)
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $date = '';
|
||||
/**
|
||||
* Format used to display times (see PHP function date_format)
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $time = '';
|
||||
/**
|
||||
* Format used to display durations (replace: %h with hours, %m with minutes, %s with seconds)
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $duration = '';
|
||||
/**
|
||||
* Whether a twenty-four hour format is used (true) or 12-hours AM/PM format (false)
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="boolean")
|
||||
*/
|
||||
private $is24hours = true;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFormDateTime(): string
|
||||
{
|
||||
return $this->formDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $formDateTime
|
||||
* @return I18n
|
||||
*/
|
||||
public function setFormDateTime(string $formDateTime)
|
||||
public function setFormDateTime(string $formDateTime): I18nConfig
|
||||
{
|
||||
$this->formDateTime = $formDateTime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFormDate(): string
|
||||
{
|
||||
return $this->formDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $formDate
|
||||
* @return I18n
|
||||
*/
|
||||
public function setFormDate(string $formDate)
|
||||
public function setFormDate(string $formDate): I18nConfig
|
||||
{
|
||||
$this->formDate = $formDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTime(): string
|
||||
{
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dateTime
|
||||
* @return I18n
|
||||
*/
|
||||
public function setDateTime(string $dateTime)
|
||||
public function setDateTime(string $dateTime): I18nConfig
|
||||
{
|
||||
$this->dateTime = $dateTime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDate(): string
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $date
|
||||
* @return I18n
|
||||
*/
|
||||
public function setDate(string $date)
|
||||
public function setDate(string $date): I18nConfig
|
||||
{
|
||||
$this->date = $date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDuration(): string
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $duration
|
||||
* @return I18n
|
||||
*/
|
||||
public function setDuration(string $duration)
|
||||
public function setDuration(string $duration): I18nConfig
|
||||
{
|
||||
$this->duration = $duration;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTime(): string
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $time
|
||||
* @return I18n
|
||||
*/
|
||||
public function setTime(string $time)
|
||||
public function setTime(string $time): I18nConfig
|
||||
{
|
||||
$this->time = $time;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isIs24hours(): bool
|
||||
{
|
||||
return $this->is24hours;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $is24hours
|
||||
* @return I18n
|
||||
*/
|
||||
public function setIs24hours(bool $is24hours)
|
||||
public function setIs24hours(bool $is24hours): I18nConfig
|
||||
{
|
||||
$this->is24hours = $is24hours;
|
||||
|
||||
@@ -11,53 +11,74 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\API\Model;
|
||||
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("none")
|
||||
*/
|
||||
final class TimesheetConfig
|
||||
{
|
||||
/**
|
||||
* See here: https://www.kimai.org/documentation/timesheet.html#tracking-modes
|
||||
* The time-tracking mode, see also: https://www.kimai.org/documentation/timesheet.html#tracking-modes
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $trackingMode = 'default';
|
||||
/**
|
||||
* Default begin datetime in PHP format
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
private $defaultBeginTime = 'now';
|
||||
/**
|
||||
* How many running timesheets a user is allowed to have at the same time
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="integer")
|
||||
*/
|
||||
private $activeEntriesHardLimit = 1;
|
||||
/**
|
||||
* How many running timesheets a user is allowed before a warning is shown
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="integer")
|
||||
*/
|
||||
private $activeEntriesSoftLimit = 1;
|
||||
/**
|
||||
* Whether entries for future times are allowed
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="boolean")
|
||||
*/
|
||||
private $isAllowFutureTimes = true;
|
||||
/**
|
||||
* Whether overlapping entries are allowed
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="boolean")
|
||||
*/
|
||||
private $isAllowOverlapping = true;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTrackingMode(): string
|
||||
{
|
||||
return $this->trackingMode;
|
||||
}
|
||||
|
||||
public function setTrackingMode(string $trackingMode): TimesheetConfig
|
||||
{
|
||||
$this->trackingMode = $trackingMode;
|
||||
@@ -65,11 +86,6 @@ final class TimesheetConfig
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefaultBeginTime(): string
|
||||
{
|
||||
return $this->defaultBeginTime;
|
||||
}
|
||||
|
||||
public function setDefaultBeginTime(string $defaultBeginTime): TimesheetConfig
|
||||
{
|
||||
$this->defaultBeginTime = $defaultBeginTime;
|
||||
@@ -77,11 +93,6 @@ final class TimesheetConfig
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getActiveEntriesHardLimit(): int
|
||||
{
|
||||
return $this->activeEntriesHardLimit;
|
||||
}
|
||||
|
||||
public function setActiveEntriesHardLimit(int $activeEntriesHardLimit): TimesheetConfig
|
||||
{
|
||||
$this->activeEntriesHardLimit = $activeEntriesHardLimit;
|
||||
@@ -89,11 +100,6 @@ final class TimesheetConfig
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getActiveEntriesSoftLimit(): int
|
||||
{
|
||||
return $this->activeEntriesSoftLimit;
|
||||
}
|
||||
|
||||
public function setActiveEntriesSoftLimit(int $activeEntriesSoftLimit): TimesheetConfig
|
||||
{
|
||||
$this->activeEntriesSoftLimit = $activeEntriesSoftLimit;
|
||||
@@ -101,11 +107,6 @@ final class TimesheetConfig
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAllowFutureTimes(): bool
|
||||
{
|
||||
return $this->isAllowFutureTimes;
|
||||
}
|
||||
|
||||
public function setIsAllowFutureTimes(bool $isAllowFutureTimes): TimesheetConfig
|
||||
{
|
||||
$this->isAllowFutureTimes = $isAllowFutureTimes;
|
||||
@@ -113,11 +114,6 @@ final class TimesheetConfig
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAllowOverlapping(): bool
|
||||
{
|
||||
return $this->isAllowOverlapping;
|
||||
}
|
||||
|
||||
public function setIsAllowOverlapping(bool $isAllowOverlapping): TimesheetConfig
|
||||
{
|
||||
$this->isAllowOverlapping = $isAllowOverlapping;
|
||||
|
||||
@@ -12,37 +12,61 @@ declare(strict_types=1);
|
||||
namespace App\API\Model;
|
||||
|
||||
use App\Constants;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Version
|
||||
{
|
||||
/**
|
||||
* Kimai Version, eg. "1.9"
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
protected $version = Constants::VERSION;
|
||||
/**
|
||||
* Candidate: either "prod" or "dev"
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
protected $candidate = Constants::STATUS;
|
||||
/**
|
||||
* Full version including status, eg: "1.9-prod"
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
protected $semver = Constants::VERSION . '-' . Constants::STATUS;
|
||||
/**
|
||||
* The version name
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
protected $name = Constants::NAME;
|
||||
/**
|
||||
* A full copyright notice
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="string")
|
||||
*/
|
||||
protected $copyright = Constants::SOFTWARE . ' - ' . Constants::VERSION . ' ' . Constants::STATUS . ' (' . Constants::NAME . ') by Kevin Papst and contributors.';
|
||||
}
|
||||
|
||||
@@ -45,6 +45,11 @@ use Symfony\Component\Validator\Constraints;
|
||||
*/
|
||||
class ProjectController extends BaseApiController
|
||||
{
|
||||
public const GROUPS_ENTITY = ['Default', 'Entity', 'Project', 'Project_Entity'];
|
||||
public const GROUPS_FORM = ['Default', 'Entity', 'Project'];
|
||||
public const GROUPS_COLLECTION = ['Default', 'Collection', 'Project'];
|
||||
public const GROUPS_RATE = ['Default', 'Entity', 'Project_Rate'];
|
||||
|
||||
/**
|
||||
* @var ProjectRepository
|
||||
*/
|
||||
@@ -159,7 +164,7 @@ class ProjectController extends BaseApiController
|
||||
|
||||
$data = $this->repository->getProjectsForQuery($query);
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Collection', 'Project']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -185,7 +190,7 @@ class ProjectController extends BaseApiController
|
||||
}
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Project']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -233,13 +238,13 @@ class ProjectController extends BaseApiController
|
||||
$this->repository->saveProject($project);
|
||||
|
||||
$view = new View($project, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Project']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
$view = new View($form);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Project']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -297,7 +302,7 @@ class ProjectController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Project']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -305,7 +310,7 @@ class ProjectController extends BaseApiController
|
||||
$this->repository->saveProject($project);
|
||||
|
||||
$view = new View($project, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Project']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -358,7 +363,7 @@ class ProjectController extends BaseApiController
|
||||
$this->repository->saveProject($project);
|
||||
|
||||
$view = new View($project, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Project']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -401,7 +406,7 @@ class ProjectController extends BaseApiController
|
||||
$rates = $this->projectRateRepository->getRatesForProject($project);
|
||||
|
||||
$view = new View($rates, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'ProjectRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -512,7 +517,7 @@ class ProjectController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'ProjectRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -520,7 +525,7 @@ class ProjectController extends BaseApiController
|
||||
$this->projectRateRepository->saveRate($rate);
|
||||
|
||||
$view = new View($rate, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'ProjectRate']);
|
||||
$view->getContext()->setGroups(self::GROUPS_RATE);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
@@ -28,11 +28,8 @@ class StatusController extends BaseApiController
|
||||
/**
|
||||
* @var ViewHandlerInterface
|
||||
*/
|
||||
protected $viewHandler;
|
||||
private $viewHandler;
|
||||
|
||||
/**
|
||||
* @param ViewHandlerInterface $viewHandler
|
||||
*/
|
||||
public function __construct(ViewHandlerInterface $viewHandler)
|
||||
{
|
||||
$this->viewHandler = $viewHandler;
|
||||
|
||||
@@ -32,22 +32,21 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
*
|
||||
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
|
||||
*/
|
||||
class TagController extends BaseApiController
|
||||
final class TagController extends BaseApiController
|
||||
{
|
||||
public const GROUPS_COLLECTION = ['Default', 'Collection', 'Tag'];
|
||||
public const GROUPS_ENTITY = ['Default', 'Entity', 'Tag'];
|
||||
public const GROUPS_FORM = ['Default', 'Entity', 'Tag'];
|
||||
|
||||
/**
|
||||
* @var TagRepository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
private $repository;
|
||||
/**
|
||||
* @var ViewHandlerInterface
|
||||
*/
|
||||
protected $viewHandler;
|
||||
private $viewHandler;
|
||||
|
||||
/**
|
||||
* @param ViewHandlerInterface $viewHandler
|
||||
* @param TagRepository $repository
|
||||
*/
|
||||
public function __construct(ViewHandlerInterface $viewHandler, TagRepository $repository)
|
||||
{
|
||||
$this->viewHandler = $viewHandler;
|
||||
@@ -78,7 +77,7 @@ class TagController extends BaseApiController
|
||||
$data = $this->repository->findAllTagNames($filter);
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Collection', 'Tag']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -120,13 +119,13 @@ class TagController extends BaseApiController
|
||||
$this->repository->saveTag($tag);
|
||||
|
||||
$view = new View($tag, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Tag']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
$view = new View($form);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Tag']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -137,7 +136,7 @@ class TagController extends BaseApiController
|
||||
* @SWG\Delete(
|
||||
* @SWG\Response(
|
||||
* response=204,
|
||||
* description="Delete one tag"
|
||||
* description="HTTP code 204 for a successful delete"
|
||||
* ),
|
||||
* )
|
||||
* @SWG\Parameter(
|
||||
|
||||
@@ -39,6 +39,10 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
*/
|
||||
final class TeamController extends BaseApiController
|
||||
{
|
||||
public const GROUPS_ENTITY = ['Default', 'Entity', 'Team', 'Team_Entity'];
|
||||
public const GROUPS_FORM = ['Default', 'Entity', 'Team', 'Team_Entity'];
|
||||
public const GROUPS_COLLECTION = ['Default', 'Collection', 'Team'];
|
||||
|
||||
/**
|
||||
* @var TeamRepository
|
||||
*/
|
||||
@@ -76,7 +80,7 @@ final class TeamController extends BaseApiController
|
||||
$data = $this->repository->findAll();
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Collection', 'Team']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -104,7 +108,7 @@ final class TeamController extends BaseApiController
|
||||
}
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -154,7 +158,7 @@ final class TeamController extends BaseApiController
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Returns the new created team",
|
||||
* @SWG\Schema(ref="#/definitions/TeamEntity",),
|
||||
* @SWG\Schema(ref="#/definitions/TeamEntity"),
|
||||
* )
|
||||
* )
|
||||
* @SWG\Parameter(
|
||||
@@ -186,13 +190,13 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
$view = new View($form);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -243,7 +247,7 @@ final class TeamController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -251,7 +255,7 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -314,7 +318,7 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -377,7 +381,7 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -440,7 +444,7 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -499,7 +503,7 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -562,7 +566,7 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -621,7 +625,7 @@ final class TeamController extends BaseApiController
|
||||
$this->repository->saveTeam($team);
|
||||
|
||||
$view = new View($team, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Team_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,11 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
*/
|
||||
class TimesheetController extends BaseApiController
|
||||
{
|
||||
public const GROUPS_ENTITY = ['Default', 'Entity', 'Timesheet', 'Timesheet_Entity', 'Not_Expanded'];
|
||||
public const GROUPS_FORM = ['Default', 'Entity', 'Timesheet', 'Not_Expanded'];
|
||||
public const GROUPS_COLLECTION = ['Default', 'Collection', 'Timesheet', 'Not_Expanded'];
|
||||
public const GROUPS_COLLECTION_FULL = ['Default', 'Collection', 'Timesheet', 'Expanded'];
|
||||
|
||||
/**
|
||||
* @var TimesheetRepository
|
||||
*/
|
||||
@@ -266,9 +271,9 @@ class TimesheetController extends BaseApiController
|
||||
|
||||
$view = new View($data, 200);
|
||||
if ('true' === $paramFetcher->get('full')) {
|
||||
$view->getContext()->setGroups(['Default', 'Subresource', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION_FULL);
|
||||
} else {
|
||||
$view->getContext()->setGroups(['Default', 'Collection', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
}
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
@@ -308,7 +313,7 @@ class TimesheetController extends BaseApiController
|
||||
}
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -368,13 +373,13 @@ class TimesheetController extends BaseApiController
|
||||
}
|
||||
|
||||
$view = new View($timesheet, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
$view = new View($form);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -438,7 +443,7 @@ class TimesheetController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -446,7 +451,7 @@ class TimesheetController extends BaseApiController
|
||||
$this->service->updateTimesheet($timesheet);
|
||||
|
||||
$view = new View($timesheet, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -498,7 +503,7 @@ class TimesheetController extends BaseApiController
|
||||
* description="Returns the collection of recent user activities (always the latest entry of a unique working set grouped by customer, project and activity)",
|
||||
* @SWG\Schema(
|
||||
* type="array",
|
||||
* @SWG\Items(ref="#/definitions/TimesheetSubCollection")
|
||||
* @SWG\Items(ref="#/definitions/TimesheetCollectionExpanded")
|
||||
* )
|
||||
* )
|
||||
*
|
||||
@@ -535,7 +540,7 @@ class TimesheetController extends BaseApiController
|
||||
$data = $this->repository->getRecentActivities($user, $begin, $limit);
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Subresource', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION_FULL);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -548,7 +553,7 @@ class TimesheetController extends BaseApiController
|
||||
* description="Returns the collection of active timesheet records for the current user",
|
||||
* @SWG\Schema(
|
||||
* type="array",
|
||||
* @SWG\Items(ref="#/definitions/TimesheetSubCollection")
|
||||
* @SWG\Items(ref="#/definitions/TimesheetCollectionExpanded")
|
||||
* )
|
||||
* )
|
||||
*
|
||||
@@ -565,7 +570,7 @@ class TimesheetController extends BaseApiController
|
||||
$data = $this->repository->getActiveEntries($user);
|
||||
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Subresource', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION_FULL);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -604,7 +609,7 @@ class TimesheetController extends BaseApiController
|
||||
$this->service->stopTimesheet($timesheet);
|
||||
|
||||
$view = new View($timesheet, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -687,7 +692,7 @@ class TimesheetController extends BaseApiController
|
||||
$this->service->saveNewTimesheet($copyTimesheet);
|
||||
|
||||
$view = new View($copyTimesheet, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -728,7 +733,7 @@ class TimesheetController extends BaseApiController
|
||||
$this->service->saveNewTimesheet($copyTimesheet);
|
||||
|
||||
$view = new View($copyTimesheet, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -771,7 +776,7 @@ class TimesheetController extends BaseApiController
|
||||
$this->service->updateTimesheet($timesheet);
|
||||
|
||||
$view = new View($timesheet, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -824,7 +829,7 @@ class TimesheetController extends BaseApiController
|
||||
$this->service->updateTimesheet($timesheet);
|
||||
|
||||
$view = new View($timesheet, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'Timesheet']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
*/
|
||||
final class UserController extends BaseApiController
|
||||
{
|
||||
public const GROUPS_ENTITY = ['Default', 'Entity', 'User', 'User_Entity'];
|
||||
public const GROUPS_FORM = ['Default', 'Entity', 'User', 'User_Entity'];
|
||||
public const GROUPS_COLLECTION = ['Default', 'Collection', 'User'];
|
||||
|
||||
/**
|
||||
* @var UserRepository
|
||||
*/
|
||||
@@ -56,10 +60,6 @@ final class UserController extends BaseApiController
|
||||
*/
|
||||
private $configuration;
|
||||
|
||||
/**
|
||||
* @param ViewHandlerInterface $viewHandler
|
||||
* @param UserRepository $repository
|
||||
*/
|
||||
public function __construct(ViewHandlerInterface $viewHandler, UserRepository $repository, UserPasswordEncoderInterface $encoder, FormConfiguration $config)
|
||||
{
|
||||
$this->viewHandler = $viewHandler;
|
||||
@@ -113,7 +113,7 @@ final class UserController extends BaseApiController
|
||||
|
||||
$data = $this->repository->getUsersForQuery($query);
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Collection', 'User']);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -150,7 +150,7 @@ final class UserController extends BaseApiController
|
||||
}
|
||||
|
||||
$view = new View($user, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'User', 'User_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -172,7 +172,7 @@ final class UserController extends BaseApiController
|
||||
public function meAction(): Response
|
||||
{
|
||||
$view = new View($this->getUser(), 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'User', 'User_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -223,13 +223,13 @@ final class UserController extends BaseApiController
|
||||
$this->repository->saveUser($user);
|
||||
|
||||
$view = new View($user, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'User', 'User_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
$view = new View($form);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'User', 'User_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -285,7 +285,7 @@ final class UserController extends BaseApiController
|
||||
|
||||
if (false === $form->isValid()) {
|
||||
$view = new View($form, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'User', 'User_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_FORM);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
@@ -293,7 +293,7 @@ final class UserController extends BaseApiController
|
||||
$this->repository->saveUser($user);
|
||||
|
||||
$view = new View($user, Response::HTTP_OK);
|
||||
$view->getContext()->setGroups(['Default', 'Entity', 'User', 'User_Entity']);
|
||||
$view->getContext()->setGroups(self::GROUPS_ENTITY);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
}
|
||||
|
||||
@@ -363,7 +363,6 @@ class ProfileController extends AbstractController
|
||||
UserPasswordType::class,
|
||||
$user,
|
||||
[
|
||||
'validation_groups' => ['PasswordUpdate'],
|
||||
'action' => $this->generateUrl('user_profile_password', ['username' => $user->getUsername()]),
|
||||
'method' => 'POST'
|
||||
]
|
||||
|
||||
@@ -12,27 +12,49 @@ namespace App\Entity;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="kimai2_activities",
|
||||
* indexes={
|
||||
* indexes={
|
||||
* @ORM\Index(columns={"visible","project_id"}),
|
||||
* @ORM\Index(columns={"visible","project_id","name"}),
|
||||
* @ORM\Index(columns={"visible","name"})
|
||||
* }
|
||||
* }
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ActivityRepository")
|
||||
*
|
||||
* columns={"visible","name"} => IDX_8811FE1C7AB0E8595E237E06 => activity administration without filter
|
||||
* columns={"visible","project_id"} => IDX_8811FE1C7AB0E859166D1F9C => activity administration with customer or project filter
|
||||
* columns={"visible","project_id","name"} => IDX_8811FE1C7AB0E859166D1F9C5E237E06 => activity drop-down for global activities in toolbar or globalsOnly filter in activity administration
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\VirtualProperty(
|
||||
* "ProjectName",
|
||||
* exp="object.getProject() === null ? null : object.getProject().getName()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("parentTitle"),
|
||||
* @Serializer\Type(name="string"),
|
||||
* @Serializer\Groups({"Activity"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\VirtualProperty(
|
||||
* "ProjectAsId",
|
||||
* exp="object.getProject() === null ? null : object.getProject().getId()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("project"),
|
||||
* @Serializer\Type(name="integer"),
|
||||
* @Serializer\Groups({"Default"})
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Activity implements EntityWithMetaFields
|
||||
{
|
||||
/**
|
||||
* Internal ID
|
||||
*
|
||||
* @var int|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
@@ -46,34 +68,82 @@ class Activity implements EntityWithMetaFields
|
||||
*/
|
||||
private $project;
|
||||
/**
|
||||
* Name of this activity
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="name", type="string", length=150, nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Length(min=2, max=150, allowEmptyString=false)
|
||||
*/
|
||||
private $name;
|
||||
/**
|
||||
* Description of this activity
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Activity_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="comment", type="text", nullable=true)
|
||||
*/
|
||||
private $comment;
|
||||
/**
|
||||
* Whether this activity is visible and can be used for timesheets
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @ORM\Column(name="visible", type="boolean", nullable=false)
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="visible", type="boolean", nullable=false, options={"default": true})
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $visible = true;
|
||||
|
||||
// keep the trait include exactly here, for placing the column at the correct position
|
||||
// keep the traits here, for placing the column at the "correct" position
|
||||
use ColorTrait;
|
||||
use BudgetTrait;
|
||||
|
||||
/**
|
||||
* The total monetary budget, will be zero if unconfigured.
|
||||
*
|
||||
* @var float
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Activity_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="budget", type="float", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $budget = 0.00;
|
||||
/**
|
||||
* The time budget in seconds, will be be zero if unconfigured.
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Activity_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="time_budget", type="integer", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $timeBudget = 0;
|
||||
/**
|
||||
* Meta fields
|
||||
*
|
||||
* All visible meta (custom) fields registered with this activity
|
||||
*
|
||||
* @var ActivityMeta[]|Collection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Activity"})
|
||||
* @Serializer\Type(name="array<App\Entity\ActivityMeta>")
|
||||
* @Serializer\SerializedName("metaFields")
|
||||
* @Serializer\Accessor(getter="getVisibleMetaFields")
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\ActivityMeta", mappedBy="activity", cascade={"persist"})
|
||||
*/
|
||||
private $meta;
|
||||
@@ -141,6 +211,30 @@ class Activity implements EntityWithMetaFields
|
||||
return $this->visible;
|
||||
}
|
||||
|
||||
public function setBudget(float $budget): Activity
|
||||
{
|
||||
$this->budget = $budget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBudget(): float
|
||||
{
|
||||
return $this->budget;
|
||||
}
|
||||
|
||||
public function setTimeBudget(int $seconds): Activity
|
||||
{
|
||||
$this->timeBudget = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTimeBudget(): int
|
||||
{
|
||||
return $this->timeBudget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|MetaTableTypeInterface[]
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
@@ -21,6 +22,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* @ORM\UniqueConstraint(columns={"activity_id", "name"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class ActivityMeta implements MetaTableTypeInterface
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
@@ -21,6 +22,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ActivityRateRepository")
|
||||
* @UniqueEntity({"user", "activity"}, ignoreNull=false)
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class ActivityRate implements RateInterface
|
||||
{
|
||||
@@ -29,6 +32,8 @@ class ActivityRate implements RateInterface
|
||||
/**
|
||||
* @var Activity
|
||||
*
|
||||
* @Serializer\Exclude()
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Activity")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
|
||||
@@ -1,69 +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\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
trait BudgetTrait
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*
|
||||
* @ORM\Column(name="budget", type="float", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $budget = 0.00;
|
||||
|
||||
/**
|
||||
* Time budget in seconds.
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="time_budget", type="integer", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $timeBudget = 0;
|
||||
|
||||
/**
|
||||
* @param float $budget
|
||||
* @return self
|
||||
*/
|
||||
public function setBudget(?float $budget)
|
||||
{
|
||||
$this->budget = $budget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getBudget()
|
||||
{
|
||||
return $this->budget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $seconds
|
||||
* @return self
|
||||
*/
|
||||
public function setTimeBudget(?int $seconds)
|
||||
{
|
||||
$this->timeBudget = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTimeBudget(): int
|
||||
{
|
||||
return $this->timeBudget;
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,21 @@
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
trait ColorTrait
|
||||
{
|
||||
/**
|
||||
* The assigned color in HTML hex format, eg. #dd1d00
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="color", type="string", length=7, nullable=true)
|
||||
* @Assert\Length(min=4, max=7)
|
||||
*/
|
||||
private $color = null;
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace App\Entity;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Swagger\Annotations as SWG;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
@@ -22,14 +24,17 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\CustomerRepository")
|
||||
*
|
||||
* columns={"visible"} => IDX_5A9760447AB0E859 => used in customer dropdown
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Customer implements EntityWithMetaFields
|
||||
{
|
||||
public const DEFAULT_CURRENCY = 'EUR';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @var int|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
@@ -39,6 +44,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="name", type="string", length=150, nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Length(min=2, max=150, allowEmptyString=false)
|
||||
@@ -47,6 +55,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="number", type="string", length=50, nullable=true)
|
||||
* @Assert\Length(max=50)
|
||||
*/
|
||||
@@ -54,12 +65,18 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="comment", type="text", nullable=true)
|
||||
*/
|
||||
private $comment;
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="visible", type="boolean", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
@@ -67,6 +84,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="company", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=255)
|
||||
*/
|
||||
@@ -74,6 +94,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="vat_id", type="string", length=50, nullable=true)
|
||||
* @Assert\Length(max=50)
|
||||
*/
|
||||
@@ -81,6 +104,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="contact", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=255)
|
||||
*/
|
||||
@@ -88,12 +114,18 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="address", type="text", nullable=true)
|
||||
*/
|
||||
private $address;
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="country", type="string", length=2, nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Length(max=2)
|
||||
@@ -102,6 +134,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer"})
|
||||
*
|
||||
* @ORM\Column(name="currency", type="string", length=3, nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Length(max=3)
|
||||
@@ -110,6 +145,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="phone", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=255)
|
||||
*/
|
||||
@@ -117,6 +155,9 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="fax", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=255)
|
||||
*/
|
||||
@@ -124,15 +165,23 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="mobile", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=255)
|
||||
*/
|
||||
private $mobile;
|
||||
/**
|
||||
* @var string
|
||||
* Customers contact email
|
||||
*
|
||||
* Limited via RFC to 254 chars
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="email", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=254)
|
||||
*/
|
||||
@@ -140,15 +189,23 @@ class Customer implements EntityWithMetaFields
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="homepage", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=255)
|
||||
*/
|
||||
private $homepage;
|
||||
/**
|
||||
* @var string
|
||||
* Timezone of begin and end
|
||||
*
|
||||
* Length was determined by a MySQL column via "use mysql;describe time_zone_name;"
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="timezone", type="string", length=64, nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Length(max=64)
|
||||
@@ -157,17 +214,58 @@ class Customer implements EntityWithMetaFields
|
||||
|
||||
// keep the trait include exactly here, for placing the column at the correct position
|
||||
use ColorTrait;
|
||||
use BudgetTrait;
|
||||
|
||||
/**
|
||||
* The total monetary budget, will be zero if unconfigured.
|
||||
*
|
||||
* @var float
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="budget", type="float", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $budget = 0.00;
|
||||
/**
|
||||
* The time budget in seconds, will be be zero if unconfigured.
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="time_budget", type="integer", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $timeBudget = 0;
|
||||
/**
|
||||
* Meta fields
|
||||
*
|
||||
* All visible meta (custom) fields registered with this customer
|
||||
*
|
||||
* @var CustomerMeta[]|Collection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer"})
|
||||
* @Serializer\Type(name="array<App\Entity\CustomerMeta>")
|
||||
* @Serializer\SerializedName("metaFields")
|
||||
* @Serializer\Accessor(getter="getVisibleMetaFields")
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\CustomerMeta", mappedBy="customer", cascade={"persist"})
|
||||
*/
|
||||
private $meta;
|
||||
/**
|
||||
* Teams
|
||||
*
|
||||
* If no team is assigned, everyone can access the customer
|
||||
*
|
||||
* @var Team[]|ArrayCollection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Customer"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/Team"))
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="Team", cascade={"persist"}, inversedBy="customers")
|
||||
* @ORM\JoinTable(
|
||||
* name="kimai2_customers_teams",
|
||||
@@ -384,6 +482,30 @@ class Customer implements EntityWithMetaFields
|
||||
return $this->timezone;
|
||||
}
|
||||
|
||||
public function setBudget(float $budget): Customer
|
||||
{
|
||||
$this->budget = $budget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBudget(): float
|
||||
{
|
||||
return $this->budget;
|
||||
}
|
||||
|
||||
public function setTimeBudget(int $seconds): Customer
|
||||
{
|
||||
$this->timeBudget = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTimeBudget(): int
|
||||
{
|
||||
return $this->timeBudget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|MetaTableTypeInterface[]
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
@@ -21,6 +22,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* @ORM\UniqueConstraint(columns={"customer_id", "name"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class CustomerMeta implements MetaTableTypeInterface
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
@@ -21,6 +22,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\CustomerRateRepository")
|
||||
* @UniqueEntity({"user", "customer"}, ignoreNull=false)
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class CustomerRate implements RateInterface
|
||||
{
|
||||
@@ -29,6 +32,8 @@ class CustomerRate implements RateInterface
|
||||
/**
|
||||
* @var Customer
|
||||
*
|
||||
* @Serializer\Exclude()
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Customer")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
|
||||
@@ -11,6 +11,7 @@ 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\Validator\Constraint;
|
||||
@@ -21,6 +22,8 @@ trait MetaTableTypeTrait
|
||||
/**
|
||||
* @var int|null
|
||||
*
|
||||
* @Serializer\Exclude()
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
@@ -28,8 +31,13 @@ trait MetaTableTypeTrait
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* Name of the meta (custom) field
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="name", type="string", length=50, nullable=false)
|
||||
* @Assert\NotNull()
|
||||
* @Assert\Length(min=2, max=50, allowEmptyString=false)
|
||||
@@ -37,8 +45,13 @@ trait MetaTableTypeTrait
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Value of the meta (custom) field
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="value", type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $value;
|
||||
|
||||
@@ -9,9 +9,12 @@
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Validator\Constraints as Constraints;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Swagger\Annotations as SWG;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
@@ -22,40 +25,78 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* }
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ProjectRepository")
|
||||
* @App\Validator\Constraints\Project
|
||||
* @Constraints\Project
|
||||
*
|
||||
* columns={"customer_id","visible","name"} => IDX_407F12069395C3F37AB0E8595E237E06 => project administration without filter
|
||||
* columns={"customer_id","visible","id"} => IDX_407F12069395C3F37AB0E859BF396750 => used in joins between project and customer, eg. dropdowns and activity administration page
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\VirtualProperty(
|
||||
* "CustomerName",
|
||||
* exp="object.getCustomer() === null ? null : object.getCustomer().getName()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("parentTitle"),
|
||||
* @Serializer\Type(name="string"),
|
||||
* @Serializer\Groups({"Project"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\VirtualProperty(
|
||||
* "CustomerAsId",
|
||||
* exp="object.getCustomer() === null ? null : object.getCustomer().getId()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("customer"),
|
||||
* @Serializer\Type(name="integer"),
|
||||
* @Serializer\Groups({"Project", "Team", "Not_Expanded"})
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Project implements EntityWithMetaFields
|
||||
{
|
||||
/**
|
||||
* Internal ID
|
||||
*
|
||||
* @var int|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
*/
|
||||
private $id;
|
||||
/**
|
||||
* Customer for this project
|
||||
*
|
||||
* @var Customer
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Subresource", "Expanded"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/Customer"))
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Customer")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $customer;
|
||||
/**
|
||||
* Project name
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="name", type="string", length=150, nullable=false)
|
||||
* @Assert\NotNull()
|
||||
* @Assert\Length(min=2, max=150, allowEmptyString=false)
|
||||
*/
|
||||
private $name;
|
||||
/**
|
||||
* Project order number
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="order_number", type="text", length=20, nullable=true)
|
||||
* @Assert\Length(max=20)
|
||||
*/
|
||||
@@ -63,40 +104,60 @@ class Project implements EntityWithMetaFields
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project_Entity"})
|
||||
* @Serializer\Type(name="DateTime")
|
||||
*
|
||||
* @ORM\Column(name="order_date", type="datetime", nullable=true)
|
||||
*/
|
||||
private $orderDate;
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project"})
|
||||
* @Serializer\Type(name="DateTime")
|
||||
*
|
||||
* @ORM\Column(name="start", type="datetime", nullable=true)
|
||||
*/
|
||||
private $start;
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project"})
|
||||
* @Serializer\Type(name="DateTime")
|
||||
*
|
||||
* @ORM\Column(name="end", type="datetime", nullable=true)
|
||||
*/
|
||||
private $end;
|
||||
/**
|
||||
* @var string
|
||||
* @internal used for storing the timezone for "order", "start" and "end" date
|
||||
*
|
||||
* @ORM\Column(name="timezone", type="string", length=64, nullable=true)
|
||||
*/
|
||||
private $timezone;
|
||||
/**
|
||||
* @var bool
|
||||
* @internal used for having the localization state of the dates (see $timezone)
|
||||
*/
|
||||
private $localized = false;
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="comment", type="text", nullable=true)
|
||||
*/
|
||||
private $comment;
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="visible", type="boolean", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
@@ -104,18 +165,58 @@ class Project implements EntityWithMetaFields
|
||||
|
||||
// keep the trait include exactly here, for placing the column at the correct position
|
||||
use ColorTrait;
|
||||
use BudgetTrait;
|
||||
|
||||
/**
|
||||
* The total monetary budget, will be zero if unconfigured.
|
||||
*
|
||||
* @var float
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="budget", type="float", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $budget = 0.00;
|
||||
/**
|
||||
* The time budget in seconds, will be be zero if unconfigured.
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="time_budget", type="integer", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $timeBudget = 0;
|
||||
/**
|
||||
* Meta fields
|
||||
*
|
||||
* All visible meta (custom) fields registered with this project
|
||||
*
|
||||
* @var ProjectMeta[]|Collection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project"})
|
||||
* @Serializer\Type(name="array<App\Entity\ProjectMeta>")
|
||||
* @Serializer\SerializedName("metaFields")
|
||||
* @Serializer\Accessor(getter="getVisibleMetaFields")
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\ProjectMeta", mappedBy="project", cascade={"persist"})
|
||||
*/
|
||||
private $meta;
|
||||
|
||||
/**
|
||||
* Teams
|
||||
*
|
||||
* If no team is assigned, everyone can access the project (also depends on the teams of the customer)
|
||||
*
|
||||
* @var Team[]|ArrayCollection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Project"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/Team"))
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="Team", cascade={"persist"}, inversedBy="projects")
|
||||
* @ORM\JoinTable(
|
||||
* name="kimai2_projects_teams",
|
||||
@@ -164,11 +265,7 @@ class Project implements EntityWithMetaFields
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $comment
|
||||
* @return Project
|
||||
*/
|
||||
public function setComment($comment): Project
|
||||
public function setComment(?string $comment): Project
|
||||
{
|
||||
$this->comment = $comment;
|
||||
|
||||
@@ -289,6 +386,30 @@ class Project implements EntityWithMetaFields
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBudget(float $budget): Project
|
||||
{
|
||||
$this->budget = $budget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBudget(): float
|
||||
{
|
||||
return $this->budget;
|
||||
}
|
||||
|
||||
public function setTimeBudget(int $seconds): Project
|
||||
{
|
||||
$this->timeBudget = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTimeBudget(): int
|
||||
{
|
||||
return $this->timeBudget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|MetaTableTypeInterface[]
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
@@ -21,6 +22,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* @ORM\UniqueConstraint(columns={"project_id", "name"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class ProjectMeta implements MetaTableTypeInterface
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
@@ -21,6 +22,8 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ProjectRateRepository")
|
||||
* @UniqueEntity({"user", "project"}, ignoreNull=false)
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class ProjectRate implements RateInterface
|
||||
{
|
||||
@@ -29,6 +32,8 @@ class ProjectRate implements RateInterface
|
||||
/**
|
||||
* @var Project
|
||||
*
|
||||
* @Serializer\Exclude()
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Project")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
|
||||
* @Assert\NotNull
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Swagger\Annotations as SWG;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
@@ -18,6 +19,9 @@ trait Rate
|
||||
/**
|
||||
* @var int|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
@@ -26,14 +30,20 @@ trait Rate
|
||||
/**
|
||||
* @var User
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @SWG\Property(ref="#/definitions/User")
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\User")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=true)
|
||||
* @SWG\Property(ref="#/definitions/User")
|
||||
*/
|
||||
private $user;
|
||||
/**
|
||||
* @var float
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="rate", type="float", nullable=false)
|
||||
* @Assert\GreaterThanOrEqual(0)
|
||||
*/
|
||||
@@ -41,12 +51,18 @@ trait Rate
|
||||
/**
|
||||
* @var float|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="internal_rate", type="float", nullable=true)
|
||||
*/
|
||||
private $internalRate;
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="fixed", type="boolean", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
@@ -22,21 +23,32 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\TagRepository")
|
||||
* @UniqueEntity("name")
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Tag
|
||||
{
|
||||
/**
|
||||
* The internal ID
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* The tag name
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="name", type="string", length=100, nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Length(min=2, max=100, allowEmptyString=false)
|
||||
@@ -49,9 +61,11 @@ class Tag
|
||||
/**
|
||||
* @var Timesheet[]|ArrayCollection
|
||||
*
|
||||
* @Serializer\Exclude()
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="Timesheet", mappedBy="tags", fetch="EXTRA_LAZY")
|
||||
*/
|
||||
protected $timesheets;
|
||||
private $timesheets;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace App\Entity;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Swagger\Annotations as SWG;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
@@ -23,48 +25,92 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\TeamRepository")
|
||||
* @UniqueEntity("name")
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Team
|
||||
{
|
||||
/**
|
||||
* The internal ID
|
||||
*
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
*/
|
||||
private $id;
|
||||
/**
|
||||
* Team name
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="name", type="string", length=100, nullable=false)
|
||||
* @Assert\NotBlank()
|
||||
* @Assert\Length(min=2, max=100, allowEmptyString=false)
|
||||
*/
|
||||
private $name;
|
||||
/**
|
||||
* Teamlead
|
||||
*
|
||||
* The teamlead for this team
|
||||
*
|
||||
* @var User
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Team_Entity"})
|
||||
* @SWG\Property(ref="#/definitions/User")
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\User")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $teamlead;
|
||||
/**
|
||||
* Team member
|
||||
*
|
||||
* All team member, including the teamlead
|
||||
*
|
||||
* @var User[]|ArrayCollection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Team_Entity"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/User"))
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="User", mappedBy="teams", fetch="EXTRA_LAZY")
|
||||
*/
|
||||
private $users;
|
||||
/**
|
||||
* Customers
|
||||
*
|
||||
* All customers assigned to the team
|
||||
*
|
||||
* @var Customer[]|ArrayCollection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Team_Entity"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/Customer"))
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="Customer", mappedBy="teams", fetch="EXTRA_LAZY")
|
||||
*/
|
||||
private $customers;
|
||||
/**
|
||||
* Projects
|
||||
*
|
||||
* All projects assigned to the team
|
||||
*
|
||||
* @var Project[]|ArrayCollection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Team_Entity", "Expanded"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/Project"))
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="Project", mappedBy="teams", fetch="EXTRA_LAZY")
|
||||
*/
|
||||
private $projects;
|
||||
|
||||
@@ -10,12 +10,15 @@
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Export\ExportItemInterface;
|
||||
use App\Validator\Constraints as Constraints;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Gedmo\Mapping\Annotation as Gedmo;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Swagger\Annotations as SWG;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
@@ -31,7 +34,45 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="App\Repository\TimesheetRepository")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
* @App\Validator\Constraints\Timesheet
|
||||
* @Constraints\Timesheet
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\VirtualProperty(
|
||||
* "ActivityAsId",
|
||||
* exp="object.getActivity() === null ? null : object.getActivity().getId()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("activity"),
|
||||
* @Serializer\Type(name="integer"),
|
||||
* @Serializer\Groups({"Not_Expanded"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\VirtualProperty(
|
||||
* "ProjectAsId",
|
||||
* exp="object.getProject() === null ? null : object.getProject().getId()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("project"),
|
||||
* @Serializer\Type(name="integer"),
|
||||
* @Serializer\Groups({"Not_Expanded"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\VirtualProperty(
|
||||
* "UserAsId",
|
||||
* exp="object.getUser().getId()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("user"),
|
||||
* @Serializer\Type(name="integer"),
|
||||
* @Serializer\Groups({"Default"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\VirtualProperty(
|
||||
* "TagsAsArray",
|
||||
* exp="object.getTagsAsArray()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("tags"),
|
||||
* @Serializer\Type(name="array<string>"),
|
||||
* @Serializer\Groups({"Default"})
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Timesheet implements EntityWithMetaFields, ExportItemInterface
|
||||
{
|
||||
@@ -59,47 +100,57 @@ class Timesheet implements EntityWithMetaFields, ExportItemInterface
|
||||
/**
|
||||
* @var int|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="IDENTITY")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="DateTime")
|
||||
*
|
||||
* @ORM\Column(name="start_time", type="datetime", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $begin;
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
* @Serializer\Type(name="DateTime")
|
||||
*
|
||||
* @ORM\Column(name="end_time", type="datetime", nullable=true)
|
||||
*/
|
||||
private $end;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @internal for storing the timezone of "begin" and "end" date
|
||||
*
|
||||
* @ORM\Column(name="timezone", type="string", length=64, nullable=false)
|
||||
*/
|
||||
private $timezone;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @internal for storing the localized state of dates (see $timezone)
|
||||
*/
|
||||
private $localized = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="duration", type="integer", nullable=true)
|
||||
* @Assert\GreaterThanOrEqual(0)
|
||||
*/
|
||||
private $duration = 0;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*
|
||||
@@ -108,71 +159,92 @@ class Timesheet implements EntityWithMetaFields, ExportItemInterface
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Activity
|
||||
*
|
||||
* @var Activity
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Expanded"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/ActivityExpanded"))
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Activity")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $activity;
|
||||
|
||||
/**
|
||||
* Project
|
||||
*
|
||||
* @var Project
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Subresource", "Expanded"})
|
||||
* @SWG\Property(type="array", @SWG\Items(ref="#/definitions/ProjectExpanded"))
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Project")
|
||||
* @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $project;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="description", type="text", nullable=true)
|
||||
*/
|
||||
private $description;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="rate", type="float", nullable=false)
|
||||
* @Assert\GreaterThanOrEqual(0)
|
||||
*/
|
||||
private $rate = 0.00;
|
||||
|
||||
/**
|
||||
* @var float|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="internal_rate", type="float", nullable=true)
|
||||
*/
|
||||
private $internalRate;
|
||||
|
||||
/**
|
||||
* @var float|null
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Entity"})
|
||||
*
|
||||
* @ORM\Column(name="fixed_rate", type="float", nullable=true)
|
||||
* @Assert\GreaterThanOrEqual(0)
|
||||
*/
|
||||
private $fixedRate = null;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Entity"})
|
||||
*
|
||||
* @ORM\Column(name="hourly_rate", type="float", nullable=true)
|
||||
* @Assert\GreaterThanOrEqual(0)
|
||||
*/
|
||||
private $hourlyRate = null;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Entity"})
|
||||
*
|
||||
* @ORM\Column(name="exported", type="boolean", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $exported = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*
|
||||
@@ -180,7 +252,6 @@ class Timesheet implements EntityWithMetaFields, ExportItemInterface
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $billable = true;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
@@ -188,16 +259,17 @@ class Timesheet implements EntityWithMetaFields, ExportItemInterface
|
||||
* @Assert\NotNull()
|
||||
*/
|
||||
private $category = self::WORK;
|
||||
|
||||
/**
|
||||
* @var DateTime|null
|
||||
* @internal used for limiting queries, eg. via API sync
|
||||
*
|
||||
* @Gedmo\Timestampable
|
||||
* @ORM\Column(name="modified_at", type="datetime", nullable=true)
|
||||
*/
|
||||
private $modifiedAt;
|
||||
|
||||
/**
|
||||
* Tags
|
||||
*
|
||||
* @var Tag[]|ArrayCollection
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="App\Entity\Tag", inversedBy="timesheets", cascade={"persist"})
|
||||
@@ -213,10 +285,19 @@ class Timesheet implements EntityWithMetaFields, ExportItemInterface
|
||||
* @Assert\Valid()
|
||||
*/
|
||||
private $tags;
|
||||
|
||||
/**
|
||||
* Meta fields
|
||||
*
|
||||
* All visible meta (custom) fields registered with this timesheet
|
||||
*
|
||||
* @var TimesheetMeta[]|Collection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Timesheet"})
|
||||
* @Serializer\Type(name="array<App\Entity\TimesheetMeta>")
|
||||
* @Serializer\SerializedName("metaFields")
|
||||
* @Serializer\Accessor(getter="getVisibleMetaFields")
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\TimesheetMeta", mappedBy="timesheet", cascade={"persist"})
|
||||
*/
|
||||
private $meta;
|
||||
|
||||
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
@@ -21,6 +22,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* @ORM\UniqueConstraint(columns={"timesheet_id", "name"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class TimesheetMeta implements MetaTableTypeInterface
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use FOS\UserBundle\Model\User as BaseUser;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
@@ -28,6 +29,26 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* )
|
||||
* @UniqueEntity("username")
|
||||
* @UniqueEntity("email")
|
||||
*
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\VirtualProperty(
|
||||
* "LanguageAsString",
|
||||
* exp="object.getLocale()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("language"),
|
||||
* @Serializer\Type(name="string"),
|
||||
* @Serializer\Groups({"User_Entity"})
|
||||
* }
|
||||
* )
|
||||
* @Serializer\VirtualProperty(
|
||||
* "TimezoneAsString",
|
||||
* exp="object.getTimezone()",
|
||||
* options={
|
||||
* @Serializer\SerializedName("timezone"),
|
||||
* @Serializer\Type(name="string"),
|
||||
* @Serializer\Groups({"User_Entity"})
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class User extends BaseUser implements UserInterface
|
||||
{
|
||||
@@ -44,67 +65,94 @@ class User extends BaseUser implements UserInterface
|
||||
public const AUTH_SAML = 'saml';
|
||||
|
||||
/**
|
||||
* Internal ID
|
||||
*
|
||||
* @var int
|
||||
* @internal must be protected because of parent class
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The user alias will be displayed in the frontend instead of the username
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"Default"})
|
||||
*
|
||||
* @ORM\Column(name="alias", type="string", length=60, nullable=true)
|
||||
* @Assert\Length(max=60)
|
||||
*/
|
||||
private $alias;
|
||||
|
||||
/**
|
||||
* Registration date for the user
|
||||
*
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(name="registration_date", type="datetime", nullable=true)
|
||||
*/
|
||||
private $registeredAt;
|
||||
|
||||
/**
|
||||
* An additional title for the user, like the Job position or Department
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"User_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="title", type="string", length=50, nullable=true)
|
||||
* @Assert\Length(max=50)
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* URL to the users avatar, will be auto-generated if empty
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"User_Entity"})
|
||||
*
|
||||
* @ORM\Column(name="avatar", type="string", length=255, nullable=true)
|
||||
* @Assert\Length(max=255)
|
||||
*/
|
||||
private $avatar;
|
||||
|
||||
/**
|
||||
* API token (password) for this user
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="api_token", type="string", length=255, nullable=true)
|
||||
*/
|
||||
protected $apiToken;
|
||||
|
||||
private $apiToken;
|
||||
/**
|
||||
* @var string
|
||||
* @internal to be set via form, must not be persisted
|
||||
*/
|
||||
protected $plainApiToken;
|
||||
|
||||
private $plainApiToken;
|
||||
/**
|
||||
* User preferences
|
||||
*
|
||||
* List of preferences for this user, required ones have dedicated fields/methods
|
||||
*
|
||||
* @var UserPreference[]|Collection
|
||||
*
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\UserPreference", mappedBy="user", cascade={"persist"})
|
||||
*/
|
||||
private $preferences;
|
||||
|
||||
/**
|
||||
* All teams of the user
|
||||
*
|
||||
* @var Team[]|ArrayCollection
|
||||
*
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Groups({"User_Entity"})
|
||||
*
|
||||
* @ORM\ManyToMany(targetEntity="Team", inversedBy="users", cascade={"persist"})
|
||||
* @ORM\JoinTable(
|
||||
* name="kimai2_users_teams",
|
||||
@@ -117,25 +165,24 @@ class User extends BaseUser implements UserInterface
|
||||
* )
|
||||
*/
|
||||
private $teams;
|
||||
|
||||
/**
|
||||
* The type of authentication used by the user (eg. "kimai", "ldap", "saml")
|
||||
*
|
||||
* @var string
|
||||
* @internal for internal usage only
|
||||
*
|
||||
* @ORM\Column(name="auth", type="string", length=20, nullable=true)
|
||||
* @Assert\Length(max=20)
|
||||
*/
|
||||
private $auth = self::AUTH_INTERNAL;
|
||||
|
||||
/**
|
||||
* This flag will be initialized in UserEnvironmentSubscriber.
|
||||
*
|
||||
* @var bool|null
|
||||
* @internal has no database mapping. as the value is calculated from a permission
|
||||
*/
|
||||
private $isAllowedToSeeAllData = null;
|
||||
|
||||
/**
|
||||
* User constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
@@ -27,7 +27,7 @@ abstract class AbstractRateForm extends AbstractType
|
||||
// documentation is for NelmioApiDocBundle
|
||||
'documentation' => [
|
||||
'type' => 'number',
|
||||
'description' => 'Rate',
|
||||
'description' => 'The rate (eg. 10.5)',
|
||||
],
|
||||
'label' => 'label.rate',
|
||||
'attr' => [
|
||||
@@ -40,7 +40,7 @@ abstract class AbstractRateForm extends AbstractType
|
||||
// documentation is for NelmioApiDocBundle
|
||||
'documentation' => [
|
||||
'type' => 'number',
|
||||
'description' => 'Internal rate',
|
||||
'description' => 'The internal rate (eg. 10.0 or 10)',
|
||||
],
|
||||
'label' => 'label.rate_internal',
|
||||
'currency' => $currency,
|
||||
@@ -50,6 +50,10 @@ abstract class AbstractRateForm extends AbstractType
|
||||
->add('isFixed', YesNoType::class, [
|
||||
'label' => 'label.fixedRate',
|
||||
'help' => 'help.fixedRate',
|
||||
'documentation' => [
|
||||
'type' => 'boolean',
|
||||
'description' => 'If "true" each time record gets the same rate, regardless of its duration',
|
||||
],
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ class TagEditForm extends AbstractType
|
||||
'attr' => [
|
||||
'autofocus' => 'autofocus'
|
||||
],
|
||||
'documentation' => [
|
||||
'type' => 'string',
|
||||
'description' => 'The tag name (forbidden character: comma)',
|
||||
],
|
||||
])
|
||||
->add('color', ColorPickerType::class);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class TeamEditForm extends AbstractType
|
||||
// documentation is for NelmioApiDocBundle
|
||||
'documentation' => [
|
||||
'type' => 'string',
|
||||
'description' => 'Name of the new team',
|
||||
'description' => 'Name of the team',
|
||||
],
|
||||
])
|
||||
->add('teamlead', UserType::class, [
|
||||
@@ -49,6 +49,12 @@ class TeamEditForm extends AbstractType
|
||||
'multiple' => true,
|
||||
'expanded' => $options['expand_users'],
|
||||
'by_reference' => false,
|
||||
'documentation' => [
|
||||
'type' => 'array',
|
||||
'items' => ['type' => 'integer', 'description' => 'User IDs'],
|
||||
'title' => 'Team member',
|
||||
'description' => 'Array of team member IDs',
|
||||
],
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ class ColorPickerType extends AbstractType implements DataTransformerInterface
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'documentation' => [
|
||||
'type' => 'string',
|
||||
'description' => sprintf('The color code as hex (default: %s)', self::DEFAULT_COLOR),
|
||||
],
|
||||
'label' => 'label.color',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ class UserType extends AbstractType
|
||||
return $user->getDisplayName();
|
||||
},
|
||||
'choice_translation_domain' => false,
|
||||
'documentation' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'User ID',
|
||||
],
|
||||
]);
|
||||
|
||||
$resolver->setDefault('query_builder', function (Options $options) {
|
||||
|
||||
@@ -56,6 +56,7 @@ class UserCreateType extends UserEditType
|
||||
parent::configureOptions($resolver);
|
||||
|
||||
$resolver->setDefaults([
|
||||
'validation_groups' => ['UserCreate'],
|
||||
'include_add_more' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ class UserEditType extends AbstractType
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'validation_groups' => ['Profile'],
|
||||
'data_class' => User::class,
|
||||
'csrf_protection' => true,
|
||||
'csrf_field_name' => '_token',
|
||||
|
||||
@@ -41,6 +41,7 @@ class UserPasswordType extends AbstractType
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'validation_groups' => ['PasswordUpdate'],
|
||||
'data_class' => User::class,
|
||||
'csrf_protection' => true,
|
||||
'csrf_field_name' => '_token',
|
||||
|
||||
@@ -40,6 +40,7 @@ class UserRolesType extends AbstractType
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'validation_groups' => ['RolesUpdate'],
|
||||
'data_class' => User::class,
|
||||
'csrf_protection' => true,
|
||||
'csrf_field_name' => '_token',
|
||||
|
||||
Reference in New Issue
Block a user