Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request]: Use a cleaner format in e107_config.php #5120

Open
CaMer0n opened this issue Nov 29, 2023 · 4 comments
Open

[Feature request]: Use a cleaner format in e107_config.php #5120

CaMer0n opened this issue Nov 29, 2023 · 4 comments
Labels
type: enhancement An improvement or new feature request
Milestone

Comments

@CaMer0n
Copy link
Member

CaMer0n commented Nov 29, 2023

Motivation

Currently it's a mess of different formats.

Proposed Solution

Return a multi-dimensional array. As an example:

return [
    'mySQL' => [
        'server'   => '127.0.0.1',
        'user'     => 'root',
        'password' => 'root',
        'defaultdb'=> 'e107v2',
        'prefix'   => 'e107_',
        'charset'  => 'utf8mb4', 
        'port'     => 3306, 
    ],
    'directories' => [
        'admin'      => 'e107_admin/',
        'files'      => 'e107_files/',
        'images'     => 'e107_images/',
        'themes'     => 'e107_themes/',
        'plugins'    => 'e107_plugins/',
        'handlers'   => 'e107_handlers/',
        'languages'  => 'e107_languages/',
        'help'       => 'e107_docs/help/',
        'downloads'  => 'e107_downloads/',
        'uploads'    => 'e107_uploads/',
        'system'     => 'e107_system/',
        'media'      => 'e107_media/',
        'cache'      => 'e107_cache/',
        'logs'       => 'e107_logs/',
        'core'       => 'e107_core/',
        'web'        => 'e107_web/',
    ],
];

or an Object:

<?php
class e107_config
{
    public static function directories()
    {
        return [
            'admin'      => 'e107_admin/',
            'files'      => 'e107_files/',
            'images'     => 'e107_images/',
            'themes'     => 'e107_themes/',
            'plugins'    => 'e107_plugins/',
            'handlers'   => 'e107_handlers/',
            'languages'  => 'e107_languages/',
            'help'       => 'e107_docs/help/',
            'system'     => 'e107_system/',
            'media'      => 'e107_media/',
        ];
    }

    public static function database()
    {
        return [
            'server'   => '127.0.0.1',
            'user'     => 'root',
            'password' => 'root',
            'defaultdb'=> 'e107v2',
            'prefix'   => 'e107_',
            'charset'  => 'utf8mb4',
        ];
    }

    public static function other()
    {
        return [
            'site_path' => '000000test'
        ];
    }
}

return new e107_config;

Alternatives

Additional Context

No response

@CaMer0n CaMer0n added the type: enhancement An improvement or new feature request label Nov 29, 2023
@CaMer0n CaMer0n added this to the e107 2.4.0 milestone Nov 29, 2023
CaMer0n added a commit that referenced this issue Nov 30, 2023
@Deltik
Copy link
Member

Deltik commented Nov 30, 2023

RFC: e107_config.php v3 Format

This request for comments proposes a new format for the e107_config.php file, which is used to store the configuration of an e107 installation.

Motivation

Status Quo

The e107 v2 configuration file is made of unstructured and inflexible variables and some additional code that defines constants to modify global behavior.

This is the template of the e107 v2 configuration file:

<?php
/**
 * e107 website system
 *
 * Copyright (C) 2008-{$copyrightYear} e107 Inc (e107.org)
 * Released under the terms and conditions of the
 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
 *
 * e107 configuration file
 *
 * This file has been generated by the installation script on {$rfc2822Date}.
 */
 
$mySQLserver    = '{{ mySQLserver }}';
$mySQLuser      = '{{ mySQLuser }}';
$mySQLpassword  = '{{ mySQLpassword }}';
$mySQLdefaultdb = '{{ mySQLdefaultdb }}';
$mySQLport      = '{{ mySQLport }}';
$mySQLprefix    = '{{ mySQLprefix }}';
$mySQLcharset   = 'utf8mb4';

