fix migration for MySQL (#430)

This commit is contained in:
Kevin Papst
2018-11-19 15:24:00 +01:00
committed by GitHub
parent 40322c6de4
commit 67dc1c7640
5 changed files with 94 additions and 18 deletions

View File

@@ -247,7 +247,7 @@ class KimaiImporterCommand extends Command
$allImports += $counter;
$io->success('Imported users: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import users: ' . $ex->getMessage());
$io->error('Failed to import users: ' . $ex->getMessage() . PHP_EOL . $ex->getTraceAsString());
return;
}
@@ -257,7 +257,7 @@ class KimaiImporterCommand extends Command
$allImports += $counter;
$io->success('Imported customers: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import customers: ' . $ex->getMessage());
$io->error('Failed to import customers: ' . $ex->getMessage() . PHP_EOL . $ex->getTraceAsString());
return;
}
@@ -267,7 +267,7 @@ class KimaiImporterCommand extends Command
$allImports += $counter;
$io->success('Imported projects: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import projects: ' . $ex->getMessage());
$io->error('Failed to import projects: ' . $ex->getMessage() . PHP_EOL . $ex->getTraceAsString());
return;
}
@@ -277,7 +277,7 @@ class KimaiImporterCommand extends Command
$allImports += $counter;
$io->success('Imported activities: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import activities: ' . $ex->getMessage());
$io->error('Failed to import activities: ' . $ex->getMessage() . PHP_EOL . $ex->getTraceAsString());
return;
}
@@ -287,7 +287,7 @@ class KimaiImporterCommand extends Command
$allImports += $counter;
$io->success('Imported timesheet records: ' . $counter);
} catch (\Exception $ex) {
$io->error('Failed to import timesheet records: ' . $ex->getMessage());
$io->error('Failed to import timesheet records: ' . $ex->getMessage() . PHP_EOL . $ex->getTraceAsString());
return;
}
@@ -385,8 +385,10 @@ class KimaiImporterCommand extends Command
protected function bytesHumanReadable($size)
{
$unit = ['b', 'kB', 'MB', 'GB'];
$i = floor(log($size, 1024));
$a = (int) $i;
return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i];
return @round($size / pow(1024, $i), 2) . ' ' . $unit[$a];
}
/**
@@ -422,12 +424,8 @@ class KimaiImporterCommand extends Command
if ($errors->count() > 0) {
/** @var \Symfony\Component\Validator\ConstraintViolation $error */
foreach ($errors as $error) {
$value = $error->getInvalidValue();
$io->error(
$error->getPropertyPath()
. ' (' . (is_array($value) ? implode(',', $value) : $value) . ')'
. "\n "
. $error->getMessage()
(string) $error
);
}
@@ -941,7 +939,7 @@ class KimaiImporterCommand extends Command
;
if (!$this->validateImport($io, $timesheet)) {
throw new \Exception('Failed to validate timesheet record: ' . $timesheet->getId());
throw new \Exception('Failed to validate timesheet record: ' . $oldRecord['timeEntryID']);
}
try {
@@ -952,8 +950,7 @@ class KimaiImporterCommand extends Command
}
++$counter;
} catch (\Exception $ex) {
$io->error('Failed to create timesheet record: ' . $timesheet->getId());
$io->error('Reason: ' . $ex->getMessage());
$io->error('Failed to create timesheet record: ' . $ex->getMessage());
}
$io->write('.');

View File

