Release 2.42 (#5686)
This commit is contained in:
@@ -12,8 +12,6 @@ namespace App\API;
|
||||
use App\Activity\ActivityService;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\ActivityRate;
|
||||
use App\Entity\User;
|
||||
use App\Event\ActivityMetaDefinitionEvent;
|
||||
use App\Form\API\ActivityApiEditForm;
|
||||
use App\Form\API\ActivityRateApiForm;
|
||||
use App\Repository\ActivityRateRepository;
|
||||
@@ -26,7 +24,6 @@ use FOS\RestBundle\Request\ParamFetcherInterface;
|
||||
use FOS\RestBundle\View\View;
|
||||
use FOS\RestBundle\View\ViewHandlerInterface;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -46,7 +43,6 @@ final class ActivityController extends BaseApiController
|
||||
public function __construct(
|
||||
private readonly ViewHandlerInterface $viewHandler,
|
||||
private readonly ActivityRepository $repository,
|
||||
private readonly EventDispatcherInterface $dispatcher,
|
||||
private readonly ActivityRateRepository $activityRateRepository,
|
||||
private readonly ActivityService $activityService
|
||||
) {
|
||||
@@ -63,25 +59,12 @@ final class ActivityController extends BaseApiController
|
||||
#[Rest\QueryParam(name: 'globals', requirements: '0|1|true|false', strict: true, nullable: true, description: 'Use if you want to fetch only global activities. Allowed values: 0|1 (default: 0 for false)')]
|
||||
#[Rest\QueryParam(name: 'orderBy', requirements: 'id|name|project', strict: true, nullable: true, description: 'The field by which results will be ordered. Allowed values: id, name, project (default: name)')]
|
||||
#[Rest\QueryParam(name: 'order', requirements: 'ASC|DESC', strict: true, nullable: true, description: 'The result order. Allowed values: ASC, DESC (default: ASC)')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term', nullable: true)]
|
||||
public function cgetAction(ParamFetcherInterface $paramFetcher, ProjectRepository $projectRepository): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
|
||||
$query = new ActivityQuery();
|
||||
$query->loadTeams();
|
||||
$query->setCurrentUser($user);
|
||||
|
||||
$order = $paramFetcher->get('order');
|
||||
if (\is_string($order) && $order !== '') {
|
||||
$query->setOrder($order);
|
||||
}
|
||||
|
||||
$orderBy = $paramFetcher->get('orderBy');
|
||||
if (\is_string($orderBy) && $orderBy !== '') {
|
||||
$query->setOrderBy($orderBy);
|
||||
}
|
||||
$this->prepareQuery($query, $paramFetcher);
|
||||
|
||||
$globals = $paramFetcher->get('globals');
|
||||
if (\is_string($globals) && ($globals === 'true' || $globals === '1')) {
|
||||
@@ -113,7 +96,6 @@ final class ActivityController extends BaseApiController
|
||||
$query->setSearchTerm(new SearchTerm($term));
|
||||
}
|
||||
|
||||
$query->setIsApiCall(true);
|
||||
$data = $this->repository->getActivitiesForQuery($query);
|
||||
$view = new View($data, 200);
|
||||
$view->getContext()->setGroups(self::GROUPS_COLLECTION);
|
||||
@@ -149,9 +131,7 @@ final class ActivityController extends BaseApiController
|
||||
}
|
||||
|
||||
$activity = new Activity();
|
||||
|
||||
$event = new ActivityMetaDefinitionEvent($activity);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->activityService->loadMetaFields($activity);
|
||||
|
||||
$form = $this->createForm(ActivityApiEditForm::class, $activity, [
|
||||
'include_budget' => $this->isGranted('budget', $activity),
|
||||
@@ -185,8 +165,7 @@ final class ActivityController extends BaseApiController
|
||||
#[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_activity', requirements: ['id' => '\d+'])]
|
||||
public function patchAction(Request $request, Activity $activity): Response
|
||||
{
|
||||
$event = new ActivityMetaDefinitionEvent($activity);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->activityService->loadMetaFields($activity);
|
||||
|
||||
$form = $this->createForm(ActivityApiEditForm::class, $activity, [
|
||||
'include_budget' => $this->isGranted('budget', $activity),
|
||||
@@ -241,8 +220,7 @@ final class ActivityController extends BaseApiController
|
||||
#[Rest\RequestParam(name: 'value', strict: true, nullable: false, description: 'The meta-field value')]
|
||||
public function metaAction(Activity $activity, ParamFetcherInterface $paramFetcher): Response
|
||||
{
|
||||
$event = new ActivityMetaDefinitionEvent($activity);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->activityService->loadMetaFields($activity);
|
||||
|
||||
$name = $paramFetcher->get('name');
|
||||
$value = $paramFetcher->get('value');
|
||||
|
||||
@@ -21,6 +21,7 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
abstract class BaseApiController extends AbstractController
|
||||
{
|
||||
public const MAX_PAGE_SIZE = 500;
|
||||
public const DATE_ONLY_FORMAT = 'yyyy-MM-dd';
|
||||
public const DATE_FORMAT = DateTimeType::HTML5_FORMAT;
|
||||
public const DATE_FORMAT_PHP = 'Y-m-d\TH:i:s';
|
||||
@@ -84,8 +85,8 @@ abstract class BaseApiController extends AbstractController
|
||||
$size = $all['size'];
|
||||
if (is_numeric($size)) {
|
||||
$size = (int) $size;
|
||||
if ($size < 1 || $size > 500) {
|
||||
throw new BadRequestHttpException('Size must be between 1 and 500');
|
||||
if ($size < 1 || $size > self::MAX_PAGE_SIZE) {
|
||||
throw new BadRequestHttpException('Size must be between 1 and ' . self::MAX_PAGE_SIZE);
|
||||
}
|
||||
$query->setPageSize($size);
|
||||
}
|
||||
|
||||
@@ -23,16 +23,12 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
#[OA\Tag(name: 'Default')]
|
||||
final class ConfigurationController extends BaseApiController
|
||||
{
|
||||
public function __construct(private readonly ViewHandlerInterface $viewHandler)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch timesheet configuration
|
||||
*/
|
||||
#[OA\Response(response: 200, description: 'Returns the instance specific timesheet configuration', content: new OA\JsonContent(ref: new Model(type: TimesheetConfig::class)))]
|
||||
#[Route(path: '/config/timesheet', methods: ['GET'])]
|
||||
public function timesheetConfigAction(SystemConfiguration $configuration): Response
|
||||
public function timesheetConfigAction(SystemConfiguration $configuration, ViewHandlerInterface $viewHandler): Response
|
||||
{
|
||||
$model = new TimesheetConfig();
|
||||
$model->setTrackingMode($configuration->getTimesheetTrackingMode());
|
||||
@@ -44,7 +40,7 @@ final class ConfigurationController extends BaseApiController
|
||||
$view = new View($model, 200);
|
||||
$view->getContext()->setGroups(['Default', 'Config']);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
return $viewHandler->handle($view);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,11 +48,11 @@ final class ConfigurationController extends BaseApiController
|
||||
*/
|
||||
#[OA\Response(response: 200, description: 'Returns the configured color codes and names', content: new OA\JsonContent(type: 'object', example: ['Red' => '#ff0000'], additionalProperties: new OA\AdditionalProperties(type: 'string')))]
|
||||
#[Route(path: '/config/colors', methods: ['GET'])]
|
||||
public function colorConfigAction(SystemConfiguration $configuration): Response
|
||||
public function colorConfigAction(SystemConfiguration $configuration, ViewHandlerInterface $viewHandler): Response
|
||||
{
|
||||
$view = new View($configuration->getThemeColors(), 200);
|
||||
$view->getContext()->setGroups(['Default']);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
return $viewHandler->handle($view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ use App\Customer\CustomerService;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\CustomerRate;
|
||||
use App\Entity\User;
|
||||
use App\Event\CustomerMetaDefinitionEvent;
|
||||
use App\Form\API\CustomerApiEditForm;
|
||||
use App\Form\API\CustomerRateApiForm;
|
||||
use App\Repository\CustomerRateRepository;
|
||||
@@ -25,7 +24,6 @@ use FOS\RestBundle\Request\ParamFetcherInterface;
|
||||
use FOS\RestBundle\View\View;
|
||||
use FOS\RestBundle\View\ViewHandlerInterface;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -45,7 +43,6 @@ final class CustomerController extends BaseApiController
|
||||
public function __construct(
|
||||
private readonly ViewHandlerInterface $viewHandler,
|
||||
private readonly CustomerRepository $repository,
|
||||
private readonly EventDispatcherInterface $dispatcher,
|
||||
private readonly CustomerRateRepository $customerRateRepository,
|
||||
private readonly CustomerService $customerService,
|
||||
) {
|
||||
@@ -59,7 +56,7 @@ final class CustomerController extends BaseApiController
|
||||
#[Rest\QueryParam(name: 'visible', requirements: '1|2|3', default: 1, strict: true, nullable: true, description: 'Visibility status to filter customers: 1=visible, 2=hidden, 3=both')]
|
||||
#[Rest\QueryParam(name: 'order', requirements: 'ASC|DESC', strict: true, nullable: true, description: 'The result order. Allowed values: ASC, DESC (default: ASC)')]
|
||||
#[Rest\QueryParam(name: 'orderBy', requirements: 'id|name', strict: true, nullable: true, description: 'The field by which results will be ordered. Allowed values: id, name (default: name)')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term', nullable: true)]
|
||||
public function cgetAction(ParamFetcherInterface $paramFetcher): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
@@ -125,9 +122,6 @@ final class CustomerController extends BaseApiController
|
||||
|
||||
$customer = $customerService->createNewCustomer('');
|
||||
|
||||
$event = new CustomerMetaDefinitionEvent($customer);
|
||||
$this->dispatcher->dispatch($event);
|
||||
|
||||
$form = $this->createForm(CustomerApiEditForm::class, $customer, [
|
||||
'include_budget' => $this->isGranted('budget', $customer),
|
||||
'include_time' => $this->isGranted('time', $customer),
|
||||
@@ -160,8 +154,7 @@ final class CustomerController extends BaseApiController
|
||||
#[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_customer', requirements: ['id' => '\d+'])]
|
||||
public function patchAction(Request $request, Customer $customer): Response
|
||||
{
|
||||
$event = new CustomerMetaDefinitionEvent($customer);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->customerService->loadMetaFields($customer);
|
||||
|
||||
$form = $this->createForm(CustomerApiEditForm::class, $customer, [
|
||||
'include_budget' => $this->isGranted('budget', $customer),
|
||||
@@ -216,8 +209,7 @@ final class CustomerController extends BaseApiController
|
||||
#[Rest\RequestParam(name: 'value', strict: true, nullable: false, description: 'The meta-field value')]
|
||||
public function metaAction(Customer $customer, ParamFetcherInterface $paramFetcher): Response
|
||||
{
|
||||
$event = new CustomerMetaDefinitionEvent($customer);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->customerService->loadMetaFields($customer);
|
||||
|
||||
$name = $paramFetcher->get('name');
|
||||
$value = $paramFetcher->get('value');
|
||||
|
||||
@@ -23,12 +23,6 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
#[OA\Tag(name: 'Export')]
|
||||
final class ExportController extends BaseApiController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ViewHandlerInterface $viewHandler,
|
||||
private readonly ExportTemplateRepository $repository,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete export template
|
||||
*/
|
||||
@@ -36,12 +30,12 @@ final class ExportController extends BaseApiController
|
||||
#[OA\Delete(responses: [new OA\Response(response: 204, description: 'Delete export template')], x: ['internal' => true])]
|
||||
#[OA\Parameter(name: 'id', description: 'Export template ID to delete', in: 'path', required: true)]
|
||||
#[Route(path: '/{id}', name: 'delete_export_template', requirements: ['id' => '\d+'], methods: ['DELETE'])]
|
||||
public function deleteTemplate(ExportTemplate $exportTemplate): Response
|
||||
public function deleteTemplate(ExportTemplate $exportTemplate, ExportTemplateRepository $repository, ViewHandlerInterface $viewHandler): Response
|
||||
{
|
||||
$this->repository->removeExportTemplate($exportTemplate);
|
||||
$repository->removeExportTemplate($exportTemplate);
|
||||
|
||||
$view = new View(null, Response::HTTP_NO_CONTENT);
|
||||
|
||||
return $this->viewHandler->handle($view);
|
||||
return $viewHandler->handle($view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace App\API;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\ProjectRate;
|
||||
use App\Entity\User;
|
||||
use App\Event\ProjectMetaDefinitionEvent;
|
||||
use App\Form\API\ProjectApiEditForm;
|
||||
use App\Form\API\ProjectRateApiForm;
|
||||
use App\Project\ProjectService;
|
||||
@@ -26,7 +25,6 @@ use FOS\RestBundle\Request\ParamFetcherInterface;
|
||||
use FOS\RestBundle\View\View;
|
||||
use FOS\RestBundle\View\ViewHandlerInterface;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -47,7 +45,6 @@ final class ProjectController extends BaseApiController
|
||||
public function __construct(
|
||||
private readonly ViewHandlerInterface $viewHandler,
|
||||
private readonly ProjectRepository $repository,
|
||||
private readonly EventDispatcherInterface $dispatcher,
|
||||
private readonly ProjectRateRepository $projectRateRepository,
|
||||
private readonly ProjectService $projectService
|
||||
) {
|
||||
@@ -67,7 +64,7 @@ final class ProjectController extends BaseApiController
|
||||
#[Rest\QueryParam(name: 'globalActivities', requirements: '0|1', strict: true, nullable: true, description: "If given, filters projects by their 'global activity' support. Allowed values: 1 (supports global activities) and 0 (without global activities) (default: all)")]
|
||||
#[Rest\QueryParam(name: 'order', requirements: 'ASC|DESC', strict: true, nullable: true, description: 'The result order. Allowed values: ASC, DESC (default: ASC)')]
|
||||
#[Rest\QueryParam(name: 'orderBy', requirements: 'id|name|customer', strict: true, nullable: true, description: 'The field by which results will be ordered. Allowed values: id, name, customer (default: name)')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term', nullable: true)]
|
||||
public function cgetAction(ParamFetcherInterface $paramFetcher, CustomerRepository $customerRepository): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
@@ -212,8 +209,7 @@ final class ProjectController extends BaseApiController
|
||||
#[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_project', requirements: ['id' => '\d+'])]
|
||||
public function patchAction(Request $request, Project $project): Response
|
||||
{
|
||||
$event = new ProjectMetaDefinitionEvent($project);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->projectService->loadMetaFields($project);
|
||||
|
||||
$form = $this->createForm(ProjectApiEditForm::class, $project, [
|
||||
'timezone' => $this->getDateTimeFactory()->getTimezone()->getName(),
|
||||
@@ -270,8 +266,7 @@ final class ProjectController extends BaseApiController
|
||||
#[Rest\RequestParam(name: 'value', strict: true, nullable: false, description: 'The meta-field value')]
|
||||
public function metaAction(Project $project, ParamFetcherInterface $paramFetcher): Response
|
||||
{
|
||||
$event = new ProjectMetaDefinitionEvent($project);
|
||||
$this->dispatcher->dispatch($event);
|
||||
$this->projectService->loadMetaFields($project);
|
||||
|
||||
$name = $paramFetcher->get('name');
|
||||
$value = $paramFetcher->get('value');
|
||||
|
||||
@@ -92,7 +92,7 @@ final class TimesheetController extends BaseApiController
|
||||
#[Rest\QueryParam(name: 'active', requirements: '0|1', strict: true, nullable: true, description: 'Filter for running/active records. Allowed values: 0=stopped, 1=active (default: all)')]
|
||||
#[Rest\QueryParam(name: 'billable', requirements: '0|1', strict: true, nullable: true, description: 'Filter for non-/billable records. Allowed values: 0=non-billable, 1=billable (default: all)')]
|
||||
#[Rest\QueryParam(name: 'full', requirements: '0|1|true|false', strict: true, nullable: true, description: 'Allows to fetch full objects including subresources. Allowed values: 0|1|false|true (default: false)')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term', nullable: true)]
|
||||
#[Rest\QueryParam(name: 'modified_after', requirements: [new Constraints\DateTime(format: 'Y-m-d\TH:i:s')], strict: true, nullable: true, description: 'Only records changed after this date will be included (format: HTML5 datetime-local, e.g. YYYY-MM-DDThh:mm:ss)')]
|
||||
public function cgetAction(ParamFetcherInterface $paramFetcher, CustomerRepository $customerRepository, ProjectRepository $projectRepository, ActivityRepository $activityRepository, UserRepository $userRepository): Response
|
||||
{
|
||||
|
||||
@@ -58,7 +58,7 @@ final class UserController extends BaseApiController
|
||||
#[Rest\QueryParam(name: 'visible', requirements: '1|2|3', default: 1, strict: true, nullable: true, description: 'Visibility status to filter users: 1=visible, 2=hidden, 3=all')]
|
||||
#[Rest\QueryParam(name: 'orderBy', requirements: 'id|username|alias|email', strict: true, nullable: true, description: 'The field by which results will be ordered. Allowed values: id, username, alias, email (default: username)')]
|
||||
#[Rest\QueryParam(name: 'order', requirements: 'ASC|DESC', strict: true, nullable: true, description: 'The result order. Allowed values: ASC, DESC (default: ASC)')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term')]
|
||||
#[Rest\QueryParam(name: 'term', description: 'Free search term', nullable: true)]
|
||||
#[Rest\QueryParam(name: 'full', requirements: '0|1|true|false', strict: true, nullable: true, description: 'Allows to fetch full objects including subresources. Allowed values: 0|1|false|true (default: false)')]
|
||||
public function cgetAction(ParamFetcherInterface $paramFetcher): Response
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user