Page MenuHomeDevCentral

D1573.diff
No OneTemporary

D1573.diff

diff --git a/src/Config/DefaultConfiguration.php b/src/Config/DefaultConfiguration.php
new file mode 100644
--- /dev/null
+++ b/src/Config/DefaultConfiguration.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Nasqueron\SAAS\PhpBB\Config;
+
+class DefaultConfiguration {
+
+ ///
+ /// Sites repository
+ ///
+
+ public static function getSqliteRepositoryFilename() : string {
+ return getenv("SAAS_SITES_DB");
+ }
+
+ ///
+ /// MySQL database
+ ///
+
+ public static function getMySQLDatasourceName() : string {
+ $info = self::getMySQLConnectionInformation();
+
+ return "mysql:host=$info[host];port=$info[port];charset=utf8";
+ }
+
+ public static function getMySQLConnectionInformation() : array {
+ // There are three scenarii we test to get information:
+ //
+ // 1. Explicit preferences given in environment or .env
+ // 2. MySQL Docker container linked with `--link phpbb_db:db`
+ // 3. MySQL development default configuration
+
+ return [
+ 'host' => $_ENV['DB_HOST'] ?? $_ENV['DB_PORT_3306_TCP_ADDR'] ?? 'localhost',
+ 'port' => $_ENV['DB_PORT'] ?? $_ENV['DB_PORT_3306_TCP_PORT'] ?? 3306,
+ 'user' => $_ENV['DB_USER'] ?? 'root',
+ 'pass' => $_ENV['DB_PASS'] ?? $_ENV['DB_ENV_MYSQL_ROOT_PASSWORD'] ?? '',
+ ];
+ }
+
+}
diff --git a/src/Runner/TasksMap.php b/src/Runner/TasksMap.php
--- a/src/Runner/TasksMap.php
+++ b/src/Runner/TasksMap.php
@@ -5,11 +5,13 @@
use InvalidArgumentException;
use Nasqueron\SAAS\PhpBB\Tasks\BootstrapSqliteRepository;
+use Nasqueron\SAAS\PhpBB\Tasks\CreateDatabase;
class TasksMap {
public static function getMap () : array {
return [
+ 'sites:createdb' => CreateDatabase::class,
'sites:bootstrap' => BootstrapSqliteRepository::class,
];
}
diff --git a/src/SitesRepository/Repository.php b/src/SitesRepository/Repository.php
--- a/src/SitesRepository/Repository.php
+++ b/src/SitesRepository/Repository.php
@@ -4,4 +4,6 @@
abstract class Repository {
+ abstract public function get (string $id) : Site;
+
}
diff --git a/src/SitesRepository/Site.php b/src/SitesRepository/Site.php
new file mode 100644
--- /dev/null
+++ b/src/SitesRepository/Site.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace Nasqueron\SAAS\PhpBB\SitesRepository;
+
+class Site {
+
+ ///
+ /// Private members
+ ///
+
+ /**
+ * @var string
+ */
+ private $id;
+
+ /**
+ * @var string
+ */
+ private $host;
+
+ /**
+ * @var string
+ */
+ private $databaseUser;
+
+ /**
+ * @var string
+ */
+ private $databasePassword;
+
+ /**
+ * @var string
+ */
+ private $databasePrefix;
+
+ /**
+ * @var bool
+ */
+ private $active;
+
+ ///
+ /// Getters and setters
+ ///
+
+ public function getId () : string {
+ return $this->id;
+ }
+
+ public function setId (string $id) : Site {
+ $this->id = $id;
+
+ if (!$this->hasValidIdentifiant()) {
+ throw new \InvalidArgumentException(
+ "ID must only contain letters, digits and underscore."
+ );
+ }
+
+ return $this;
+ }
+
+ public function getHost () : string {
+ return $this->host;
+ }
+
+ public function setHost (string $host) : Site {
+ $this->host = $host;
+
+ return $this;
+ }
+
+ public function getDatabaseUser () : string {
+ return $this->databaseUser;
+ }
+
+ public function setDatabaseUser (string $databaseUser) : Site {
+ $this->databaseUser = $databaseUser;
+
+ return $this;
+ }
+
+ public function getDatabasePassword () : string {
+ return $this->databasePassword;
+ }
+
+ public function setDatabasePassword (string $databasePassword) : Site {
+ $this->databasePassword = $databasePassword;
+
+ return $this;
+ }
+
+ public function getDatabasePrefix () : string {
+ return $this->databasePrefix;
+ }
+
+ public function setDatabasePrefix (string $databasePrefix) : Site {
+ $this->databasePrefix = $databasePrefix;
+
+ return $this;
+ }
+
+ public function isActive () : bool {
+ return $this->active;
+ }
+
+ public function setActive (bool $active) : Site {
+ $this->active = $active;
+
+ return $this;
+ }
+
+ ///
+ /// Identifiant validation
+ ///
+
+ const VALID_ID_REGEXP = "/^[A-Za-z0-9_]+$/";
+
+ private function hasValidIdentifiant () : bool {
+ return (bool)preg_match(self::VALID_ID_REGEXP, $this->id);
+ }
+
+}
diff --git a/src/SitesRepository/SqliteRepository.php b/src/SitesRepository/SqliteRepository.php
--- a/src/SitesRepository/SqliteRepository.php
+++ b/src/SitesRepository/SqliteRepository.php
@@ -2,6 +2,8 @@
namespace Nasqueron\SAAS\PhpBB\SitesRepository;
+use Nasqueron\SAAS\PhpBB\Config\DefaultConfiguration;
+
use PDO;
class SqliteRepository extends Repository {
@@ -24,8 +26,8 @@
/// Constructor
///
- public function __construct (string $filename) {
- $this->filename = $filename;
+ public function __construct (string $filename = null) {
+ $this->filename = $filename ?? DefaultConfiguration::getSqliteRepositoryFilename();
}
///
@@ -41,6 +43,26 @@
}
}
+ public function get (string $id) : Site {
+ $statement = $this->getDB()->prepare(
+ "SELECT * FROM sites WHERE id = ?"
+ );
+ $result = $statement->execute([ $id ]);
+ $row = $statement->fetch();
+
+ if ($row === false) {
+ throw new \InvalidArgumentException("Site $id not found.");
+ }
+
+ return (new Site())
+ ->setId($row['id'])
+ ->setHost($row['host'])
+ ->setDatabaseUser($row['db_user'])
+ ->setDatabasePassword($row['db_password'])
+ ->setDatabasePrefix($row['db_prefix'])
+ ->setActive((bool)$row['active']);
+ }
+
///
/// Helper methods
///
diff --git a/src/Tasks/BootstrapSqliteRepository.php b/src/Tasks/BootstrapSqliteRepository.php
--- a/src/Tasks/BootstrapSqliteRepository.php
+++ b/src/Tasks/BootstrapSqliteRepository.php
@@ -7,12 +7,12 @@
class BootstrapSqliteRepository extends Task {
/**
- * @var string
+ * @var ?string
*/
private $filename;
- public function __construct (?string $filename = null) {
- $this->filename = $filename ?? $this->getDefaultFilename();
+ public function __construct (string $filename = null) {
+ $this->filename = $filename;
}
///
@@ -35,12 +35,4 @@
}
- ///
- /// Helper methods
- ///
-
- private function getDefaultFilename() : string {
- return getenv("SAAS_SITES_DB");
- }
-
}
diff --git a/src/Tasks/CreateDatabase.php b/src/Tasks/CreateDatabase.php
new file mode 100644
--- /dev/null
+++ b/src/Tasks/CreateDatabase.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Nasqueron\SAAS\PhpBB\Tasks;
+
+use Nasqueron\SAAS\PhpBB\SitesRepository\Site;
+use Nasqueron\SAAS\PhpBB\SitesRepository\SqliteRepository;
+
+class CreateDatabase extends Task {
+
+ use WithMySQL;
+
+ ///
+ /// Private members
+ ///
+
+ /**
+ * @var string
+ */
+ private $id;
+
+ /**
+ * @var Site
+ */
+ private $site;
+
+ /**
+ * @var \PDO
+ */
+ private $db;
+
+ ///
+ /// Constructor
+ ///
+
+ public function __construct (string $id) {
+ $this->id = $id;
+ }
+
+ ///
+ /// Task methods
+ ///
+
+ public function run () : void {
+ $this->initialize();
+ $this->createDatabase();
+ }
+
+ private function initialize () : void {
+ $this->site = (new SqliteRepository)->get($this->id);
+ $this->db = $this->getMySQLDatabase();
+ }
+
+ private function createDatabase () : void {
+ $this->getMySQLDatabase()
+ ->prepare($this->getQueries())
+ ->execute([
+ 'db' => $this->site->getId(),
+ 'user' => $this->site->getDatabaseUser(),
+ 'pass' => $this->site->getDatabasePassword(),
+ ]);
+ }
+
+ ///
+ /// Helper methods
+ ///
+
+ private function getQueries () : string {
+ $queries = <<<SQL
+CREATE DATABASE IF NOT EXISTS %db%;
+CREATE USER :user@'%' IDENTIFIED BY :pass;
+GRANT ALL ON %db%.* TO :user@'%';
+FLUSH PRIVILEGES;
+SQL;
+
+ return str_replace("%db%", $this->id, $queries);
+ }
+
+ public static function getUsage () : string {
+ return <<<DOC
+%command% <id>: creates a MySQL database for the specified identifant
+DOC;
+ }
+
+}
diff --git a/src/Tasks/WithMySQL.php b/src/Tasks/WithMySQL.php
new file mode 100644
--- /dev/null
+++ b/src/Tasks/WithMySQL.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Nasqueron\SAAS\PhpBB\Tasks;
+
+use Nasqueron\SAAS\PhpBB\Config\DefaultConfiguration;
+
+use PDO;
+
+trait WithMySQL {
+
+ public function getMySQLDatabase() : PDO {
+ $info = DefaultConfiguration::getMySQLConnectionInformation();
+
+ return new PDO(
+ DefaultConfiguration::getMySQLDatasourceName(),
+ $info['user'],
+ $info['pass'],
+ [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]
+ );
+ }
+
+}
diff --git a/tests/SitesRepository/SiteTest.php b/tests/SitesRepository/SiteTest.php
new file mode 100644
--- /dev/null
+++ b/tests/SitesRepository/SiteTest.php
@@ -0,0 +1,27 @@
+<?php
+declare(strict_types=1);
+
+namespace Nasqueron\SAAS\PhpBB\Tests\SitesRepository;
+
+use Nasqueron\SAAS\PhpBB\SitesRepository\Site;
+use PHPUnit\Framework\TestCase;
+
+use InvalidArgumentException;
+
+class SiteTest extends TestCase {
+
+ public function testSetId () {
+ $site = new Site;
+ $site->setId('acme');
+
+ $this->assertEquals('acme', $site->getId());
+ }
+
+ public function testSetIdWithInvalidIdentifiant () {
+ $this->expectException(InvalidArgumentException::class);
+
+ $site = new Site;
+ $site->setId('invalid acme');
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 09:58 (17 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2257712
Default Alt Text
D1573.diff (9 KB)

Event Timeline