fix migration for sqlite (#881)

This commit is contained in:
Kevin Papst
2019-06-30 15:16:44 +02:00
committed by GitHub
parent d8621f0b7a
commit 834a0a873f
7 changed files with 62 additions and 44 deletions

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace App\API; namespace App\API;
use App\Entity\Activity; use App\Entity\Activity;
use App\Event\ActivityMetaDefinitionEvent;
use App\Form\API\ActivityApiEditForm; use App\Form\API\ActivityApiEditForm;
use App\Repository\ActivityRepository; use App\Repository\ActivityRepository;
use App\Repository\Query\ActivityQuery; use App\Repository\Query\ActivityQuery;
@@ -23,7 +22,6 @@ use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface; use FOS\RestBundle\View\ViewHandlerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG; use Swagger\Annotations as SWG;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -43,16 +41,11 @@ class ActivityController extends BaseApiController
* @var ViewHandlerInterface * @var ViewHandlerInterface
*/ */
protected $viewHandler; protected $viewHandler;
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
public function __construct(ViewHandlerInterface $viewHandler, ActivityRepository $repository, EventDispatcherInterface $dispatcher) public function __construct(ViewHandlerInterface $viewHandler, ActivityRepository $repository)
{ {
$this->viewHandler = $viewHandler; $this->viewHandler = $viewHandler;
$this->repository = $repository; $this->repository = $repository;
$this->dispatcher = $dispatcher;
} }
/** /**
@@ -142,11 +135,6 @@ class ActivityController extends BaseApiController
throw new NotFoundException(); throw new NotFoundException();
} }
// make sure the fields are properly setup and we know, which meta fields
// should be exposed and which not
$event = new ActivityMetaDefinitionEvent($data);
$this->dispatcher->dispatch(ActivityMetaDefinitionEvent::class, $event);
$view = new View($data, 200); $view = new View($data, 200);
$view->getContext()->setGroups(['Default', 'Entity', 'Activity']); $view->getContext()->setGroups(['Default', 'Entity', 'Activity']);

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace App\API; namespace App\API;
use App\Entity\Customer; use App\Entity\Customer;
use App\Event\CustomerMetaDefinitionEvent;
use App\Form\API\CustomerApiEditForm; use App\Form\API\CustomerApiEditForm;
use App\Repository\CustomerRepository; use App\Repository\CustomerRepository;
use App\Repository\Query\CustomerQuery; use App\Repository\Query\CustomerQuery;
@@ -23,7 +22,6 @@ use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface; use FOS\RestBundle\View\ViewHandlerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG; use Swagger\Annotations as SWG;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -43,16 +41,11 @@ class CustomerController extends BaseApiController
* @var ViewHandlerInterface * @var ViewHandlerInterface
*/ */
protected $viewHandler; protected $viewHandler;
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
public function __construct(ViewHandlerInterface $viewHandler, CustomerRepository $repository, EventDispatcherInterface $dispatcher) public function __construct(ViewHandlerInterface $viewHandler, CustomerRepository $repository)
{ {
$this->viewHandler = $viewHandler; $this->viewHandler = $viewHandler;
$this->repository = $repository; $this->repository = $repository;
$this->dispatcher = $dispatcher;
} }
/** /**
@@ -120,11 +113,6 @@ class CustomerController extends BaseApiController
throw new NotFoundException(); throw new NotFoundException();
} }
// make sure the fields are properly setup and we know, which meta fields
// should be exposed and which not
$event = new CustomerMetaDefinitionEvent($data);
$this->dispatcher->dispatch(CustomerMetaDefinitionEvent::class, $event);
$view = new View($data, 200); $view = new View($data, 200);
$view->getContext()->setGroups(['Default', 'Entity', 'Customer']); $view->getContext()->setGroups(['Default', 'Entity', 'Customer']);

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace App\API; namespace App\API;
use App\Entity\Project; use App\Entity\Project;
use App\Event\ProjectMetaDefinitionEvent;
use App\Form\API\ProjectApiEditForm; use App\Form\API\ProjectApiEditForm;
use App\Repository\ProjectRepository; use App\Repository\ProjectRepository;
use App\Repository\Query\ProjectQuery; use App\Repository\Query\ProjectQuery;
@@ -23,7 +22,6 @@ use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface; use FOS\RestBundle\View\ViewHandlerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG; use Swagger\Annotations as SWG;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
@@ -43,16 +41,11 @@ class ProjectController extends BaseApiController
* @var ViewHandlerInterface * @var ViewHandlerInterface
*/ */
protected $viewHandler; protected $viewHandler;
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
public function __construct(ViewHandlerInterface $viewHandler, ProjectRepository $repository, EventDispatcherInterface $dispatcher) public function __construct(ViewHandlerInterface $viewHandler, ProjectRepository $repository)
{ {
$this->viewHandler = $viewHandler; $this->viewHandler = $viewHandler;
$this->repository = $repository; $this->repository = $repository;
$this->dispatcher = $dispatcher;
} }
/** /**
@@ -126,11 +119,6 @@ class ProjectController extends BaseApiController
throw new NotFoundException(); throw new NotFoundException();
} }
// make sure the fields are properly setup and we know, which meta fields
// should be exposed and which not
$event = new ProjectMetaDefinitionEvent($data);
$this->dispatcher->dispatch(ProjectMetaDefinitionEvent::class, $event);
$view = new View($data, 200); $view = new View($data, 200);
$view->getContext()->setGroups(['Default', 'Entity', 'Project']); $view->getContext()->setGroups(['Default', 'Entity', 'Project']);

View File

@@ -52,6 +52,25 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai
return 'kimai2_' . $name; return 'kimai2_' . $name;
} }
protected function isSupportingForeignKeys(): bool
{
return true;
}
protected function deactivateForeignKeysOnSqlite()
{
if ($this->isPlatformSqlite() && !$this->isSupportingForeignKeys()) {
$this->addSql('PRAGMA foreign_keys = OFF;');
}
}
private function activateForeignKeysOnSqlite()
{
if ($this->isPlatformSqlite() && !$this->isSupportingForeignKeys()) {
$this->addSql('PRAGMA foreign_keys = ON;');
}
}
/** /**
* @param Schema $schema * @param Schema $schema
* @throws DBALException * @throws DBALException
@@ -59,6 +78,16 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai
public function preUp(Schema $schema): void public function preUp(Schema $schema): void
{ {
$this->abortIfPlatformNotSupported(); $this->abortIfPlatformNotSupported();
$this->deactivateForeignKeysOnSqlite();
}
/**
* @param Schema $schema
* @throws DBALException
*/
public function postUp(Schema $schema): void
{
$this->activateForeignKeysOnSqlite();
} }
/** /**
@@ -68,6 +97,16 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai
public function preDown(Schema $schema): void public function preDown(Schema $schema): void
{ {
$this->abortIfPlatformNotSupported(); $this->abortIfPlatformNotSupported();
$this->deactivateForeignKeysOnSqlite();
}
/**
* @param Schema $schema
* @throws DBALException
*/
public function postDown(Schema $schema): void
{
$this->activateForeignKeysOnSqlite();
} }
/** /**

View File

@@ -35,6 +35,6 @@ class SqliteSessionInitSubscriber implements EventSubscriber
return; return;
} }
$args->getConnection()->executeUpdate('PRAGMA foreign_keys = ON;'); $args->getConnection()->exec('PRAGMA foreign_keys = ON;');
} }
} }

View File

@@ -26,6 +26,21 @@ final class Version20190605171157 extends AbstractMigration
return 'Creates the budget columns on: customer, project, activity'; return 'Creates the budget columns on: customer, project, activity';
} }
protected function isSupportingForeignKeys(): bool
{
return false;
}
public function isTransactional(): bool
{
if ($this->isPlatformSqlite()) {
// does fail if we use transactions, as tables are re-created and foreign keys would fail
return false;
}
return true;
}
public function up(Schema $schema): void public function up(Schema $schema): void
{ {
$customers = $schema->getTable('kimai2_customers'); $customers = $schema->getTable('kimai2_customers');

View File

@@ -41,12 +41,12 @@ class SqliteSessionInitSubscriberTest extends TestCase
$platformMock->expects($this->once())->method('getName')->willReturn('sqlite'); $platformMock->expects($this->once())->method('getName')->willReturn('sqlite');
$connectionMock = $this->getMockBuilder(Connection::class) $connectionMock = $this->getMockBuilder(Connection::class)
->setMethods(['getDatabasePlatform', 'getConnection', 'executeUpdate']) ->setMethods(['getDatabasePlatform', 'getConnection', 'exec'])
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$connectionMock->expects($this->once())->method('getDatabasePlatform')->willReturn($platformMock); $connectionMock->expects($this->once())->method('getDatabasePlatform')->willReturn($platformMock);
$connectionMock->expects($this->once())->method('executeUpdate')->with('PRAGMA foreign_keys = ON;', [], []); $connectionMock->expects($this->once())->method('exec')->with('PRAGMA foreign_keys = ON;');
$args = new ConnectionEventArgs($connectionMock); $args = new ConnectionEventArgs($connectionMock);
$sut->postConnect($args); $sut->postConnect($args);
@@ -64,12 +64,12 @@ class SqliteSessionInitSubscriberTest extends TestCase
$platformMock->expects($this->once())->method('getName')->willReturn('mysql'); $platformMock->expects($this->once())->method('getName')->willReturn('mysql');
$connectionMock = $this->getMockBuilder(Connection::class) $connectionMock = $this->getMockBuilder(Connection::class)
->setMethods(['getDatabasePlatform', 'getConnection', 'executeUpdate']) ->setMethods(['getDatabasePlatform', 'getConnection', 'exec'])
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$connectionMock->expects($this->once())->method('getDatabasePlatform')->willReturn($platformMock); $connectionMock->expects($this->once())->method('getDatabasePlatform')->willReturn($platformMock);
$connectionMock->expects($this->never())->method('executeUpdate')->with('PRAGMA foreign_keys = ON;', [], []); $connectionMock->expects($this->never())->method('exec')->with('PRAGMA foreign_keys = ON;');
$args = new ConnectionEventArgs($connectionMock); $args = new ConnectionEventArgs($connectionMock);
$sut->postConnect($args); $sut->postConnect($args);