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 @@ + $_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 @@ +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 @@ +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 = <<id, $queries); + } + + public static function getUsage () : string { + return <<: 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 @@ + 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 @@ +setId('acme'); + + $this->assertEquals('acme', $site->getId()); + } + + public function testSetIdWithInvalidIdentifiant () { + $this->expectException(InvalidArgumentException::class); + + $site = new Site; + $site->setId('invalid acme'); + } + +}