added begin, end and export filter for API timesheets (#639)

This commit is contained in:
Kevin Papst
2019-03-14 03:34:54 +01:00
committed by GitHub
parent 2e6f3ed864
commit bde791fa55
28 changed files with 993 additions and 86 deletions

View File

@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
/*
* 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\API;
use App\API\Model\I18n;
use App\Configuration\LanguageFormattings;
use App\Entity\User;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use Swagger\Annotations as SWG;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class ConfigurationController extends Controller
{
/**
* @var ViewHandlerInterface
*/
protected $viewHandler;
/**
* @var LanguageFormattings
*/
protected $formats;
/**
* @param ViewHandlerInterface $viewHandler
* @param LanguageFormattings $formats
*/
public function __construct(ViewHandlerInterface $viewHandler, LanguageFormattings $formats)
{
$this->viewHandler = $viewHandler;
$this->formats = $formats;
}
/**
* @SWG\Response(
* response=200,
* description="Returns the locale specific configurations for this user",
* @SWG\Schema(ref="#/definitions/I18nConfig")
* )
*
* @Rest\Get(path="/config/i18n")
*/
public function i18nAction()
{
/** @var User $user */
$user = $this->getUser();
$locale = $user->getLocale();
$model = new I18n();
$model
->setFormDateTime($this->formats->getDateTimeTypeFormat($locale))
->setFormDate($this->formats->getDateTypeFormat($locale))
->setDateTime($this->formats->getDateTimeFormat($locale))
->setDate($this->formats->getDateFormat($locale))
->setDuration($this->formats->getDurationFormat($locale))
->setTime($this->formats->getTimeFormat($locale))
->setIs24hours($this->formats->isTwentyFourHours($locale))
;
$view = new View($model, 200);
$view->getContext()->setGroups(['Default', 'Config']);
return $this->viewHandler->handle($view);
}
}

190
src/API/Model/I18n.php Normal file
View File

@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
/*
* 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\API\Model;
class I18n
{
/**
* Format used for 'begin' and 'end' in TimesheetEditForm: POST, PATCH
*
* @var string
*/
protected $formDateTime = '';
/**
* Format used for Timesheet queries in: GET
*
* @var string
*/
protected $formDate = '';
/**
* Format used to display date-time values (see PHP function date_format)
*
* @var string
*/
protected $dateTime = '';
/**
* Format used to display date values (see PHP function date_format)
*
* @var string
*/
protected $date = '';
/**
* Format used to display times (see PHP function date_format)
*
* @var string
*/
protected $time = '';
/**
* Format used to display durations (replace: %h with hours, %m with minutes, %s with seconds)
*
* @var string
*/
protected $duration = '';
/**
* Whether a twenty-four hour format is used (true) or 12-hours AM/PM format (false)
* @var bool
*/
protected $is24hours = true;
/**
* @return string
*/
public function getFormDateTime(): string
{
return $this->formDateTime;
}
/**
* @param string $formDateTime
* @return I18n
*/
public function setFormDateTime(string $formDateTime)
{
$this->formDateTime = $formDateTime;
return $this;
}
/**
* @return string
*/
public function getFormDate(): string
{
return $this->formDate;
}
/**
* @param string $formDate
* @return I18n
*/
public function setFormDate(string $formDate)
{
$this->formDate = $formDate;
return $this;
}
/**
* @return string
*/
public function getDateTime(): string
{
return $this->dateTime;
}
/**
* @param string $dateTime
* @return I18n
*/
public function setDateTime(string $dateTime)
{
$this->dateTime = $dateTime;
return $this;
}
/**
* @return string
*/
public function getDate(): string
{
return $this->date;
}
/**
* @param string $date
* @return I18n
*/
public function setDate(string $date)
{
$this->date = $date;
return $this;
}
/**
* @return string
*/
public function getDuration(): string
{
return $this->duration;
}
/**
* @param string $duration
* @return I18n
*/
public function setDuration(string $duration)
{
$this->duration = $duration;
return $this;
}
/**
* @return string
*/
public function getTime(): string
{
return $this->time;
}
/**
* @param string $time
* @return I18n
*/
public function setTime(string $time)
{
$this->time = $time;
return $this;
}
/**
* @return bool
*/
public function isIs24hours(): bool
{
return $this->is24hours;
}
/**
* @param bool $is24hours
* @return I18n
*/
public function setIs24hours(bool $is24hours)
{
$this->is24hours = $is24hours;
return $this;
}
}