$ADMIN_DIRECTORY     = 'e107_admin/';
$FILES_DIRECTORY     = 'e107_files/';
$IMAGES_DIRECTORY    = 'e107_images/';
$THEMES_DIRECTORY    = 'e107_themes/';
$PLUGINS_DIRECTORY   = 'e107_plugins/';
$HANDLERS_DIRECTORY  = 'e107_handlers/';
$LANGUAGES_DIRECTORY = 'e107_languages/';
$HELP_DIRECTORY      = 'e107_docs/help/';
$MEDIA_DIRECTORY     = 'e107_media/';
$SYSTEM_DIRECTORY    = 'e107_system/';

// -- Optional --
// define('e_DEBUG', true); // Enable debug mode to allow displaying of errors
// define('e_HTTP_STATIC', 'https://static.mydomain.com/');  // Use a static subdomain for js/css/images etc. 
// define('e_MOD_REWRITE_STATIC', true); // Rewrite static image urls. 
// define('e_LOG_CRITICAL', true); // log critical errors but do not display them to user. 
// define('e_GIT', 'path-to-git');  // Path to GIT for developers
// define('X-FRAME-SAMEORIGIN', false); // Option to override X-Frame-Options 
// define('e_PDO, true); // Enable PDO mode (used in PHP > 7 and when mysql_* methods are not available)

This template has the following limitations:

  • The database configuration is defined by a set of variables that are not grouped together.
  • Only one kind of database configuration is supported.
  • The directories are also defined by a set of variables that are not grouped together.
  • Arbitrary code is loaded in an uncontrolled manner.
  • There is no schema to validate the configuration file.
  • The variables that are set have to be retrieved and are not passed to the caller, making the handoff unstructured, too.

Goals

  • Plug-in architecture for the database configuration to support multiple database types or connection methods
  • Validatable schema for the configuration file
  • Logical grouping of configuration options
  • Structured handoff of the configuration to the caller that imports the configuration file
  • Deferred loading of configuration options for tighter control over the loading process
  • Adapter for the old configuration file format to allow for a smooth transition

Proposal

New Configuration File Template

The equivalent configuration file in the new format would look like this:

<?php
/**
 * e107 website system
 *
 * Copyright (C) 2008-{$copyrightYear} e107 Inc (e107.org)
 * Released under the terms and conditions of the
 * GNU General Public License (https://www.gnu.org/licenses/gpl.txt)
 *
 * Site configuration file
 */

class E107Config extends BaseSiteConfig
{
    function getDatabase(): DatabaseConnector
    {
        return new MysqlTcpConnector(
            user:     '{{ mySQLuser }}',
            password: '{{ mySQLpassword }}',
            host:     '{{ mySQLserver }}',
            port:     '{{ mySQLport }}',
            dbname:   '{{ mySQLdefaultdb }}',
            charset:  'utf8mb4',
            prefix:   '{{ mySQLprefix }}',
        );
    }

    #[ArrayShape(SiteConfig::PATHS_ARRAY_SHAPE)]
    function getPaths(): array
    {
        return [
            'admin'     => 'e107_admin/',
            'core'      => 'e107_system/',
            'handlers'  => 'e107_handlers/',
            'images'    => 'e107_images/',
            'languages' => 'e107_languages/',
            'media'     => 'e107_media/',
            'plugins'   => 'e107_plugins/',
            'system'    => 'e107_system/',
            'themes'    => 'e107_themes/',
            'web'       => 'e107_web/',
            'docs'      => 'e107_docs/',
            'files'     => 'e107_files/',
        ];
    }

    function defineGlobals(): void
    {
        // define('e_DEBUG', true); // Enable debug mode to allow displaying of errors
        // define('e_HTTP_STATIC', 'https://static.mydomain.com/');  // Use a static subdomain for js/css/images etc.
        // define('e_MOD_REWRITE_STATIC', true); // Rewrite static image urls.
        // define('e_LOG_CRITICAL', true); // log critical errors but do not display them to user.
        // define('e_GIT', 'path-to-git');  // Path to GIT for developers
        // define('X-FRAME-SAMEORIGIN', false); // Option to override X-Frame-Options
        // define('e_PDO, true); // Enable PDO mode (used in PHP > 7 and when mysql_* methods are not available)
    }
}

return new E107Config();

