Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 11 additions & 42 deletions gibbon.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,28 @@
$guid = $gibbon->getConfig('guid');
$caching = $gibbon->getConfig('caching');
$version = $gibbon->getConfig('version');
$session = $container->get('session');
$gibbon->session = $session;

// Setup global absoluteURL for all urls.
Url::setBaseURL($container->get('absoluteURL'));

// Handle Gibbon installation redirect
if (!$gibbon->isInstalled() && !$gibbon->isInstalling()) {
define('SESSION_TABLE_AVAILABLE', false);
header("Location: ./installer/install.php");
exit;
}

// Initialize the database connection
if ($gibbon->isInstalled()) {
$mysqlConnector = new Gibbon\Database\MySqlConnector();

// Display a static error message for database connections after install.
if ($pdo = $mysqlConnector->connect($gibbon->getConfig())) {
// Add the database to the container
if ($container->has('db')) {
$pdo = $container->get('db');

// For legacy modules / functions compatibility.
// TODO: remove this.
$connection2 = $pdo->getConnection();
$container->add('db', $pdo);
$container->share(Gibbon\Contracts\Database\Connection::class, $pdo);

// Add a feature flag here to prevent errors before updating
// TODO: this can likely be removed in v24+
if (!defined('SESSION_TABLE_AVAILABLE')) {
$hasSessionTable = $pdo->selectOne("SHOW TABLES LIKE 'gibbonSession'");
define('SESSION_TABLE_AVAILABLE', !empty($hasSessionTable));
}

// Initialize core
try {
Expand All @@ -98,7 +95,7 @@
include __DIR__.'/error.php';
exit;
}

} else {
if (!$gibbon->isInstalling()) {
$message = sprintf(__('A database connection could not be established. Please %1$stry again%2$s.'), '', '');
Expand All @@ -108,34 +105,6 @@
}
}

if (!defined('SESSION_TABLE_AVAILABLE')) {
define('SESSION_TABLE_AVAILABLE', false);
}

// Globals for backwards compatibility
$session = $container->get('session');
$gibbon->session = $session;
$container->share(\Gibbon\Contracts\Services\Session::class, $session);

// Setup global absoluteURL for all urls.
if ($gibbon->isInstalled() && $session->has('absoluteURL')) {
Url::setBaseUrl($session->get('absoluteURL'));
} else {
// TODO: put this absoluteURL detection somewhere?
$absoluteURL = (function () {
// Find out the base installation URL path.
$prefixLength = strlen(realpath($_SERVER['DOCUMENT_ROOT']));
$baseDir = realpath(__DIR__) . '/';
$urlBasePath = substr($baseDir, $prefixLength);

// Construct the full URL to the base URL path.
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$protocol = !empty($_SERVER['HTTPS']) ? 'https' : 'http';
return "{$protocol}://{$host}{$urlBasePath}";
})();
Url::setBaseUrl($absoluteURL);
}

// Autoload the current module namespace
if (!empty($session->get('module'))) {
$moduleNamespace = preg_replace('/[^a-zA-Z0-9]/', '', $session->get('module'));
Expand Down
5 changes: 3 additions & 2 deletions index_notification_ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@
// Check for session timeout
$sessionGateway = $container->get(SessionGateway::class);
$sessionInfo = $sessionGateway->getByID(session_id());
if (\SESSION_TABLE_AVAILABLE && !empty($sessionInfo)) {
$sessionTableHasSetup = $container->has('sessionTableHasSetup') && $container->get('sessionTableHasSetup');
if ($sessionTableHasSetup && !empty($sessionInfo)) {
$sessionLastActive = strtotime($sessionInfo['timestampModified']);
$sessionDuration = $session->get('sessionDuration');
$timeDifference = time() - $sessionLastActive;

if (empty($sessionInfo['gibbonPersonID']) || (isset($sessionInfo['sessionStatus']) && empty($sessionInfo['sessionStatus']))) {
$result['timeout'] = 'force';
} elseif ($timeDifference > $sessionDuration) {
Expand Down
7 changes: 2 additions & 5 deletions src/Gibbon/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,10 @@ public function initializeCore(ContainerInterface $container)
ini_set('display_errors', 0);
}

$this->locale->setLocale($this->session->get(array('i18n', 'code')));
$this->locale->setTimezone($this->session->get('timezone', 'UTC'));
$this->locale->setTextDomain($db);
$this->locale->setStringReplacementList($this->session, $db);
$sessionTableHasSetup = $container->has('sessionTableHasSetup') && $container->get('sessionTableHasSetup');

// Update the information for this session (except in ajax scripts)
if (\SESSION_TABLE_AVAILABLE && stripos($this->session->get('action'), 'ajax') === false) {
if ($sessionTableHasSetup && stripos($this->session->get('action'), 'ajax') === false) {
$container->get(SessionGateway::class)->updateSessionAction(session_id(), $this->session->get('action'), $this->session->get('module'), $this->session->get('gibbonPersonID'));
}

Expand Down
94 changes: 87 additions & 7 deletions src/Services/CoreServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,18 @@
use Gibbon\View\View;
use Gibbon\Comms\Mailer;
use Gibbon\Data\Validator;
use Gibbon\Session\Session;
use Gibbon\Domain\System\Theme;
use Gibbon\Domain\System\Module;
use Gibbon\Session\SessionFactory;
use Gibbon\Services\Payment\Payment;
use Gibbon\Domain\System\SettingGateway;
use Gibbon\Contracts\Comms\SMS as SMSInterface;
use Gibbon\Contracts\Comms\Mailer as MailerInterface;
use Gibbon\Contracts\Database\Connection;
use Gibbon\Contracts\Services\Payment as PaymentInterface;
use Gibbon\Contracts\Services\Session as SessionInterface;
use Gibbon\Data\PasswordPolicy;
use Gibbon\Database\MySqlConnector;
use League\Container\ServiceProvider\AbstractServiceProvider;
use League\Container\ServiceProvider\BootableServiceProviderInterface;

Expand Down Expand Up @@ -73,9 +74,11 @@ public function __construct($absolutePath)
'page',
'module',
'theme',
'sessionTableHasSetup',
PaymentInterface::class,
MailerInterface::class,
SMSInterface::class,
SessionInterface::class,
'gibbon_logger',
'mysql_logger',
Validator::class,
Expand All @@ -97,8 +100,89 @@ public function boot()
{
$container = $this->getLeagueContainer();

$container->share('config', new Core($this->absolutePath));
$container->share('locale', new Locale($this->absolutePath));
$core = new Core($this->absolutePath);

// TODO: decouple config file reading logics from Core to prevent cyclic
// reference in building 'config' (Core) object.
// TODO: migrate Core object setup to this provider
// (i.e. $gibbon->locale and $gibbon->session).
$container->share('config', $core);

// If configuration exists, create and share the database connection.
$config = $core->getConfig();
if (!empty($config['databaseUsername']) && isset($config['databasePassword'])) {

// Tell others that we provide db.
array_push($this->provides, 'db', Connection::class);

// Recipe of creating db.
$container->share('db', function () {
return $this->getContainer()->get(Connection::class);
});
$container->share(Connection::class, function () use ($config) {
// Create connector to connect database.
return (new MySqlConnector())->connect($config);
});
}

// Define internal variable.
$container->add('sessionTableHasSetup', function () {
$container = $this->getContainer();
if (!$container->has(Connection::class)) {
return false;
}
$connection = $container->get(Connection::class);
$hasSessionTable = $connection->selectOne("SHOW TABLES LIKE 'gibbonSession'");
return !empty($hasSessionTable);
}, false);

// Define how session can be created.
$container->share('session', function () {
return $this->getContainer()->get(SessionInterface::class);
});
$container->share(SessionInterface::class, function () {
$container = $this->getContainer();
$sessionTableHasSetup = $container->has('sessionTableHasSetup') && $container->get('sessionTableHasSetup');
return SessionFactory::create($this->getContainer(), $sessionTableHasSetup);
});

// Define locale object.
$container->share('locale', function () {
// Get dependencies.
$container = $this->getContainer();
$session = $container->get(SessionInterface::class);

// Create locale instance.
$locale = new Locale($this->absolutePath);
$locale->setLocale($session->get(array('i18n', 'code')));
$locale->setTimezone($session->get('timezone', 'UTC'));

// If database is configured, setup the text domain and string replacement.
if ($container->has('db')) {
$db = $container->get(Connection::class);
$locale->setTextDomain($db);
$locale->setStringReplacementList($session, $db);
}
return $locale;
});

// Setup global absoluteURL of all URLs.
$container->share('absoluteURL', function () use ($core) {
$session = $this->getContainer()->get(SessionInterface::class);
if ($core->isInstalled() && $session->has('absoluteURL')) {
return $session->get('absoluteURL');
}

// Find out the base installation URL path.
$prefixLength = strlen(realpath($_SERVER['DOCUMENT_ROOT']));
$baseDir = realpath(__DIR__ . '/../../') . '/';
$urlBasePath = substr($baseDir, $prefixLength);

// Construct the full URL to the base URL path.
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$protocol = !empty($_SERVER['HTTPS']) ? 'https' : 'http';
return "{$protocol}://{$host}{$urlBasePath}";
});
}

/**
Expand Down Expand Up @@ -126,10 +210,6 @@ public function register()

// $pdo->setLogger($container->get('mysql_logger'));

$container->share('session', function () {
return SessionFactory::create($this->getContainer());
});

$container->share('twig', function () use ($absolutePath) {
$session = $this->getLeagueContainer()->get('session');
$loader = new \Twig\Loader\FilesystemLoader($absolutePath.'/resources/templates');
Expand Down
11 changes: 7 additions & 4 deletions src/Session/SessionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ class SessionFactory
*
* @return \Gibbon\Session\Session The newly created session object.
*/
public static function create(ContainerInterface $container): SessionInterface {
public static function create(
ContainerInterface $container,
bool $sessionTableHasSetup = false
): SessionInterface {
global $guid;

$config = $container->get('config')->getConfig();
Expand All @@ -56,9 +59,9 @@ public static function create(ContainerInterface $container): SessionInterface {

// Start the session (this should be the first time called)
if (session_status() !== PHP_SESSION_ACTIVE) {

// Check if the database exists, if not, use the built-in PHP session handler class
if (\SESSION_TABLE_AVAILABLE && $container->has(Connection::class)) {
if ($container->has(Connection::class) && $sessionTableHasSetup) {
$sessionGateway = $container->get(SessionGateway::class);

if (!empty($config['sessionHandler']) && $config['sessionHandler'] == 'database') {
Expand All @@ -69,7 +72,7 @@ public static function create(ContainerInterface $container): SessionInterface {
} else {
$handler = new SessionHandler();
}

// Set the handler for the session, enabling non-default
session_set_save_handler($handler, true);

Expand Down
2 changes: 1 addition & 1 deletion src/View/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Page extends View
* @param array $params Essential parameters for building a page.
*/
public function __construct(ContainerInterface $container = null, array $params = [])
{
{
parent::__construct($container ? $container->get('twig') : null);

$this->breadcrumbs = new Breadcrumbs();
Expand Down