View File

@@ -26,6 +26,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Constraints;
/**
* @RouteResource("Timesheet")
@@ -84,6 +85,9 @@ class TimesheetController extends BaseApiController
* @Rest\QueryParam(name="size", requirements="\d+", strict=true, nullable=true, description="The amount of entries for each page (default: 25)")
* @Rest\QueryParam(name="order", requirements="ASC|DESC", strict=true, nullable=true, description="The result order (allowed values: 'ASC', 'DESC')")
* @Rest\QueryParam(name="orderBy", requirements="id|begin|end|rate", strict=true, nullable=true, description="The field by which results will be ordered (allowed values: 'id', 'begin', 'end', 'rate')")
* @Rest\QueryParam(name="begin", requirements=@Constraints\DateTime, strict=true, nullable=true, description="Only records after this date will be included (format: Y-m-d H:i:s)")
* @Rest\QueryParam(name="end", requirements=@Constraints\DateTime, strict=true, nullable=true, description="Only records before this date will be included (format: Y-m-d H:i:s)")
* @Rest\QueryParam(name="exported", requirements="0|1", strict=true, nullable=true, description="Use this flag if you want to filter for export state (0=not exported, 1=exported, null=all")
*
* @Security("is_granted('view_own_timesheet') or is_granted('view_other_timesheet')")
*
@@ -130,6 +134,23 @@ class TimesheetController extends BaseApiController
$query->setOrderBy($orderBy);
}
if (null !== ($begin = $paramFetcher->get('begin'))) {
$query->setBegin(new \DateTime($begin));
}
if (null !== ($end = $paramFetcher->get('end'))) {
$query->setEnd(new \DateTime($end));
}
if (null !== ($exported = $paramFetcher->get('exported'))) {
$exported = (int) $exported;
if ($exported === 1) {
$query->setExported(TimesheetQuery::STATE_EXPORTED);
} elseif ($exported === 0) {
$query->setExported(TimesheetQuery::STATE_NOT_EXPORTED);
}
}
/** @var Pagerfanta $data */
$data = $this->repository->findByQuery($query);
$data = (array) $data->getCurrentPageResults();

View File

@@ -0,0 +1,153 @@
<?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\Configuration;
class LanguageFormattings
{
/**
* @var array
*/
protected $settings;
/**
* @param array $languageSettings
*/
public function __construct(array $languageSettings)
{
$this->settings = $languageSettings;
}
/**
* Returns an array with all available locale/language codes.
*
* @return string[]
*/
public function getAvailableLanguages(): array
{
return array_keys($this->settings);
}
/**
* Returns the format which is used by the form component to handle date values.
*
* @param string $locale
* @return string
*/
public function getDateTypeFormat(string $locale): string
{
return $this->getConfig('date_type', $locale);
}
/**
* Returns the format which is used by the Javascript component to handle date values.
*
* @param string $locale
* @return string
*/
public function getDatePickerFormat(string $locale): string
{
return $this->getConfig('date_picker', $locale);
}
/**
* Returns the format which is used by the form component to handle datetime values.
*
* @param string $locale
* @return string
*/
public function getDateTimeTypeFormat(string $locale): string
{
return $this->getConfig('date_time_type', $locale);
}
/**
* Returns the format which is used by the Javascript component to handle datetime values.
*
* @param string $locale
* @return string
*/
public function getDateTimePickerFormat(string $locale): string
{
return $this->getConfig('date_time_picker', $locale);
}
/**
* Returns the locale specific date format, which should be used in combination with the twig filter "|date".
*
* @param string $locale
* @return string
*/
public function getDateFormat(string $locale): string
{
return $this->getConfig('date', $locale);
}
/**
* Returns the locale specific time format, which should be used in combination with the twig filter "|time".
*
* @param string $locale
* @return string
*/
public function getTimeFormat(string $locale): string
{
return $this->getConfig('time', $locale);
}
/**
* Returns the locale specific datetime format, which should be used in combination with the twig filter "|date".
*
* @param string $locale
* @return string
*/
public function getDateTimeFormat(string $locale): string
{
return $this->getConfig('date_time', $locale);
}
/**
* Returns the format used in the "|duration" twig filter to display a Timesheet duration.
*
* @param string $locale
* @return string
*/
public function getDurationFormat(string $locale): string
{
return $this->getConfig('duration', $locale);
}
/**
* Returns whether this locale uses the 24 hour format.
*
* @param string $locale
* @return bool
*/
public function isTwentyFourHours(string $locale): bool
{
return (bool) $this->getConfig('24_hours', $locale);
}
/**
* @param string $key
* @param string $locale
* @return string
*/
protected function getConfig(string $key, string $locale): string
{
if (!isset($this->settings[$locale])) {
throw new \InvalidArgumentException(sprintf('Unknown locale given: %s', $locale));
}
if (!isset($this->settings[$locale][$key])) {
throw new \InvalidArgumentException(sprintf('Unknown setting for locale %s: %s', $locale, $key));
}
return $this->settings[$locale][$key];
}
}

