diff --git a/src/API/ActivityController.php b/src/API/ActivityController.php index f46f03c4..dab8d76e 100644 --- a/src/API/ActivityController.php +++ b/src/API/ActivityController.php @@ -12,7 +12,6 @@ declare(strict_types=1); namespace App\API; use App\Entity\Activity; -use App\Event\ActivityMetaDefinitionEvent; use App\Form\API\ActivityApiEditForm; use App\Repository\ActivityRepository; use App\Repository\Query\ActivityQuery; @@ -23,7 +22,6 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Swagger\Annotations as SWG; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -43,16 +41,11 @@ class ActivityController extends BaseApiController * @var ViewHandlerInterface */ 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->repository = $repository; - $this->dispatcher = $dispatcher; } /** @@ -142,11 +135,6 @@ class ActivityController extends BaseApiController 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->getContext()->setGroups(['Default', 'Entity', 'Activity']); diff --git a/src/API/CustomerController.php b/src/API/CustomerController.php index 5e101b4c..7bc6fd2c 100644 --- a/src/API/CustomerController.php +++ b/src/API/CustomerController.php @@ -12,7 +12,6 @@ declare(strict_types=1); namespace App\API; use App\Entity\Customer; -use App\Event\CustomerMetaDefinitionEvent; use App\Form\API\CustomerApiEditForm; use App\Repository\CustomerRepository; use App\Repository\Query\CustomerQuery; @@ -23,7 +22,6 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Swagger\Annotations as SWG; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -43,16 +41,11 @@ class CustomerController extends BaseApiController * @var ViewHandlerInterface */ 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->repository = $repository; - $this->dispatcher = $dispatcher; } /** @@ -120,11 +113,6 @@ class CustomerController extends BaseApiController 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->getContext()->setGroups(['Default', 'Entity', 'Customer']); diff --git a/src/API/ProjectController.php b/src/API/ProjectController.php index 6375152e..a97d898b 100644 --- a/src/API/ProjectController.php +++ b/src/API/ProjectController.php @@ -12,7 +12,6 @@ declare(strict_types=1); namespace App\API; use App\Entity\Project; -use App\Event\ProjectMetaDefinitionEvent; use App\Form\API\ProjectApiEditForm; use App\Repository\ProjectRepository; use App\Repository\Query\ProjectQuery; @@ -23,7 +22,6 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Swagger\Annotations as SWG; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -43,16 +41,11 @@ class ProjectController extends BaseApiController * @var ViewHandlerInterface */ 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->repository = $repository; - $this->dispatcher = $dispatcher; } /** @@ -126,11 +119,6 @@ class ProjectController extends BaseApiController 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->getContext()->setGroups(['Default', 'Entity', 'Project']); diff --git a/src/Doctrine/AbstractMigration.php b/src/Doctrine/AbstractMigration.php index fa8f877c..7f509044 100644 --- a/src/Doctrine/AbstractMigration.php +++ b/src/Doctrine/AbstractMigration.php @@ -52,6 +52,25 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai 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 * @throws DBALException @@ -59,6 +78,16 @@ abstract class AbstractMigration extends BaseAbstractMigration implements Contai public function preUp(Schema $schema): void { $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 { $this->abortIfPlatformNotSupported(); + $this->deactivateForeignKeysOnSqlite(); + } + + /** + * @param Schema $schema + * @throws DBALException + */ + public function postDown(Schema $schema): void + { + $this->activateForeignKeysOnSqlite(); } /** diff --git a/src/Doctrine/SqliteSessionInitSubscriber.php b/src/Doctrine/SqliteSessionInitSubscriber.php index 9c3f04a0..59c431b7 100644 --- a/src/Doctrine/SqliteSessionInitSubscriber.php +++ b/src/Doctrine/SqliteSessionInitSubscriber.php @@ -35,6 +35,6 @@ class SqliteSessionInitSubscriber implements EventSubscriber return; } - $args->getConnection()->executeUpdate('PRAGMA foreign_keys = ON;'); + $args->getConnection()->exec('PRAGMA foreign_keys = ON;'); } } diff --git a/src/Migrations/Version20190605171157.php b/src/Migrations/Version20190605171157.php index 7cd8a272..0cca9a68 100644 --- a/src/Migrations/Version20190605171157.php +++ b/src/Migrations/Version20190605171157.php @@ -26,6 +26,21 @@ final class Version20190605171157 extends AbstractMigration 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 { $customers = $schema->getTable('kimai2_customers'); diff --git a/tests/Doctrine/SqliteSessionInitSubscriberTest.php b/tests/Doctrine/SqliteSessionInitSubscriberTest.php index 1acc9d6a..3dcf6d8c 100644 --- a/tests/Doctrine/SqliteSessionInitSubscriberTest.php +++ b/tests/Doctrine/SqliteSessionInitSubscriberTest.php @@ -41,12 +41,12 @@ class SqliteSessionInitSubscriberTest extends TestCase $platformMock->expects($this->once())->method('getName')->willReturn('sqlite'); $connectionMock = $this->getMockBuilder(Connection::class) - ->setMethods(['getDatabasePlatform', 'getConnection', 'executeUpdate']) + ->setMethods(['getDatabasePlatform', 'getConnection', 'exec']) ->disableOriginalConstructor() ->getMock(); $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); $sut->postConnect($args); @@ -64,12 +64,12 @@ class SqliteSessionInitSubscriberTest extends TestCase $platformMock->expects($this->once())->method('getName')->willReturn('mysql'); $connectionMock = $this->getMockBuilder(Connection::class) - ->setMethods(['getDatabasePlatform', 'getConnection', 'executeUpdate']) + ->setMethods(['getDatabasePlatform', 'getConnection', 'exec']) ->disableOriginalConstructor() ->getMock(); $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); $sut->postConnect($args);