Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
synio-wesley committed Mar 18, 2024
2 parents 740dba7 + a20fc2d commit 365a3b5
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 36 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# catalogs-php
A PHP framework to talk to Catalogs. Part of the [CloudFest 2024 Hackathon](https://hackathon.cloudfest.com/project/integrating-mariadb-catalogs-with-php-platforms/).

![Build status](https://github.com/MariaDB/catalogs-php/actions/workflows/test.yml/badge.svg?branch=main)

# Installation

Include the catalog-php with composer:
Expand All @@ -15,8 +17,12 @@ Include autoloader in your project.
<?php require_once('vendor/autoload.php');
```

# Examples

You can check some usage examples on [Examples](examples.md)

# Contributing
We welcome contributions! Please see our contribution guidelines for details on how to submit pull requests, report issues, or suggest improvements.

# License
This project is licensed under the General Public License (GPLv3). See the LICENSE file for details.
This project is licensed under the General Public License (GPLv3). See the LICENSE file for details.
8 changes: 4 additions & 4 deletions implementations-dummy-code.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

require ('vendor/autoload.php');

use Mariadb\CatalogsPHP\Catalog;
use Mariadb\CatalogsPHP\CatalogManager;

/**
* Use case 1: Create a new catalog and connect it to a wp install.
*/
$cat = new Catalog('127.0.0.1', 3306, 'root', 'rootpassword');
$catPort = $cat->create('wp_1');
$cat->createAdminUserForCatalog('wp_1', 'admin', 'adminpassword', '%');
$cat = new CatalogManager('127.0.0.1', 3306, 'root', 'rootpassword');
$catPort = $cat->create('wp_2');
$cat->createAdminUserForCatalog('wp_2', 'admin', 'adminpassword', '%');

// Using PDO, Create a DB and user in the collection using the $catPort.
// Set DB_NAME with the "name:$catPort"
6 changes: 6 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
<!-- PSR12 based -->
<rule ref="PSR12"/>

<rule ref="Squiz.Commenting.BlockComment"/>
<rule ref="Squiz.Commenting.DocCommentAlignment"/>
<rule ref="Squiz.Commenting.EmptyCatchComment"/>
<rule ref="Squiz.Commenting.PostStatementComment"/>
<rule ref="Squiz.Commenting.VariableComment"/>

<!-- Lines can be N chars long (warnings), errors at M chars -->
<rule ref="Generic.Files.LineLength">
<properties>
Expand Down
68 changes: 40 additions & 28 deletions src/Catalog.php → src/CatalogManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
* @package Mariadb\CatalogsPHP
*/
class Catalog
class CatalogManager
{
/**
* The connection to the MariaDB server.
Expand All @@ -18,6 +18,15 @@ class Catalog
*/
private $connection;

// Prepared statements with the USE CATALOG command are not working as expected.
// This method is used to check the catalog name before using it in a query.
private function checkCatalogName($catalogName): void
{
if (preg_match('/[^a-zA-Z0-9_]/', $catalogName) === 1) {
throw new CatalogManagerException('Invalid catalog name');
}
}

// This is too low, because this is a beta version we are developing for.
public const MINIMAL_MARIA_VERSION = '11.0.2';

Expand All @@ -39,7 +48,7 @@ class Catalog
* @param \PDO|null $pdo Optional. An existing PDO connection to use. Default is null.
*
* @throws PDOException If a PDO error occurs during the connection attempt.
* @throws Exception If a general error occurs during instantiation.
* @throws CatalogManagerException If a general error occurs during instantiation.
*/
public function __construct(
protected string $dbHost = 'localhost',
Expand Down Expand Up @@ -71,7 +80,7 @@ public function __construct(
$version = $versionQuery->fetchColumn();

if (version_compare($version, self::MINIMAL_MARIA_VERSION, '<') === true) {
throw new Exception(
throw new CatalogManagerException(
'The MariaDB version is too low. The minimal version is ' . self::MINIMAL_MARIA_VERSION
);
}
Expand All @@ -86,28 +95,29 @@ public function __construct(
/**
* Create a new catalog
*
* @param string $catName The new Catalog name.
* @param string $catalogName The new Catalog name.
*
* @return int
*/
public function create(string $catName): int
public function create(string $catalogName): int
{
// Check if the Catalog name is valid.
if (in_array($catName, array_keys($this->list())) === true) {
throw new Exception('Catalog name already exists.');
if (in_array($catalogName, array_keys($this->list())) === true) {
throw new CatalogManagerException('Catalog name already exists.');
}

$rootPrivileges = $this->connection->query("SELECT * FROM mysql.global_priv WHERE User='{$this->dbUser}' AND Host='%';");

$scripts = [
'src/create_catalog_sql/mysql_system_tables.sql',
'src/create_catalog_sql/mysql_performance_tables.sql',
'src/create_catalog_sql/mysql_system_tables_data.sql',
'src/create_catalog_sql/maria_add_gis_sp.sql',
'src/create_catalog_sql/mysql_sys_schema.sql',
__DIR__ . '/create_catalog_sql/mysql_system_tables.sql',
__DIR__ . '/create_catalog_sql/mysql_performance_tables.sql',
__DIR__ . '/create_catalog_sql/mysql_system_tables_data.sql',
__DIR__ . '/create_catalog_sql/maria_add_gis_sp.sql',
__DIR__ . '/create_catalog_sql/mysql_sys_schema.sql',
];
$this->connection->exec('CREATE CATALOG IF NOT EXISTS ' . $catName);
$this->connection->exec('USE CATALOG ' . $catName);
$this->checkCatalogName($catalogName);
$this->connection->exec('CREATE CATALOG IF NOT EXISTS ' . $catalogName);
$this->connection->exec('USE CATALOG ' . $catalogName);

$this->connection->exec('CREATE DATABASE IF NOT EXISTS mysql');
$this->connection->exec('USE mysql');
Expand Down Expand Up @@ -139,18 +149,18 @@ public function create(string $catName): int
}
}

return $this->getPort($catName);
return $this->getPort($catalogName);
}


/**
* Get the port of a catalog.
*
* @param string $catName The catalog name.
* @param string $catalogName The catalog name.
*
* @return int
*/
public function getPort(string $catName): int
public function getPort(string $catalogName): int
{
// TODO: wait for the functionality to be implemented in the server.
return ($this->dbPort ?? 0);
Expand Down Expand Up @@ -179,24 +189,25 @@ public function list(): array
/**
* Drop a catalog.
*
* @param string $catName The catalog name.
* @param string $catalogName The catalog name.
*
* @return void
*
* @throws PDOException If a PDO error occurs during the catalog drop attempt.
* @throws Exception If a general error occurs during catalog drop.
* @throws CatalogManagerException If a general error occurs during catalog drop.
*/
public function drop(string $catName): bool
public function drop(string $catalogName): bool
{
try {
// Enter the catalog.
$this->connection->exec('USE CATALOG ' . $catName);
$this->checkCatalogName($catalogName);
$this->connection->exec('USE CATALOG ' . $catalogName);

// Check if there are any tables besides mysql, sys, performance_schema and information_schema.
$tables = $this->connection->query('SHOW DATABASES');
foreach ($tables as $table) {
if (in_array($table['Database'], ['mysql', 'sys', 'performance_schema', 'information_schema']) === false) {
throw new \Exception('Catalog is not empty');
throw new CatalogManagerException('Catalog is not empty');
}
}

Expand All @@ -206,9 +217,9 @@ public function drop(string $catName): bool
$this->connection->exec('DROP DATABASE IF EXISTS performance_schema');

// Drop the catalog.
$this->connection->exec('DROP CATALOG ' . $catName);
$this->connection->exec('DROP CATALOG ' . $catalogName);
} catch (\PDOException $e) {
throw new \Exception('Error dropping catalog: ' . $e->getMessage());
throw new CatalogManagerException('Error dropping catalog: ' . $e->getMessage());
}

return true;
Expand All @@ -231,24 +242,25 @@ private function alter()
/**
* Create admin user for a catalog
*
* @param string $catalog The catalog name
* @param string $catalogName The catalog name
* @param string $userName The user name
* @param string $password The user password
* @param string $authHost The database host
*
* @return void
*/
public function createAdminUserForCatalog(
string $catalog,
string $catalogName,
string $userName,
string $password,
string $authHost = 'localhost'
): void {
$this->connection->exec("USE CATALOG {$catalog}");
$this->checkCatalogName($catalogName);
$this->connection->exec("USE CATALOG {$catalogName}");
$this->connection->exec("USE mysql");

$this->connection = new \PDO(
"mysql:host={$this->dbHost};port={$this->dbPort};dbname={$catalog}.mysql",
"mysql:host={$this->dbHost};port={$this->dbPort};dbname={$catalogName}.mysql",
$this->dbUser,
$this->dbPass,
$this->dbOptions
Expand Down
2 changes: 1 addition & 1 deletion src/Exception.php → src/CatalogManagerException.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
* @package Mariadb\CatalogsPHP
*/
class Exception extends \Exception
class CatalogManagerException extends \Exception
{
/**
* Constructs the Exception.
Expand Down
28 changes: 26 additions & 2 deletions tests/CatalogTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,41 @@

namespace Mariadb\CatalogsPHP\Tests;

use Mariadb\CatalogsPHP\Catalog;
use Mariadb\CatalogsPHP\CatalogManager;
use PHPUnit\Framework\TestCase;

/**
* Class PDOStatementMock
*
* A mock for the PDOStatement class
*/
class CatalogTest extends TestCase
{
/**
* @var CatalogManager $catalog The Catalog instance to test
*/
private $catalog;

/**
* @var \PDO $pdoMock The PDO mock to inject into the Catalog instance
*/
private $pdoMock;

/**
* Set up the test
*/
protected function setUp(): void
{
// Create a mock for the PDO class
$this->pdoMock = $this->createMock(\PDO::class);

// Inject the PDO mock into your Catalog class
$this->catalog = new Catalog('localhost', 3306, 'root', '', null, $this->pdoMock);
$this->catalog = new CatalogManager('localhost', 3306, 'root', '', null, $this->pdoMock);
}

/**
* Test the list method
*/
public function testList()
{
// Mock the PDOStatement for the 'SHOW CATALOGS' query
Expand All @@ -42,12 +60,18 @@ public function testList()
], $catalogs);
}

/**
* Test the getPort method
*/
public function testGetPort()
{
$port = $this->catalog->getPort('test');
$this->assertEquals(3306, $port);
}

/**
* Test the create method
*/
public function testCreate()
{
// Configure the PDO mock to return the PDOStatement mock for the 'SHOW CATALOGS' query
Expand Down

0 comments on commit 365a3b5

Please sign in to comment.