View File

@@ -38,7 +38,9 @@ class User extends BaseUser implements UserInterface
public const ROLE_TEAMLEAD = 'ROLE_TEAMLEAD';
public const ROLE_ADMIN = 'ROLE_ADMIN';
public const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
public const DEFAULT_ROLE = self::ROLE_USER;
public const DEFAULT_LANGUAGE = 'en';
/**
* @var int
@@ -267,6 +269,14 @@ class User extends BaseUser implements UserInterface
return null;
}
/**
* @return string
*/
public function getLocale()
{
return $this->getPreferenceValue(UserPreference::LOCALE, User::DEFAULT_LANGUAGE);
}
/**
* @param string $name
* @param mixed $default

View File

@@ -30,6 +30,8 @@ class UserPreference
{
public const HOURLY_RATE = 'hourly_rate';
public const SKIN = 'skin';
public const LOCALE = 'language';
public const TIMEZONE = 'timezone';
/**
* @var int

View File

@@ -86,13 +86,13 @@ class UserPreferenceSubscriber implements EventSubscriberInterface
->addConstraint(new Range(['min' => 0])),
(new UserPreference())
->setName('timezone')
->setName(UserPreference::TIMEZONE)
->setValue(date_default_timezone_get())
->setType(TimezoneType::class),
(new UserPreference())
->setName('language')
->setValue('en')
->setName(UserPreference::LOCALE)
->setValue(User::DEFAULT_LANGUAGE)
->setType(LanguageType::class),
(new UserPreference())

View File

@@ -268,11 +268,17 @@ class TimesheetEditForm extends AbstractType
if ($options['include_rate']) {
$builder
->add('fixedRate', MoneyType::class, [
'documentation' => [
'type' => 'float'
],
'label' => 'label.fixedRate',
'required' => false,
'currency' => $currency,
])
->add('hourlyRate', MoneyType::class, [
'documentation' => [
'type' => 'float'
],
'label' => 'label.hourlyRate',
'required' => false,
'currency' => $currency,

View File

@@ -125,10 +125,19 @@ class DateRangeType extends AbstractType
$pattern = $this->formatToPattern($formatDate, $separator);
$builder->addModelTransformer(new CallbackTransformer(
function (DateRange $range) use ($formatDate, $separator) {
function ($range) use ($formatDate, $separator) {
if (null === $range) {
return '';
}
if (!($range instanceof DateRange)) {
throw new \InvalidArgumentException('Invalid DateRange given');
}
if (null === $range->getBegin()) {
return '';
}
$display = $range->getBegin()->format($formatDate);
if (null !== $range->getEnd()) {
$display .= $separator . $range->getEnd()->format($formatDate);

View File

@@ -9,14 +9,18 @@
namespace App\Utils;
use App\Configuration\LanguageFormattings;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Use this class, when you want information about formats for the "current request locale".
*/
class LocaleSettings
{
/**
* @var array
*/
protected $settings;
protected $formats;
/**
* @var string
@@ -25,15 +29,15 @@ class LocaleSettings
/**
* @param RequestStack $requestStack
* @param array $languageSettings
* @param LanguageFormattings $formats
*/
public function __construct(RequestStack $requestStack, array $languageSettings)
public function __construct(RequestStack $requestStack, LanguageFormattings $formats)
{
// It can be null in a console command
if (null !== $requestStack->getMasterRequest()) {
$this->locale = $requestStack->getMasterRequest()->getLocale();
}
$this->settings = $languageSettings;
$this->formats = $formats;
}
/**
@@ -43,7 +47,7 @@ class LocaleSettings
*/
public function getAvailableLanguages(): array
{
return array_keys($this->settings);
return $this->formats->getAvailableLanguages();
}
/**
@@ -59,121 +63,90 @@ class LocaleSettings
/**
* Returns the format which is used by the form component to handle date values.
*
* @param null|string $locale
* @return string
*/
public function getDateTypeFormat(?string $locale = null): string
public function getDateTypeFormat(): string
{
return $this->getConfigByLocaleAndKey('date_type', $locale);
return $this->formats->getDateTypeFormat($this->getLocale());
}
/**
* Returns the format which is used by the Javascript component to handle date values.
*
* @param null|string $locale
* @return string
*/
public function getDatePickerFormat(?string $locale = null): string
public function getDatePickerFormat(): string
{
return $this->getConfigByLocaleAndKey('date_picker', $locale);
return $this->formats->getDatePickerFormat($this->getLocale());
}
/**
* Returns the format which is used by the form component to handle datetime values.
*
* @param null|string $locale
* @return string
*/
public function getDateTimeTypeFormat(?string $locale = null): string
public function getDateTimeTypeFormat(): string
{
return $this->getConfigByLocaleAndKey('date_time_type', $locale);
return $this->formats->getDateTimeTypeFormat($this->getLocale());
}
/**
* Returns the format which is used by the Javascript component to handle datetime values.
*
* @param null|string $locale
* @return string
*/
public function getDateTimePickerFormat(?string $locale = null): string
public function getDateTimePickerFormat(): string
{
return $this->getConfigByLocaleAndKey('date_time_picker', $locale);
return $this->formats->getDateTimePickerFormat($this->getLocale());
}
/**
* Returns the locale specific date format, which should be used in combination with the twig filter "|date".
*
* @param null|string $locale
* @return string
*/
public function getDateFormat(?string $locale = null): string
public function getDateFormat(): string
{
return $this->getConfigByLocaleAndKey('date', $locale);
return $this->formats->getDateFormat($this->getLocale());
}
/**
* Returns the locale specific time format, which should be used in combination with the twig filter "|time".
*
* @param null|string $locale
* @return string
*/
public function getTimeFormat(?string $locale = null): string
public function getTimeFormat(): string
{
return $this->getConfigByLocaleAndKey('time', $locale);
return $this->formats->getTimeFormat($this->getLocale());
}
/**
* Returns the locale specific datetime format, which should be used in combination with the twig filter "|date".
*
* @param null|string $locale
* @return string
*/
public function getDateTimeFormat(?string $locale = null): string
public function getDateTimeFormat(): string
{
return $this->getConfigByLocaleAndKey('date_time', $locale);
return $this->formats->getDateTimeFormat($this->getLocale());
}
/**
* Returns the format used in the "|duration" twig filter to display a Timesheet duration.
*
* @param null|string $locale
* @return string
*/
public function getDurationFormat(?string $locale = null): string
public function getDurationFormat(): string
{
return $this->getConfigByLocaleAndKey('duration', $locale);
return $this->formats->getDurationFormat($this->getLocale());
}
/**
* Returns whether this locale uses the 24 hour format.
*
* @param null|string $locale
* @return bool
*/
public function isTwentyFourHours(?string $locale = null): bool
public function isTwentyFourHours(): bool
{
return (bool) $this->getConfigByLocaleAndKey('24_hours', $locale);
}
/**
* @param string $key
* @param null|string $locale
* @return string
*/
protected function getConfigByLocaleAndKey(string $key, ?string $locale = null): string
{
if (null === $locale) {
$locale = $this->getLocale();
}
if (!isset($this->settings[$locale])) {
throw new \InvalidArgumentException(sprintf('Unknown locale given: %s', $locale));
}
if (!isset($this->settings[$locale][$key])) {
throw new \InvalidArgumentException(sprintf('Unknown setting for locale %s: %s', $locale, $key));
}
return $this->settings[$locale][$key];
return $this->formats->isTwentyFourHours($this->getLocale());
}
}