Skip to content

Commit

Permalink
Allow options to be provided to Doctrine
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Summers <[email protected]>
  • Loading branch information
summersab committed Sep 15, 2023
1 parent 2078109 commit c5f5f4e
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 5 deletions.
28 changes: 28 additions & 0 deletions config/config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,34 @@
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET wait_timeout = 28800'
],

/**
* Allows defining custom DB types and options as well as the ability to override
* the default connection parameters as defined by
* OC\DB\ConnectionFactory::defaultConnectionParams.
*/
'dbconnectionparams' => [
'dbtype' => [
'adapter' => AdapterMySQL::class,
'charset' => 'UTF8',
'driver' => 'pdo_dbtype',
'wrapperClass' => Doctrine\DBAL\Connection::class,
],
],

/**
* Allows additional configuration options to be provided for the database
* connection as defined by Doctrine\DBAL\Configuration::class. This is useful
* for specifying a custom logger, middlewares, etc.
*/
'dbconfigurationparams' => [
"sqllogger" => 'Doctrine\DBAL\Logging\SQLLogger',
"resultcache" => 'Psr\Cache\CacheItemPoolInterface',
"schemaassetsfilter" => 'callable',
"autocommit" => true,
"middlewares" => array(
'Doctrine\DBAL\Driver\Middleware',
),
],
/**
* sqlite3 journal mode can be specified using this configuration parameter -
* can be 'WAL' or 'DELETE' see for more details https://www.sqlite.org/wal.html
Expand Down
48 changes: 44 additions & 4 deletions lib/private/AppFramework/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@
use OC\AppFramework\DependencyInjection\DIContainer;
use OC\AppFramework\Http\Dispatcher;
use OC\AppFramework\Http\Request;
use OCP\App\IAppManager;
use OCP\Profiler\IProfiler;
use OC\Profiler\RoutingDataCollector;
use OCP\AppFramework\QueryException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\ICallbackResponse;
use OCP\AppFramework\Http\IOutput;
use OCP\AppFramework\QueryException;
use OCP\Diagnostics\IEventLogger;
use OCP\HintException;
use OCP\IRequest;
use OCP\Profiler\IProfiler;

/**
* Entry point for every request in your app. You can consider this as your
Expand All @@ -69,7 +68,7 @@ public static function buildAppNamespace(string $appId, string $topNamespace = '
return $topNamespace . self::$nameSpaceCache[$appId];
}

$appInfo = \OCP\Server::get(IAppManager::class)->getAppInfo($appId);
$appInfo = self::getAppInfo($appId);
if (isset($appInfo['namespace'])) {
self::$nameSpaceCache[$appId] = trim($appInfo['namespace']);
} else {
Expand All @@ -91,11 +90,42 @@ public static function buildAppNamespace(string $appId, string $topNamespace = '
return $topNamespace . self::$nameSpaceCache[$appId];
}

public static function getAppInfo(string $appId, bool $path = false, $lang = null) {
if ($path) {
$file = $appId;
} else {
try {
if ($appPath = \OC_App::findAppInDirectories($appId, true)) {
$appPath = $appPath['path'] . '/' . $appId;

Check failure on line 99 in lib/private/AppFramework/App.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

InvalidArrayOffset

lib/private/AppFramework/App.php:99:17: InvalidArrayOffset: Cannot access value on variable $appPath using offset value of 'path', expecting int (see https://psalm.dev/115)

Check failure

Code scanning / Psalm

InvalidArrayOffset Error

Cannot access value on variable $appPath using offset value of 'path', expecting int
}
} catch (\OCP\App\AppPathNotFoundException $e) {
return null;
}
$file = $appPath . '/appinfo/info.xml';
}

$parser = new \OC\App\InfoParser();
$data = $parser->parse($file);

if (is_array($data)) {
$data = \OC_App::parseAppInfo($data, $lang);
}

return $data;
}

public static function getAppIdForClass(string $className, string $topNamespace = 'OCA\\'): ?string {
if (!str_starts_with($className, $topNamespace)) {
return null;
}

if (str_starts_with($className, $topNamespace)) {
$classNoTopNamespace = substr($className, strlen($topNamespace));
$appNameParts = explode('\\', $classNoTopNamespace, 2);
$appName = reset($appNameParts);
return strtolower($appName);
}

foreach (self::$nameSpaceCache as $appId => $namespace) {
if (str_starts_with($className, $topNamespace . $namespace . '\\')) {
return $appId;
Expand All @@ -105,6 +135,16 @@ public static function getAppIdForClass(string $className, string $topNamespace
return null;
}

public static function registerAppClass(string $className): void {
$classParts = explode('\\', $className, 2);
$topNamespace = reset($classParts) . '\\';
$appId = self::getAppIdForClass($className, $topNamespace);

if ($appPath = \OC_App::findAppInDirectories($appId, true)) {
$appPath = $appPath['path'] . '/' . $appId;

Check failure on line 144 in lib/private/AppFramework/App.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

InvalidArrayOffset

lib/private/AppFramework/App.php:144:15: InvalidArrayOffset: Cannot access value on variable $appPath using offset value of 'path', expecting int (see https://psalm.dev/115)

Check failure

Code scanning / Psalm

InvalidArrayOffset Error

Cannot access value on variable $appPath using offset value of 'path', expecting int
\OC_App::registerAutoloading($appId, $appPath);
}
}

/**
* Shortcut for calling a controller method and printing the result
Expand Down
49 changes: 48 additions & 1 deletion lib/private/DB/ConnectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Event\Listeners\OracleSessionInit;
use Doctrine\DBAL\Event\Listeners\SQLSessionInit;
use OC\AppFramework\App;
use OC\SystemConfig;

/**
Expand Down Expand Up @@ -93,6 +94,21 @@ public function __construct(SystemConfig $systemConfig) {
if ($collationOverride) {
$this->defaultConnectionParams['mysql']['collation'] = $collationOverride;
}

$connectionParams = $this->config->getValue('dbconnectionparams', array());

foreach ($connectionParams as $type) {
foreach ($type as $key => $param) {
switch ($key) {
case 'adapter':
case 'wrapperClass':
\OC::$server->get(App::class)::registerAppClass($param);
break;
}
}
}

$this->defaultConnectionParams = array_replace_recursive($this->defaultConnectionParams, $connectionParams);
}

/**
Expand Down Expand Up @@ -158,9 +174,40 @@ public function getConnection($type, $additionalConnectionParams) {
break;
}
/** @var Connection $connection */
$configuration = new Configuration();