This template has the following advantages:

  • The database configuration can be defined flexibly by implementing the DatabaseConnector interface. Plugins or other core components can provide their own implementations of the interface to support different database types or connection methods.
  • The system paths are grouped together in a single method.
  • The provider pattern allows us to defer the loading of the configuration until each scope (paths, database, or globals) is needed.
  • Arbitrary (legacy) code moved into the defineGlobals() method allows us to defer and disable the execution of this code in the future. Administrators can then test their installation with the legacy code disabled and report any issues.
  • The configuration follows a clearly defined schema that can be validated with static code analysis.
  • The configuration is passed to the caller as an object, which allows for a structured handoff.
  • With that ending return, the caller can also detect whether the old or the new configuration format is used and select the appropriate adapter.

To use this structured approach, the following interface is defined prior to loading e107_config.php:

/**
 * Interface for the return value of including e107_config.php
 */
interface SiteConfig
{
	const PATHS_ARRAY_SHAPE = [
		// Current paths
		'admin'     => 'string', // Admin area files
		'core'      => 'string', // System assets
		'handlers'  => 'string', // System backend framework
		'images'    => 'string', // System images
		'languages' => 'string', // Locale files
		'media'     => 'string', // Uploaded files
		'plugins'   => 'string', // System plugins
		'system'    => 'string', // Runtime-generated site files
		'themes'    => 'string', // System themes
		'web'       => 'string', // Frontend web libraries

		// Legacy paths
		'docs'      => 'string', // Admin documentation
		'files'     => 'string', // e107 v1/v2 supplementary files
	];

	/**
	 * Base Paths
	 *
	 * Relative paths to the directories of each kind of e107 resource
	 *
	 * e107 will append site-specific paths to these base paths.
	 *
	 * @return array Associative array of relative paths
	 */
	#[ArrayShape(SiteConfig::PATHS_ARRAY_SHAPE)]
	function getPaths(): array;

	/**
	 * Database Connection Settings
	 *
	 * How to connect to the database
	 *
	 * @return DatabaseConnector The database connection settings
	 */
	function getDatabase(): DatabaseConnector;

	/**
	 * Set legacy global constants
	 *
	 * @deprecated v2.4.0 Global constants are being phased out in favor of configurable settings elsewhere.
	 *
	 * @example
	 *         define('e_DEBUG', true); // Enable debug mode to allow displaying of errors
	 *         define('e_HTTP_STATIC', 'https://static.mydomain.com/'); // Use a static subdomain for js/css/images etc.
	 *         define('e_MOD_REWRITE_STATIC', true); // Rewrite static image urls.
	 *         define('e_LOG_CRITICAL', true); // log critical errors but do not display them to user.
	 *         define('e_GIT', 'path-to-git');  // Path to GIT for developers
	 *         define('X-FRAME-SAMEORIGIN', false); // Option to override X-Frame-Options
	 *         define('e_PDO, true); // Enable PDO mode (used in PHP > 7 and when mysql_* methods are not available)
	 */
	function defineGlobals(): void;
}

To shield the concrete implementation from new methods that might be added to the interface in the future, the interface is extended by an abstract class:

/**
 * Dummy class implementing the {@see SiteConfig} interface
 */
abstract class BaseSiteConfig implements SiteConfig
{
    /**
     * @inheritDoc
     */
    abstract function getDatabase(): DatabaseConnector;

    /**
     * @inheritDoc
     */
    abstract function getPaths(): array;

    /**
     * @inheritDoc
     */
    abstract function defineGlobals(): void;
}

Optional Sensible Defaults

We could go a step further and inherit sensible defaults, but this would obfuscate what configurable options are available in the concrete implementation in e107_config.php.

Such a default implementation could look like this:

/**
 * Partial {@see SiteConfig} implementation with default paths and no global constants
 *
 * {@see SiteConfig::getDatabase()} must be implemented by the concrete class.
 */
abstract class DefaultSiteConfig implements SiteConfig
{
	const DEFAULT_PATH_ADMIN = 'admin/';
	const DEFAULT_PATH_CORE = 'core/';
	const DEFAULT_PATH_HANDLERS = 'handlers/';
	const DEFAULT_PATH_IMAGES = 'images/';
	const DEFAULT_PATH_LANGUAGES = 'languages/';
	const DEFAULT_PATH_MEDIA = 'media/';
	const DEFAULT_PATH_PLUGINS = 'plugins/';
	const DEFAULT_PATH_SYSTEM = 'system/';
	const DEFAULT_PATH_THEMES = 'themes/';
	const DEFAULT_PATH_WEB = 'web/';
	const DEFAULT_PATH_DOCS = 'docs/';
	const DEFAULT_PATH_FILES = 'files/';

