diff --git a/lib/ArangoDBClient/Database.php b/lib/ArangoDBClient/Database.php
index 3ffd7cac..ac583ab6 100644
--- a/lib/ArangoDBClient/Database.php
+++ b/lib/ArangoDBClient/Database.php
@@ -43,7 +43,7 @@ class Database
* This creates a new database
*
* @param Connection $connection - the connection to be used
- * @param string $name - database name, for example 'myDatabase'
+ * @param string $name - database name, for example 'myDatabase' - must be NFC-normalized!
* @param array $options - extra options for new collections in this database.
*
Options are :
*
'replicationFactor'
@@ -58,16 +58,6 @@ class Database
*/
public static function create(Connection $connection, $name, array $options = [])
{
- try {
- // NFC-normalize the database name, as this is required
- // by the server
- if (class_exists("\Normalizer", false)) {
- $name = \Normalizer::normalize($name, \Normalizer::FORM_C);
- }
- } catch (\Exception $e) {
- // don't fail if Unicode normalization doesn't work.
- // probably it is not installed.
- }
$payload = [
self::ENTRY_DATABASE_NAME => $name,
self::ENTRY_DATABASE_USERS => [
@@ -195,6 +185,33 @@ public static function getInfo(Connection $connection)
return $response->getJson();
}
+
+
+ /**
+ * normalizes a database name
+ *
+ * UTF-8 NFC Normalization is required for database names in case
+ * the extended naming scheme for databases is used. This has to
+ * be enabled on the server side and is present since server version
+ * 3.9.
+ * If the name needs normalization but no normalizer is installed,
+ * this function can fail and abort the program with a PHP fatal error.
+ *
+ * @param string $name - database name to normalize.
+ *
+ * @return string $name - The normalized name
+ */
+ public static function normalizeName($name)
+ {
+ // first check if the database name follows the traditional
+ // naming scheme. if so, there is no need to normalize it.
+ if (!preg_match("/^[a-zA-Z0-9_\-]+$/", $name)) {
+ // extended database naming scheme. now NFC-normalize
+ // the database name, as this is required by the server
+ $name = \Normalizer::normalize($name, \Normalizer::FORM_C);
+ }
+ return $name;
+ }
}
class_alias(Database::class, '\triagens\ArangoDb\Database');
diff --git a/lib/ArangoDBClient/UrlHelper.php b/lib/ArangoDBClient/UrlHelper.php
index b936309d..2a37a27a 100644
--- a/lib/ArangoDBClient/UrlHelper.php
+++ b/lib/ArangoDBClient/UrlHelper.php
@@ -66,7 +66,7 @@ public static function buildUrl($baseUrl, array $parts = [])
@list(,$part) = explode('/', $part);
}
- $url .= '/' . urlencode($part);
+ $url .= '/' . rawurlencode($part);
}
return $url;
diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php
index d2621a07..1af71028 100644
--- a/tests/DatabaseTest.php
+++ b/tests/DatabaseTest.php
@@ -45,6 +45,79 @@ public function setUp(): void
}
}
+
+ public function testCreateDatabaseWithUnicodeName()
+ {
+ if (!class_exists("\Normalizer", false)) {
+ $this->markTestSkipped("unable to find Normalizer class. maybe php-intl is not installed?");
+ return;
+ }
+
+ // try to create a database with Unicode name.
+ // this may fail if the server side is not configured to allow
+ // Unicode database names
+ $database = "tröt tröt tröt_" . static::$testsTimestamp;
+ try {
+ $response = Database::create($this->connection, $database);
+ } catch (ServerException $exception) {
+ // ERROR_ARANGO_DATABASE_NAME_INVALID,1229,"database name invalid","Will be raised when an invalid database name is used."
+ if ($exception->getServerCode() === 1229) {
+ $this->markTestSkipped("server was not started with extended database naming scheme");
+ return;
+ }
+ throw $exception;
+ }
+
+ $response = Database::listDatabases($this->connection);
+ static::assertArrayHasKey($database, array_flip($response['result']));
+ }
+
+
+ public function testCreateDatabaseWithUnicodeNameNormalization()
+ {
+ if (!class_exists("\Normalizer", false)) {
+ $this->markTestSkipped("unable to find Normalizer class. maybe php-intl is not installed?");
+ return;
+ }
+
+ $databases = [ "😀", "ﻚﻠﺑ ﻞﻄﻴﻓ", "かわいい犬" ];
+
+ // try to create a database with Unicode name.
+ // this may fail if the server side is not configured to allow
+ // Unicode database names
+ foreach ($databases as $database) {
+ $database = Database::normalizeName($database);
+
+ try {
+ Database::delete($this->connection, $database);
+ } catch (\Exception $ex) {
+ // try to get rid of existing databases first. ignore if it does not exist.
+ }
+
+ try {
+ $response = Database::create($this->connection, $database);
+ } catch (ServerException $exception) {
+ // ERROR_ARANGO_DATABASE_NAME_INVALID,1229,"database name invalid","Will be raised when an invalid database name is used."
+ if ($exception->getServerCode() === 1229) {
+ $this->markTestSkipped("server was not started with extended database naming scheme");
+ return;
+ }
+ throw $exception;
+ }
+
+ try {
+ $response = Database::listDatabases($this->connection);
+ static::assertArrayHasKey($database, array_flip($response['result']));
+
+ Database::delete($this->connection, $database);
+ } catch (\Exception $ex) {
+ // always clean up
+ Database::delete($this->connection, $database);
+ throw $ex;
+ }
+ }
+ }
+
/**
* Test if Databases can be created and deleted
*/
@@ -53,7 +126,6 @@ public function testCreateDatabaseDeleteIt()
$database = 'ArangoTestSuiteDatabaseTest01' . '_' . static::$testsTimestamp;
try {
- $e = null;
Database::delete($this->connection, $database);
} catch (\Exception $e) {
// don't bother us... just give us the $e
@@ -354,7 +426,11 @@ public function tearDown(): void
$this->connection->setDatabase('_system');
// clean up
- $databases = ['ArangoTestSuiteDatabaseTest01' . '_' . static::$testsTimestamp, 'ArangoTestSuiteDatabaseTest02' . '_' . static::$testsTimestamp];
+ $databases = [
+ 'ArangoTestSuiteDatabaseTest01' . '_' . static::$testsTimestamp,
+ 'ArangoTestSuiteDatabaseTest02' . '_' . static::$testsTimestamp,
+ 'tröt tröt tröt_' . static::$testsTimestamp,
+ ];
foreach ($databases as $database) {
try {
diff --git a/tests/travis/setup_arangodb.sh b/tests/travis/setup_arangodb.sh
index 33763e23..ce778715 100644
--- a/tests/travis/setup_arangodb.sh
+++ b/tests/travis/setup_arangodb.sh
@@ -3,12 +3,12 @@
echo "PHP version: $TRAVIS_PHP_VERSION"
if [[ "$TRAVIS_PHP_VERSION" == "7.4" ]] ; then
-wget "https://phar.phpunit.de/phpunit-9.5.phar"
+wget --no-check-certificate "https://phar.phpunit.de/phpunit-9.5.phar"
mv phpunit-9.5.phar ./phpunit
fi
if [[ "$TRAVIS_PHP_VERSION" == "8.0" ]] ; then
-wget "https://phar.phpunit.de/phpunit-9.5.phar"
+wget --no-check-certificate "https://phar.phpunit.de/phpunit-9.5.phar"
mv phpunit-9.5.phar ./phpunit
fi
@@ -21,7 +21,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
docker pull arangodb/arangodb-preview:3.9.0-nightly
-docker run -d -e ARANGO_ROOT_PASSWORD="test" -p 8529:8529 arangodb/arangodb-preview:3.9.0-nightly
+docker run -d -e ARANGO_ROOT_PASSWORD="test" -p 8529:8529 arangodb/arangodb-preview:3.9.0-nightly arangod --database.extended-names-databases true
sleep 2