@@ -376,21 +376,21 @@ class Timesheet
->addViolation();
}
if ($activity->getVisible() === false) {
if (null === $this->getEnd() && $activity->getVisible() === false) {
$context->buildViolation('Cannot start a disabled activity.')
->atPath('activity')
->setTranslationDomain('validators')
->addViolation();
}
if ($project->getVisible() === false) {
if (null === $this->getEnd() && $project->getVisible() === false) {
$context->buildViolation('Cannot start a disabled project.')
->atPath('project')
->setTranslationDomain('validators')
->addViolation();
}
if ($project->getCustomer()->getVisible() === false) {
if (null === $this->getEnd() && $project->getCustomer()->getVisible() === false) {
$context->buildViolation('Cannot start a disabled customer.')
->atPath('customer')
->setTranslationDomain('validators')

View File

@@ -56,10 +56,11 @@ final class Version20181031220003 extends AbstractMigration
$this->addSql('CREATE INDEX IDX_4F60C6B1166D1F9C ON ' . $timesheet . ' (project_id)');
} else {
// project table
$this->addSql('ALTER TABLE ' . $projects . ' DROP FOREIGN KEY FK_407F12069395C3F3');
$this->addSql('ALTER TABLE ' . $projects . ' CHANGE customer_id customer_id INT NOT NULL');
$this->addSql('ALTER TABLE ' . $projects . ' ADD CONSTRAINT FK_407F12069395C3F3 FOREIGN KEY (customer_id) REFERENCES ' . $customers . ' (id) ON DELETE CASCADE');
// timesheet table
$this->addSql('ALTER TABLE ' . $timesheet . ' ADD project_id INT DEFAULT NULL AFTER activity_id');
$this->addSql('ALTER TABLE ' . $timesheet . ' ADD CONSTRAINT FK_4F60C6B1166D1F9C FOREIGN KEY (project_id) REFERENCES ' . $projects . ' (id) ON DELETE CASCADE');
$this->addSql('CREATE INDEX IDX_4F60C6B1166D1F9C ON ' . $timesheet . ' (project_id)');
}
@@ -80,7 +81,12 @@ final class Version20181031220003 extends AbstractMigration
$this->addSql('CREATE INDEX IDX_4F60C6B18D93D649 ON ' . $timesheet . ' (user)');
$this->addSql('CREATE INDEX IDX_4F60C6B1166D1F9C ON ' . $timesheet . ' (project_id)');
} else {
$this->addSql('ALTER TABLE ' . $timesheet . ' DROP FOREIGN KEY FK_4F60C6B18D93D649');
$this->addSql('ALTER TABLE ' . $timesheet . ' DROP FOREIGN KEY FK_4F60C6B181C06096');
$this->addSql('ALTER TABLE ' . $timesheet . ' CHANGE project_id project_id INT NOT NULL, CHANGE user user INT NOT NULL, CHANGE activity_id activity_id INT NOT NULL');
$this->addSql('ALTER TABLE ' . $timesheet . ' ADD CONSTRAINT FK_4F60C6B1166D1F9C FOREIGN KEY (project_id) REFERENCES ' . $projects . ' (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE ' . $timesheet . ' ADD CONSTRAINT FK_4F60C6B18D93D649 FOREIGN KEY (user) REFERENCES ' . $users . ' (id) ON DELETE CASCADE');
$this->addSql('ALTER TABLE ' . $timesheet . ' ADD CONSTRAINT FK_4F60C6B181C06096 FOREIGN KEY (activity_id) REFERENCES ' . $activities . ' (id) ON DELETE CASCADE');
}
}
@@ -94,6 +100,7 @@ final class Version20181031220003 extends AbstractMigration
$timesheet = $this->getTableName('timesheet');
$projects = $this->getTableName('projects');
$customers = $this->getTableName('customers');
if ($platform === 'sqlite') {
// project table
@@ -117,7 +124,9 @@ final class Version20181031220003 extends AbstractMigration
$this->addSql('CREATE INDEX IDX_4F60C6B181C06096 ON ' . $timesheet . ' (activity_id)');
} else {
// project table
$this->addSql('ALTER TABLE ' . $projects . ' DROP FOREIGN KEY FK_407F12069395C3F3');
$this->addSql('ALTER TABLE ' . $projects . ' CHANGE customer_id customer_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE ' . $projects . ' ADD CONSTRAINT FK_407F12069395C3F3 FOREIGN KEY (customer_id) REFERENCES ' . $customers . ' (id) ON DELETE CASCADE');
// timesheet table
$this->addSql('ALTER TABLE ' . $timesheet . ' DROP FOREIGN KEY FK_4F60C6B1166D1F9C');
$this->addSql('DROP INDEX IDX_4F60C6B1166D1F9C ON ' . $timesheet);

View File

@@ -121,6 +121,24 @@ class TimesheetTest extends AbstractEntityTest
$this->assertHasViolationForField($entity, 'customer');
}
public function testValidationCustomerInvisibleDoesNotTriggerOnStoppedEntites()
{
$customer = (new Customer())->setVisible(false);
$project = (new Project())->setName('foo')->setCustomer($customer);
$activity = (new Activity())->setName('hello-world')->setProject($project);
$entity = new Timesheet();
$entity
->setUser(new User())
->setActivity($activity)
->setProject($project)
->setBegin(new \DateTime())
->setEnd(new \DateTime())
;
$this->assertHasNoViolations($entity);
}
public function testValidationProjectInvisible()
{
$customer = new Customer();
@@ -138,6 +156,24 @@ class TimesheetTest extends AbstractEntityTest
$this->assertHasViolationForField($entity, 'project');
}
public function testValidationProjectInvisibleDoesNotTriggerOnStoppedEntites()
{
$customer = new Customer();
$project = (new Project())->setName('foo')->setCustomer($customer)->setVisible(false);
$activity = (new Activity())->setName('hello-world')->setProject($project);
$entity = new Timesheet();
$entity
->setUser(new User())
->setActivity($activity)
->setProject($project)
->setBegin(new \DateTime())
->setEnd(new \DateTime())
;
$this->assertHasNoViolations($entity);
}
public function testValidationActivityInvisible()
{
$customer = new Customer();
@@ -155,6 +191,24 @@ class TimesheetTest extends AbstractEntityTest
$this->assertHasViolationForField($entity, 'activity');
}
public function testValidationActivityInvisibleDoesNotTriggerOnStoppedEntites()
{
$customer = new Customer();
$project = (new Project())->setName('foo')->setCustomer($customer);
$activity = (new Activity())->setName('hello-world')->setProject($project)->setVisible(false);
$entity = new Timesheet();
$entity
->setUser(new User())
->setActivity($activity)
->setProject($project)
->setBegin(new \DateTime())
->setEnd(new \DateTime())
;
$this->assertHasNoViolations($entity);
}
public function testValidationEndNotEarlierThanBegin()
{
$entity = $this->getEntity();

View File

@@ -42,3 +42,19 @@ SQLite is a great database engine for testing, but when it comes to production u
- It does not support ALTER TABLE commands and makes update procedures very clunky and problematic/errorsome (we still try to support updates, but they are heavy on large databases)
- It does not support FOREIGN KEY constraints out of the box, which can lead to critical bugs when deleting activities/projects/customers
## Dotenv::populate() must be an instance of Symfony\\Component\\Dotenv\\void
If you encounter an error like this:
```
PHP Fatal error: Uncaught TypeError: Return value of Symfony\\Component\\Dotenv\\Dotenv::populate() must be an instance of Symfony\\Component\\Dotenv\\void, none returned in /var/www/kimai2/vendor/symfony/dotenv/Dotenv.php:95
Stack trace:
#0 /var/www/kimai2/vendor/symfony/dotenv/Dotenv.php(57): Symfony\\Component\\Dotenv\\Dotenv->populate(Array)
#1 /var/www//kimai2/public/index.php(15): Symfony\\Component\\Dotenv\\Dotenv->load('/var/www/html/k...')
#2 {main}\n thrown in /var/www/kimai2/vendor/symfony/dotenv/Dotenv.php on line 95
```
you are running PHP 7.0. Probably you were able to install Kimai v2, because your PHP-CLI uses a different PHP version than your webserver.
Upgrade PHP and the error will be gone.