	protected function pathPrefix(): string
	{
		return "e107_";
	}

	/**
	 * @inheritDoc
	 */
	#[ArrayShape(SiteConfig::PATHS_ARRAY_SHAPE)]
	function getPaths(): array
	{
		$pathPrefix = $this->pathPrefix();

		return [
			'admin'     => $pathPrefix . self::DEFAULT_PATH_ADMIN,
			'core'      => $pathPrefix . self::DEFAULT_PATH_CORE,
			'handlers'  => $pathPrefix . self::DEFAULT_PATH_HANDLERS,
			'images'    => $pathPrefix . self::DEFAULT_PATH_IMAGES,
			'languages' => $pathPrefix . self::DEFAULT_PATH_LANGUAGES,
			'media'     => $pathPrefix . self::DEFAULT_PATH_MEDIA,
			'plugins'   => $pathPrefix . self::DEFAULT_PATH_PLUGINS,
			'system'    => $pathPrefix . self::DEFAULT_PATH_SYSTEM,
			'themes'    => $pathPrefix . self::DEFAULT_PATH_THEMES,
			'web'       => $pathPrefix . self::DEFAULT_PATH_WEB,
			'docs'      => $pathPrefix . self::DEFAULT_PATH_DOCS,
			'files'     => $pathPrefix . self::DEFAULT_PATH_FILES,
		];
	}

	/**
	 * @inheritDoc
	 */
	function defineGlobals(): void
	{
	}
}

DatabaseConnector

The DatabaseConnector is a simple interface that returns the database abstraction layer (DBAL):

interface DatabaseConnector
{
	/**
	 * Get a new database connection
	 *
	 * @return e_db The database abstraction layer
	 */
	function connect(): e_db;
}

Implementations will be autoloaded from the core in e107_handlers/Database/Connection or from plugins.

