composer prod dependencies and commands (#986)
This commit is contained in:
@@ -1,151 +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\Command;
|
||||
|
||||
use App\Entity\Timesheet;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use Doctrine\DBAL\Types\DateTimeType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
/**
|
||||
* This command was added with v0.8.
|
||||
* Kimai saved the DateTime before with the local timezone, which can cause big problems when used in different environments.
|
||||
* You should convert all timesheet records that were saved with Kimai 2 directly, but NOT the ones migrated from Kimai v1.
|
||||
*
|
||||
* Please read https://github.com/kevinpapst/kimai2/pull/372 to find out more!
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ConvertTimezoneCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var TimesheetRepository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @param TimesheetRepository $repository
|
||||
*/
|
||||
public function __construct(TimesheetRepository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('kimai:convert-timezone')
|
||||
->setDescription('Convert timesheet dates between timezones, only made for updates from 0.7 to 0.8')
|
||||
->setHelp('This command should only be required if you imported data from Kimai v1')
|
||||
->addOption('first-id', 'f', InputArgument::OPTIONAL, 'The database ID which should be converted first')
|
||||
->addOption('last-id', 'l', InputArgument::OPTIONAL, 'The database ID which should be converted last')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|string $start
|
||||
* @param null|string $end
|
||||
* @return Timesheet[]
|
||||
*/
|
||||
protected function getTimesheets($start = null, $end = null)
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('t');
|
||||
|
||||
$qb->select('t');
|
||||
if (!empty($start)) {
|
||||
$qb->andWhere($qb->expr()->gte('t.id', $start));
|
||||
}
|
||||
if (!empty($end)) {
|
||||
$qb->andWhere($qb->expr()->lte('t.id', $end));
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Timesheet $timesheet
|
||||
* @param \DateTimeZone $timeZone
|
||||
* @return Timesheet
|
||||
*/
|
||||
protected function convertTimesheet(Timesheet $timesheet, \DateTimeZone $timeZone): Timesheet
|
||||
{
|
||||
$oldTimezone = $timesheet->getTimezone();
|
||||
|
||||
if (null !== $timesheet->getBegin()) {
|
||||
$beginDate = clone $timesheet->getBegin();
|
||||
$beginDate->setTimezone($timeZone);
|
||||
$timesheet->setBegin($beginDate);
|
||||
}
|
||||
|
||||
if (null !== $timesheet->getEnd()) {
|
||||
$endDate = clone $timesheet->getEnd();
|
||||
$endDate->setTimezone($timeZone);
|
||||
$timesheet->setEnd($endDate);
|
||||
}
|
||||
|
||||
$timesheet->setTimezone($oldTimezone);
|
||||
|
||||
return $timesheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
Type::overrideType(Type::DATETIME, DateTimeType::class);
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$start = $input->getOption('first-id');
|
||||
$end = $input->getOption('last-id');
|
||||
|
||||
$result = $this->getTimesheets($start, $end);
|
||||
$amount = count($result);
|
||||
|
||||
$answer = $io->ask(sprintf('This will update %s timesheet records, continue (y/n) ? ', $amount), 'y');
|
||||
|
||||
if ('y' !== $answer) {
|
||||
$io->text('Aborting.');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$utc = new \DateTimeZone('UTC');
|
||||
$i = 0;
|
||||
|
||||
/** @var Timesheet $timesheet */
|
||||
foreach ($result as $timesheet) {
|
||||
$timesheet = $this->convertTimesheet($timesheet, $utc);
|
||||
$this->repository->save($timesheet);
|
||||
|
||||
if (++$i % 80 === 0) {
|
||||
$io->writeln('. (' . $i . '/' . $amount . ')');
|
||||
} else {
|
||||
$io->write('.');
|
||||
}
|
||||
}
|
||||
|
||||
$io->writeln('. (' . $i . '/' . $amount . ')');
|
||||
$io->writeln('');
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,14 @@ class CreateReleaseCommand extends Command
|
||||
->addOption('directory', null, InputOption::VALUE_OPTIONAL, 'Directory where the release package will be stored', 'var/data/')
|
||||
->addOption('release', null, InputOption::VALUE_OPTIONAL, 'The version that should be zipped', Constants::VERSION)
|
||||
;
|
||||
|
||||
/*
|
||||
* Hide this command in production.
|
||||
* Maybe it should be de-activated completely?!
|
||||
*/
|
||||
if (getenv('APP_ENV') === 'prod') {
|
||||
$this->setHidden(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use Exception;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
@@ -46,6 +47,17 @@ EOT
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that this command CANNOT be executed in production.
|
||||
* It can't work, as the fixtures bundle is not available in production.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return getenv('APP_ENV') !== 'prod';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
@@ -55,17 +67,11 @@ EOT
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
if (getenv('APP_ENV') === 'prod') {
|
||||
$io->error('kimai:reset-dev is not allowed in production');
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ($this->askConfirmation($input, $output, 'Do you want to create the database y/N ?')) {
|
||||
try {
|
||||
$command = $this->getApplication()->find('doctrine:database:create');
|
||||
$command->run(new ArrayInput([]), $output);
|
||||
} catch (\Exception $ex) {
|
||||
} catch (Exception $ex) {
|
||||
$io->error('Failed to create database: ' . $ex->getMessage());
|
||||
|
||||
return 1;
|
||||
@@ -76,7 +82,7 @@ EOT
|
||||
try {
|
||||
$command = $this->getApplication()->find('doctrine:schema:drop');
|
||||
$command->run(new ArrayInput(['--force' => true]), $output);
|
||||
} catch (\Exception $ex) {
|
||||
} catch (Exception $ex) {
|
||||
$io->error('Failed to drop database schema: ' . $ex->getMessage());
|
||||
|
||||
return 2;
|
||||
@@ -85,7 +91,7 @@ EOT
|
||||
try {
|
||||
$command = $this->getApplication()->find('doctrine:schema:create');
|
||||
$command->run(new ArrayInput([]), $output);
|
||||
} catch (\Exception $ex) {
|
||||
} catch (Exception $ex) {
|
||||
$io->error('Failed to create database schema: ' . $ex->getMessage());
|
||||
|
||||
return 3;
|
||||
@@ -97,7 +103,7 @@ EOT
|
||||
$cmdInput = new ArrayInput([]);
|
||||
$cmdInput->setInteractive(false);
|
||||
$command->run($cmdInput, $output);
|
||||
} catch (\Exception $ex) {
|
||||
} catch (Exception $ex) {
|
||||
$io->error('Failed to import fixtures: ' . $ex->getMessage());
|
||||
|
||||
return 4;
|
||||
@@ -108,7 +114,7 @@ EOT
|
||||
$cmdInput = new ArrayInput(['--add' => true, '--all' => true]);
|
||||
$cmdInput->setInteractive(false);
|
||||
$command->run($cmdInput, $output);
|
||||
} catch (\Exception $ex) {
|
||||
} catch (Exception $ex) {
|
||||
$io->error('Failed to set migration status: ' . $ex->getMessage());
|
||||
|
||||
return 5;
|
||||
@@ -118,7 +124,7 @@ EOT
|
||||
$command = $this->getApplication()->find('cache:clear');
|
||||
try {
|
||||
$command->run(new ArrayInput([]), $output);
|
||||
} catch (\Exception $ex) {
|
||||
} catch (Exception $ex) {
|
||||
$io->error('Failed to clear cache: ' . $ex->getMessage());
|
||||
|
||||
return 6;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
@@ -48,7 +50,7 @@ class Timesheet implements EntityWithMetaFields
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
* @var DateTime
|
||||
*
|
||||
* @ORM\Column(name="start_time", type="datetime", nullable=false)
|
||||
* @Assert\NotNull()
|
||||
@@ -56,7 +58,7 @@ class Timesheet implements EntityWithMetaFields
|
||||
private $begin;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
* @var DateTime
|
||||
*
|
||||
* @ORM\Column(name="end_time", type="datetime", nullable=true)
|
||||
*/
|
||||
@@ -188,17 +190,17 @@ class Timesheet implements EntityWithMetaFields
|
||||
}
|
||||
|
||||
if (null !== $this->begin) {
|
||||
$this->begin->setTimeZone(new \DateTimeZone($this->timezone));
|
||||
$this->begin->setTimeZone(new DateTimeZone($this->timezone));
|
||||
}
|
||||
|
||||
if (null !== $this->end) {
|
||||
$this->end->setTimeZone(new \DateTimeZone($this->timezone));
|
||||
$this->end->setTimeZone(new DateTimeZone($this->timezone));
|
||||
}
|
||||
|
||||
$this->localized = true;
|
||||
}
|
||||
|
||||
public function getBegin(): ?\DateTime
|
||||
public function getBegin(): ?DateTime
|
||||
{
|
||||
$this->localizeDates();
|
||||
|
||||
@@ -206,10 +208,10 @@ class Timesheet implements EntityWithMetaFields
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $begin
|
||||
* @param DateTime $begin
|
||||
* @return Timesheet
|
||||
*/
|
||||
public function setBegin(\DateTime $begin): Timesheet
|
||||
public function setBegin(DateTime $begin): Timesheet
|
||||
{
|
||||
$this->begin = $begin;
|
||||
$this->timezone = $begin->getTimezone()->getName();
|
||||
@@ -217,7 +219,7 @@ class Timesheet implements EntityWithMetaFields
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEnd(): ?\DateTime
|
||||
public function getEnd(): ?DateTime
|
||||
{
|
||||
$this->localizeDates();
|
||||
|
||||
@@ -225,10 +227,10 @@ class Timesheet implements EntityWithMetaFields
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTime $end
|
||||
* @param DateTime $end
|
||||
* @return Timesheet
|
||||
*/
|
||||
public function setEnd(?\DateTime $end): Timesheet
|
||||
public function setEnd(?DateTime $end): Timesheet
|
||||
{
|
||||
$this->end = $end;
|
||||
|
||||
@@ -422,10 +424,10 @@ class Timesheet implements EntityWithMetaFields
|
||||
}
|
||||
|
||||
/**
|
||||
* BE WARNED: this method should NOT be used programmatically, there is very likely no reason for it!
|
||||
* BE WARNED: this method should NOT be used.
|
||||
* It was ONLY introduced for the command "kimai:import-v1".
|
||||
*
|
||||
* @internal
|
||||
* @deprecated since it was introduced, only meant for the initial migration. Will be removed with 1.0.
|
||||
* @param string $timezone
|
||||
* @return Timesheet
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user