소스 검색

Create MichelPaperORMPackage for Michel Framework

phpdevcommunity 7 달 전
부모
커밋
397d045387
5개의 변경된 파일194개의 추가작업 그리고 1개의 파일을 삭제
  1. 1 0
      .gitignore
  2. 2 1
      composer.json
  3. 57 0
      src/Michel/Package/MichelPaperORMPackage.php
  4. 72 0
      src/Parser/DSNParser.php
  5. 62 0
      tests/Common/DSNParserTest.php

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 /vendor/
 /.idea/
+composer.lock

+ 2 - 1
composer.json

@@ -24,7 +24,8 @@
     "ext-json": "*",
     "ext-ctype": "*",
     "phpdevcommunity/relational-query": "^1.0",
-    "phpdevcommunity/php-console": "^1.0"
+    "phpdevcommunity/php-console": "^1.0",
+    "phpdevcommunity/michel-package-starter": "^1.0"
   },
   "require-dev": {
     "phpdevcommunity/unitester": "^0.1.0@alpha"

+ 57 - 0
src/Michel/Package/MichelPaperORMPackage.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Michel\Package;
+
+use Exception;
+use PhpDevCommunity\Michel\Package\PackageInterface;
+use PhpDevCommunity\PaperORM\Command\DatabaseCreateCommand;
+use PhpDevCommunity\PaperORM\Command\DatabaseDropCommand;
+use PhpDevCommunity\PaperORM\Command\QueryExecuteCommand;
+use PhpDevCommunity\PaperORM\Command\ShowTablesCommand;
+use PhpDevCommunity\PaperORM\EntityManager;
+use PhpDevCommunity\PaperORM\Parser\DSNParser;
+use Psr\Container\ContainerInterface;
+
+class MichelPaperORMPackage implements PackageInterface
+{
+    public function getDefinitions(): array
+    {
+        return [
+            EntityManager::class => static function (ContainerInterface $container) {
+                $dsn = $container->get('database.dsn');
+                if (!is_string($dsn) || empty($dsn)) {
+                    throw new \LogicException('Database DSN not found, please set DATABASE_DSN in .env file or database.dsn in config');
+                }
+                $params = DSNParser::parse($container->get('database.dsn'));
+                return new EntityManager($params);
+            }
+        ];
+    }
+
+    public function getParameters(): array
+    {
+        return [
+            'database.dsn' => getenv('DATABASE_DSN') ?? '',
+        ];
+    }
+
+    public function getRoutes(): array
+    {
+        return [];
+    }
+
+    public function getListeners(): array
+    {
+        return [];
+    }
+
+    public function getCommands(): array
+    {
+        return [
+            DatabaseCreateCommand::class,
+            DatabaseDropCommand::class,
+            QueryExecuteCommand::class,
+            ShowTablesCommand::class,
+        ];
+    }
+}

+ 72 - 0
src/Parser/DSNParser.php

@@ -0,0 +1,72 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Parser;
+
+final class DSNParser
+{
+
+    public static function parse(string $dsn): array
+    {
+        if (str_starts_with($dsn, 'sqlite:')) {
+            $rest = substr($dsn, 7);
+
+            $memory = false;
+            $options = [];
+
+            if (str_contains($rest, '?')) {
+                [$path, $query] = explode('?', $rest, 2);
+                parse_str($query, $options);
+            } else {
+                $path = $rest;
+            }
+
+            $path = ltrim($path, '/');
+            if ($path === '' || $path === 'memory' || $path === ':memory:') {
+                $memory = true;
+                $path = null;
+            } else {
+                if (str_starts_with($rest, '///')) {
+                    $path = '/' . $path;
+                }
+            }
+
+            return [
+                'driver' => 'sqlite',
+                'path' => $path,
+                'memory' => $memory,
+                'options' => $options,
+            ];
+        }
+
+        $params = parse_url($dsn);
+        if ($params === false) {
+            throw new \InvalidArgumentException("Unable to parse DSN: $dsn");
+        }
+
+
+        $options = [];
+        if (isset($params['query'])) {
+            parse_str($params['query'], $options);
+            unset($params['query']);
+        }
+        $driver = $params['scheme'] ?? null;
+        $host = $params['host'] ?? null;
+        $port = isset($params['port']) ? (int) $params['port'] : null;
+        $user = $params['user'] ?? null;
+        $password = $params['pass'] ?? null;
+        $path = isset($params['path']) ? ltrim($params['path'], '/') : null;
+        $isMemory = ($path === 'memory' || $path === ':memory:');
+
+        return [
+            'driver' => $driver,
+            'host' => $host,
+            'port' => $port,
+            'user' => $user,
+            'password' => $password,
+            'path' => $path,
+            'memory' => $isMemory,
+            'options' => $options
+        ];
+    }
+
+}

+ 62 - 0
tests/Common/DSNParserTest.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace Test\PhpDevCommunity\PaperORM\Common;
+
+use PhpDevCommunity\PaperORM\Parser\DSNParser;
+use PhpDevCommunity\UniTester\TestCase;
+
+class DSNParserTest extends TestCase
+{
+
+    protected function setUp(): void
+    {
+        // TODO: Implement setUp() method.
+    }
+
+    protected function tearDown(): void
+    {
+        // TODO: Implement tearDown() method.
+    }
+
+    protected function execute(): void
+    {
+        $this->testParse();
+    }
+
+    public function testParse()
+    {
+         $this->assertEquals(
+             [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'port' => 3306, 'user' => 'db_user', 'password' => 'db_password', 'path' => 'db_name', 'memory' => false, 'options' => [ 'serverVersion' => '8.0.37' ]],
+             DSNParser::parse("mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=8.0.37")
+         );
+        $this->assertEquals(
+            [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'port' => 3306, 'user' => 'db_user', 'password' => 'db_password', 'path' => 'db_name', 'memory' => false, 'options' => [ 'serverVersion' => 'mariadb-10.5.8' ]],
+            DSNParser::parse("mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=mariadb-10.5.8")
+        );
+        $this->assertEquals(
+            [ 'driver' => 'sqlite', 'path' => 'app.db', 'memory' => false, 'options' => []],
+            DSNParser::parse("sqlite://app.db")
+        );
+
+        $this->assertEquals(
+            [ 'driver' => 'sqlite', 'path' => '/app.db', 'memory' => false, 'options' => []],
+            DSNParser::parse("sqlite:///app.db")
+        );
+        $this->assertEquals(
+            [ 'driver' => 'sqlite', 'path' => 'var/app.db', 'memory' => false, 'options' => []],
+            DSNParser::parse("sqlite://var/app.db")
+        );
+        $this->assertEquals(
+            [ 'driver' => 'sqlite', 'path' => null, 'memory' => true, 'options' => []],
+            DSNParser::parse("sqlite:///:memory:")
+        );
+
+        $this->assertEquals(
+            [ 'driver' => 'sqlite', 'path' => '/app.db', 'memory' => false, 'options' => [
+                'mode' => 'ro',
+                'cache' => 'shared'
+            ]],
+            DSNParser::parse('sqlite:///app.db?mode=ro&cache=shared')
+        );
+    }
+}