The core will provide the following implementations:

  • MysqlConnector < DatabaseConnector for MySQL or MariaDB connections
    • MysqlTcpConnector < MysqlConnector for MySQL connections via TCP
      • MysqlTlsConnector < MysqlTcpConnector for encrypted MySQL connections via TCP
    • MysqlSocketConnector < MysqlConnector for MySQL connections via a UNIX socket
  • DsnConnector < DatabaseConnector for connections from a DSN string as an alternative and compact way to define the database connection. (A DSN string might look like: mysql://user:password@localhost:3306/database?charset=utf8mb4)

Although not in the scope of this RFC, this plug-in architecture could be extended to support more database types. Hypothetical examples could be:

  • PgsqlConnector < DatabaseConnector for PostgreSQL connections
  • SqliteConnector < DatabaseConnector for SQLite file connections
  • SqlsrvConnector < DatabaseConnector for Microsoft SQL Server connections
  • OracleConnector < DatabaseConnector for Oracle connections
  • Db2Connector < DatabaseConnector for IBM DB2 connections

Backwards-Compatibility Adapter

Using just the new configuration file format in the core would be simple:

$config = include(e_ROOT . 'e107_config.php');

// Connect to the database
$db = $config->getDatabase()->connect();
// Get the handler path
$handlerPath = $config->getPaths()['handlers'];

To transition from the old configuration file format to the new one, we will need to detect which format is used and wrap the old configuration file values in an adapter:

$config = include(e_ROOT . 'e107_config.php');
if (!($config instanceof SiteConfig)) {
    $config = new V2ConfigAdapter();
}

V2ConfigAdapter will implement the SiteConfig interface and wrap the old configuration file values:

/**
 * Adapter for the old e107 v2 configuration file format
 */
class V2ConfigAdapter implements SiteConfig
{
	protected const DATABASE_CREDENTIAL_DEFAULTS = [
		'prefix'  => '',
		'port'    => '3306',
		'charset' => 'utf8mb4',
	];
	protected const LEGACY_DATABASE_VARIABLES = [
		'prefix'   => 'mySQLprefix',
		'host'     => 'mySQLserver',
		'port'     => 'mySQLport',
		'name'     => 'mySQLdefaultdb',
		'username' => 'mySQLuser',
		'password' => 'mySQLpassword',
		'charset'  => 'mySQLcharset',
	];
	protected const LEGACY_PATH_VARIABLES = [
		'admin'     => 'ADMIN_DIRECTORY',
		'core'      => 'CORE_DIRECTORY',
		'docs'      => 'DOCS_DIRECTORY',
		'help'      => 'HELP_DIRECTORY',
		'files'     => 'FILES_DIRECTORY',
		'handlers'  => 'HANDLERS_DIRECTORY',
		'images'    => 'IMAGES_DIRECTORY',
		'languages' => 'LANGUAGES_DIRECTORY',
		'media'     => 'MEDIA_DIRECTORY',
		'plugins'   => 'PLUGINS_DIRECTORY',
		'system'    => 'SYSTEM_DIRECTORY',
		'themes'    => 'THEMES_DIRECTORY',
		'web'       => 'WEB_DIRECTORY',
	];
	
	/**
     * @inheritDoc
     */
    function getDatabase(): DatabaseConnector
    {
        $credentials = self::DATABASE_CREDENTIAL_DEFAULTS;
        foreach (self::LEGACY_DATABASE_VARIABLES as $key => $legacyVariable) {
            $credentials[$key] = $$legacyVariable;
        }
        return new DsnConnector(
            dsn: sprintf(
                'mysql://%s:%s@%s:%s/%s?charset=%s',
                $credentials['username'],
                $credentials['password'],
                $credentials['host'],
                $credentials['port'],
                $credentials['name'],
                $credentials['charset'],
            ),
            prefix: $credentials['prefix'],
        );
    }
    
    /**
     * @inheritDoc
     */
    #[ArrayShape(SiteConfig::PATHS_ARRAY_SHAPE)]
    function getPaths(): array
    {
        $paths = [];
        foreach (self::LEGACY_PATH_VARIABLES as $key => $legacyVariable) {
            $paths[$key] = constant($legacyVariable);
        }
        return $paths;
    }
    
    /**
     * @inheritDoc
     */
    function defineGlobals(): void
    {
        include_once(e_ROOT . 'e107_config.php');
    }
}

Migration

The old configuration file format can likely be migrated to the new one automatically by a script that reads the old configuration file and replaces it with the new one.

A PHP parser is not required because the configuration loaded by the adapter (V2ConfigAdapter) can be rewritten into the new format template, and all the other code can be wrapped within the SiteConfig::defineGlobals() method.

@CaMer0n
Copy link
Member Author

CaMer0n commented Nov 30, 2023

Thank you for this @Deltik .

Since e107's inception by Jalist over 20 years ago, I, and the other developers through the years, have tried our best to follow his lead, by maintaining the KISS principal "keep-it-simple, stupid!" that he worked by. Not just with the user experience of e107, but also in how it is coded. The goal has always been to minimize complexity, take a minimalist approach, while still trying to maintain a balance, so that the CMS remains both flexible and powerful. Particularly in the areas of plugins, themes and files that users may need to edit, we've always strived to reduce complexity, in order to make the code feel intuitive, even to a non-coder or novice.

So, while I appreciate all the time and effort that must have gone into your proposal, after careful consideration, I don’t find it to be a good fit for e107.

btw. I also took some time to research the format of similar config files for other CMSes while considering your proposal.
Some of them are quite powerful, and function with multiple types of databases.
Here were the results:

  1. WordPress
/** The name of the database for WordPress */
define('DB_NAME', 'database_name');

/** MySQL database username */
define('DB_USER', 'database_username');

/** MySQL database password */
define('DB_PASSWORD', 'database_password');

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');
  1. Joomla
public $dbtype = 'mysqli';
public $host = 'localhost';
public $user = 'database_user';
public $password = 'database_password';
public $db = 'database_name';
public $dbprefix = 'jos_';
  1. Drupal
<?php

/**
 * Database settings:
 */
$databases['default']['default'] = [
  'database' => 'databasename',
  'username' => 'username',
  'password' => 'password',
  'host' => 'localhost',
  'port' => '3306',
  'driver' => 'mysql',
  'prefix' => '',
];

/**
 * Salt for one-time login links, cancel links, form tokens, etc.
 */
$settings['hash_salt'] = 'YOUR_HASH_SALT';

/**
 * Access control for update.php script
 */
$settings['update_free_access'] = FALSE;

/**
 * Default theme
 */
$settings['default_theme'] = 'bartik';
  1. Magento
...
'db' => [
  'table_prefix' => '',
  'connection' => [
    'default' => [
      'host' => 'localhost',
      'dbname' => 'magento',
      'username' => 'root',
      'password' => ‘root’,
      'model' => 'mysql4',
      'engine' => 'innodb',
      'initStatements' => 'SET NAMES utf8;',
      'active' => '1'
    ]
  ]
],
...
  1. PrestaShop
define('_DB_SERVER_', 'localhost');
define('_DB_NAME_', 'database_name');
define('_DB_USER_', 'database_user');
define('_DB_PASSWD_', 'database_password');
define('_DB_PREFIX_', 'ps_');
  1. OpenCart
// DB
define('DB_DRIVER', 'mysqli');
define('DB_HOSTNAME', 'localhost');
define('DB_USERNAME', 'user');
define('DB_PASSWORD', 'pass');
define('DB_DATABASE', 'opencart');
define('DB_PORT', '3306');
define('DB_PREFIX', 'oc_');
  1. Typo3
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['dbname'] = 'your-database-name';
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'] = 'database-user';
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'] = 'password';
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['port'] = '3306';
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] = 'localhost';
  1. ExpressionEngine

