composer prod dependencies and commands (#986)
This commit is contained in:
@@ -5,9 +5,6 @@ cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
|
||||
services:
|
||||
- mysql
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- stage: Code quality
|
||||
@@ -41,6 +38,8 @@ matrix:
|
||||
env: CODECOVERAGE=0 DB=mariadb
|
||||
addons:
|
||||
mariadb: '10.2'
|
||||
services:
|
||||
- mysql
|
||||
before_script:
|
||||
- mysql -u root -e 'CREATE USER IF NOT EXISTS travis@localhost; GRANT ALL ON *.* TO travis@localhost;'
|
||||
- stage: Test
|
||||
@@ -48,6 +47,8 @@ matrix:
|
||||
env: CODECOVERAGE=0 DB=mariadb
|
||||
addons:
|
||||
mariadb: '10.2'
|
||||
services:
|
||||
- mysql
|
||||
before_script:
|
||||
- mysql -u root -e 'CREATE USER IF NOT EXISTS travis@localhost; GRANT ALL ON *.* TO travis@localhost;'
|
||||
- stage: Code coverage
|
||||
|
||||
10
UPGRADING.md
10
UPGRADING.md
@@ -5,10 +5,14 @@ _Make sure to create a backup before you start!_
|
||||
Read the [updates documentation](https://www.kimai.org/documentation/updates.html) to find out how
|
||||
you can upgrade your Kimai installation to the latest stable release.
|
||||
|
||||
**Before you leave ...**
|
||||
Check below if there are more version specific steps required, which need to be executed after the normal update process.
|
||||
Perform EACH version specific task between your version and the new one, otherwise you risk data inconsistency or a broken installation.
|
||||
|
||||
There might be more steps required which are version specific and need to be executed after [the update](https://www.kimai.org/documentation/updates.html).
|
||||
Read and perform EACH version specific task below, otherwise you risk data inconsistency or a broken installation!
|
||||
## [1.2](https://github.com/kevinpapst/kimai2/releases/tag/1.2)
|
||||
|
||||
### BC breaks
|
||||
|
||||
Deleted timezone conversion command. If you are still using 0.7 or below, you need to upgrade to 1.1 before upgrading to this version.
|
||||
|
||||
## [1.1](https://github.com/kevinpapst/kimai2/releases/tag/1.1)
|
||||
|
||||
|
||||
@@ -18,11 +18,9 @@
|
||||
"ext-pdo": "*",
|
||||
"ext-zip": "*",
|
||||
"beberlei/doctrineextensions": "^1.2",
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.0",
|
||||
"erusev/parsedown": "^1.6",
|
||||
"friendsofsymfony/rest-bundle": "^2.3",
|
||||
"friendsofsymfony/user-bundle": "~2.0",
|
||||
"fzaninotto/faker": "^1.8",
|
||||
"gedmo/doctrine-extensions": "^2.4",
|
||||
"jms/metadata": "^2.0",
|
||||
"jms/serializer-bundle": "^3.2",
|
||||
@@ -45,10 +43,8 @@
|
||||
"symfony/form": "^4.0",
|
||||
"symfony/framework-bundle": "^4.0",
|
||||
"symfony/intl": "^4.0",
|
||||
"symfony/maker-bundle": "^1.0",
|
||||
"symfony/monolog-bundle": "^3.1",
|
||||
"symfony/orm-pack": "^1.0",
|
||||
"symfony/profiler-pack": "^1.0",
|
||||
"symfony/security-bundle": "~4.2.0",
|
||||
"symfony/security-csrf": "^4.0",
|
||||
"symfony/serializer": "^4.0",
|
||||
@@ -56,7 +52,6 @@
|
||||
"symfony/translation": "^4.0",
|
||||
"symfony/twig-bundle": "^4.0",
|
||||
"symfony/validator": "^4.0",
|
||||
"symfony/web-server-bundle": "^4.0",
|
||||
"symfony/webpack-encore-bundle": "^1.5",
|
||||
"symfony/yaml": "^4.0",
|
||||
"twig/extensions": "^1.5",
|
||||
@@ -64,7 +59,9 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"dama/doctrine-test-bundle": "^5.0",
|
||||
"doctrine/doctrine-fixtures-bundle": "^3.2",
|
||||
"friendsofphp/php-cs-fixer": "^2.10",
|
||||
"fzaninotto/faker": "^1.8",
|
||||
"phpstan/phpstan": "^0.11.7",
|
||||
"phpstan/phpstan-doctrine": "^0.11.4",
|
||||
"phpstan/phpstan-phpunit": "^0.11.2",
|
||||
@@ -72,8 +69,11 @@
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"symfony/browser-kit": "^4.0",
|
||||
"symfony/css-selector": "^4.0",
|
||||
"symfony/maker-bundle": "^1.12",
|
||||
"symfony/phpunit-bridge": "^4.0",
|
||||
"symfony/thanks": "^1.0"
|
||||
"symfony/profiler-pack": "^1.0",
|
||||
"symfony/thanks": "^1.0",
|
||||
"symfony/web-server-bundle": "~4.2.0"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
|
||||
1158
composer.lock
generated
1158
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -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