foreach ($this->config->getValue('dbconfigurationparams', array()) as $param => $value) {
switch ($param) {
case "sqllogger":
\OC::$server->get(App::class)::registerAppClass($value);
$configuration->setSQLLogger(new $value());

Check failure

Code scanning / Psalm

TaintedCallable Error

Detected tainted text

Check failure

Code scanning / Psalm

TaintedCallable Error

Detected tainted text
break;
case "resultcache":
\OC::$server->get(App::class)::registerAppClass($value);
$configuration->setResultCache(new $value());

Check failure

Code scanning / Psalm

TaintedCallable Error

Detected tainted text

Check failure

Code scanning / Psalm

TaintedCallable Error

Detected tainted text
break;
case "schemaassetsfilter":
$configuration->setSchemaAssetsFilter($value);
break;
case "autocommit":
$configuration->setAutoCommit($value);
break;
case "middlewares":
$middlewares = array();

foreach ($value as $middleware) {
\OC::$server->get(App::class)::registerAppClass($middleware);
array_push($middlewares, new $middleware());

Check failure

Code scanning / Psalm

TaintedCallable Error

Detected tainted text
}

$configuration->setMiddlewares($value);
break;
}
}

$connection = DriverManager::getConnection(
array_merge($this->getDefaultConnectionParams($type), $additionalConnectionParams),
new Configuration(),
$configuration,
$eventManager
);
return $connection;

Check failure on line 213 in lib/private/DB/ConnectionFactory.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

LessSpecificReturnStatement

lib/private/DB/ConnectionFactory.php:213:10: LessSpecificReturnStatement: The type 'Doctrine\DBAL\Connection' is more general than the declared return type 'OC\DB\Connection' for OC\DB\ConnectionFactory::getConnection (see https://psalm.dev/129)
Expand Down

0 comments on commit c5f5f4e

Please sign in to comment.