ExpressionEngine utilizes a config.php file for management of many settings. Entries look similar to this:

$config['app_version'] = "305";
$config['install_lock'] = "";
$config['license_number'] = "";
$config['debug'] = "1";
$config['cp_url'] = "";
$config['doc_url'] = "http://ellislab.com/expressionengine/user-guide/";
$config['site_label'] = 'My Site';
$config['cookie_prefix'] = '';
  1. Concrete5

In Concrete5, the configuration details are stored as PHP constants inside the site.php file located in the config directory. Entries look like the following:

define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'your_db_username');
define('DB_PASSWORD', 'your_db_password');
define('DB_DATABASE', 'your_database');
define('PASSWORD_SALT', 'random_string_for_encryption');
  1. Craft CMS

Craft CMS utilizes a .env file to store sensitive configuration details. Entries in the .env file are typically as follows:

# The environment Craft is currently running in
ENVIRONMENT="dev"

# The secure key Craft will use for hashing and encrypting data
SECURITY_KEY="your_security_key"

# The data source name (DSN) for connecting to the database
DB_DSN="mysql:host=localhost;dbname=craft"

# The database username
DB_USER="your_db_username"

# The database password
DB_PASSWORD="your_db_password"

# The database table prefix
DB_TABLE_PREFIX="craft"
  1. Grav CMS

In this flat-file CMS, the system configuration is stored as a YAML file in system/config/system.yaml. An example looks as follows:

home:
    alias: '/home'
cache:
    enabled: true
system:
    pages:
        theme: mytheme
    cache:
        gzip: true

@Jimmi08
Copy link
Contributor

Jimmi08 commented Dec 1, 2023

Be aware that f.e. lgsl plugin uses e107_config this way:

        case "e107":
          @include "{$lgsl_file_path}../../../e107_config.php";
          $lgsl_config['db']['server'] = $mySQLserver;
          $lgsl_config['db']['user']   = $mySQLuser;
          $lgsl_config['db']['pass']   = $mySQLpassword;
          $lgsl_config['db']['db']     = $mySQLdefaultdb;
          $lgsl_config['db']['prefix'] = $mySQLprefix;
        break;

@Jimmi08
Copy link
Contributor

Jimmi08 commented Sep 5, 2024

Tested:
With new config there are issues if you renamed folder's names.

#5323

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement An improvement or new feature request
Projects
None yet
Development

No branches or pull requests

3 participants