Browse Source

Singleton pattern for Settings::get(), Database::get() and Plugins::get()

What could properly go wrong? ¯\_(ツ)_/¯
Tobias Reich 9 years ago
parent
commit
17e5dba979

File diff suppressed because it is too large
+ 0 - 0
dist/main.js


+ 11 - 25
docs/Plugins.md

@@ -11,33 +11,19 @@ The plugin-system of Lychee allows you to execute scripts, when a certain action
 
 ### How to create a plugin
 
-1. Create a folder in `plugins/`
-2. Create an `index.php` within the new folder and with the following content:
+1. Create a folder in `plugins/` (e.g. `plugins/ExamplePlugin/`)
+2. Create an `ExamplePlugin.php` file within the new folder and add the following content:
 
 ```php
 <?php
 
-###
-# @name			ExamplePlugin
-# @author		Tobias Reich
-# @copyright	2015 by Tobias Reich
-###
-
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 class ExamplePlugin implements SplObserver {
 
-	private $database = null;
-	private $settings = null;
-
-	public function __construct($database, $settings) {
-
-		# These params are passed to your plugin from Lychee
-		# Save them to access the database and settings of Lychee
-		$this->database = $database;
-		$this->settings = $settings;
+	public function __construct() {
 
-		# Add more code here if wanted
+		# Add code here if wanted
 		# __construct() will be called every time Lychee gets called
 		# Make sure this part is performant
 
@@ -52,8 +38,9 @@ class ExamplePlugin implements SplObserver {
 		if ($subject->action!=='Photo::add:before') return false;
 
 		# Do something when Photo::add:before gets called
-		# $this->database => The database of Lychee
-		# $this->settings => The settings of Lychee
+		# Database::get() => Database connection of Lychee
+		# Settings::get() => Settings of Lychee
+		# $subject->action => Called hook
 		# $subject->args => Params passed to the original function
 
 		return true;
@@ -62,15 +49,14 @@ class ExamplePlugin implements SplObserver {
 
 }
 
-# Register your plugin
-$plugins->attach(new ExamplePlugin($database, $settings));
+?>
 ```
 
-3. Add the plugin-path to the database of Lychee
+3. Add the class name to the database of Lychee
 
-Select the table `lychee_settings` and edit the value of `plugins` to the path of your plugin. The path must be relative from the `plugins/`-folder: `ExamplePlugin/index.php`.
+Select the table `lychee_settings` and add the name of the class to the value of `plugins` (e.g. `ExamplePlugin`). Please ensure that the folder has the same name as the class and as the file.
 
-Divide multiple plugins with semicolons: `Plugin01/index.php;Plugin02/index.php`.
+Divide multiple plugins with semicolons: `ExamplePlugin;ExampleTwoPlugin`.
 
 ### Available hooks
 

+ 2 - 15
php/access/Access.php

@@ -7,22 +7,9 @@
 
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
-class Access {
+abstract class Access {
 
-	protected $database	= null;
-	protected $plugins	= null;
-	protected $settings	= null;
-
-	public function __construct($database, $plugins, $settings) {
-
-		# Init vars
-		$this->database	= $database;
-		$this->plugins	= $plugins;
-		$this->settings	= $settings;
-
-		return true;
-
-	}
+	abstract protected function check($fn);
 
 }
 

+ 31 - 35
php/access/Admin.php

@@ -6,7 +6,6 @@
 ###
 
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
-if (!defined('LYCHEE_ACCESS_ADMIN')) exit('Error: You are not allowed to access this area!');
 
 final class Admin extends Access {
 
@@ -71,7 +70,7 @@ final class Admin extends Access {
 
 	private function getAlbums() {
 
-		$album = new Album($this->database, $this->plugins, $this->settings, null);
+		$album = new Album(null);
 		echo json_encode($album->getAll(false));
 
 	}
@@ -79,7 +78,7 @@ final class Admin extends Access {
 	private function getAlbum() {
 
 		Module::dependencies(isset($_POST['albumID']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
+		$album = new Album($_POST['albumID']);
 		echo json_encode($album->get());
 
 	}
@@ -87,7 +86,7 @@ final class Admin extends Access {
 	private function addAlbum() {
 
 		Module::dependencies(isset($_POST['title']));
-		$album = new Album($this->database, $this->plugins, $this->settings, null);
+		$album = new Album(null);
 		echo $album->add($_POST['title']);
 
 	}
@@ -95,7 +94,7 @@ final class Admin extends Access {
 	private function setAlbumTitle() {
 
 		Module::dependencies(isset($_POST['albumIDs'], $_POST['title']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']);
+		$album = new Album($_POST['albumIDs']);
 		echo $album->setTitle($_POST['title']);
 
 	}
@@ -103,7 +102,7 @@ final class Admin extends Access {
 	private function setAlbumDescription() {
 
 		Module::dependencies(isset($_POST['albumID'], $_POST['description']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
+		$album = new Album($_POST['albumID']);
 		echo $album->setDescription($_POST['description']);
 
 	}
@@ -111,7 +110,7 @@ final class Admin extends Access {
 	private function setAlbumPublic() {
 
 		Module::dependencies(isset($_POST['albumID'], $_POST['password'], $_POST['visible'], $_POST['downloadable']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
+		$album = new Album($_POST['albumID']);
 		echo $album->setPublic($_POST['public'], $_POST['password'], $_POST['visible'], $_POST['downloadable']);
 
 	}
@@ -119,7 +118,7 @@ final class Admin extends Access {
 	private function deleteAlbum() {
 
 		Module::dependencies(isset($_POST['albumIDs']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']);
+		$album = new Album($_POST['albumIDs']);
 		echo $album->delete();
 
 	}
@@ -127,7 +126,7 @@ final class Admin extends Access {
 	private function mergeAlbums() {
 
 		Module::dependencies(isset($_POST['albumIDs']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']);
+		$album = new Album($_POST['albumIDs']);
 		echo $album->merge();
 
 	}
@@ -137,7 +136,7 @@ final class Admin extends Access {
 	private function getPhoto() {
 
 		Module::dependencies(isset($_POST['photoID'], $_POST['albumID']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
+		$photo = new Photo($_POST['photoID']);
 		echo json_encode($photo->get($_POST['albumID']));
 
 	}
@@ -145,7 +144,7 @@ final class Admin extends Access {
 	private function setPhotoTitle() {
 
 		Module::dependencies(isset($_POST['photoIDs'], $_POST['title']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
+		$photo = new Photo($_POST['photoIDs']);
 		echo $photo->setTitle($_POST['title']);
 
 	}
@@ -153,7 +152,7 @@ final class Admin extends Access {
 	private function setPhotoDescription() {
 
 		Module::dependencies(isset($_POST['photoID'], $_POST['description']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
+		$photo = new Photo($_POST['photoID']);
 		echo $photo->setDescription($_POST['description']);
 
 	}
@@ -161,7 +160,7 @@ final class Admin extends Access {
 	private function setPhotoStar() {
 
 		Module::dependencies(isset($_POST['photoIDs']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
+		$photo = new Photo($_POST['photoIDs']);
 		echo $photo->setStar();
 
 	}
@@ -169,7 +168,7 @@ final class Admin extends Access {
 	private function setPhotoPublic() {
 
 		Module::dependencies(isset($_POST['photoID']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
+		$photo = new Photo($_POST['photoID']);
 		echo $photo->setPublic();
 
 	}
@@ -177,7 +176,7 @@ final class Admin extends Access {
 	private function setPhotoAlbum() {
 
 		Module::dependencies(isset($_POST['photoIDs'], $_POST['albumID']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
+		$photo = new Photo($_POST['photoIDs']);
 		echo $photo->setAlbum($_POST['albumID']);
 
 	}
@@ -185,7 +184,7 @@ final class Admin extends Access {
 	private function setPhotoTags() {
 
 		Module::dependencies(isset($_POST['photoIDs'], $_POST['tags']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
+		$photo = new Photo($_POST['photoIDs']);
 		echo $photo->setTags($_POST['tags']);
 
 	}
@@ -193,7 +192,7 @@ final class Admin extends Access {
 	private function duplicatePhoto() {
 
 		Module::dependencies(isset($_POST['photoIDs']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
+		$photo = new Photo($_POST['photoIDs']);
 		echo $photo->duplicate();
 
 	}
@@ -201,7 +200,7 @@ final class Admin extends Access {
 	private function deletePhoto() {
 
 		Module::dependencies(isset($_POST['photoIDs']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
+		$photo = new Photo($_POST['photoIDs']);
 		echo $photo->delete();
 
 	}
@@ -211,7 +210,7 @@ final class Admin extends Access {
 	private function upload() {
 
 		Module::dependencies(isset($_FILES, $_POST['albumID'], $_POST['tags']));
-		$photo = new Photo($this->database, $this->plugins, $this->settings, null);
+		$photo = new Photo(null);
 		echo $photo->add($_FILES, $_POST['albumID'], '', $_POST['tags']);
 
 	}
@@ -219,7 +218,7 @@ final class Admin extends Access {
 	private function importUrl() {
 
 		Module::dependencies(isset($_POST['url'], $_POST['albumID']));
-		$import = new Import($this->database, $this->plugins, $this->settings);
+		$import = new Import();
 		echo $import->url($_POST['url'], $_POST['albumID']);
 
 	}
@@ -227,7 +226,7 @@ final class Admin extends Access {
 	private function importServer() {
 
 		Module::dependencies(isset($_POST['albumID'], $_POST['path']));
-		$import = new Import($this->database, $this->plugins, $this->settings);
+		$import = new Import();
 		echo $import->server($_POST['path'], $_POST['albumID']);
 
 	}
@@ -237,7 +236,7 @@ final class Admin extends Access {
 	private function search() {
 
 		Module::dependencies(isset($_POST['term']));
-		echo json_encode(search($this->database, $this->settings, $_POST['term']));
+		echo json_encode(search($_POST['term']));
 
 	}
 
@@ -247,22 +246,22 @@ final class Admin extends Access {
 
 		global $dbName;
 
-		$session = new Session($this->plugins, $this->settings);
-		echo json_encode($session->init($this->database, $dbName, false));
+		$session = new Session();
+		echo json_encode($session->init(false));
 
 	}
 
 	private function login() {
 
 		Module::dependencies(isset($_POST['user'], $_POST['password']));
-		$session = new Session($this->plugins, $this->settings);
+		$session = new Session();
 		echo $session->login($_POST['user'], $_POST['password']);
 
 	}
 
 	private function logout() {
 
-		$session = new Session($this->plugins, $this->settings);
+		$session = new Session();
 		echo $session->logout();
 
 	}
@@ -273,18 +272,16 @@ final class Admin extends Access {
 
 		Module::dependencies(isset($_POST['username'], $_POST['password']));
 		if (!isset($_POST['oldPassword'])) $_POST['oldPassword'] = '';
-		$this->settings = new Settings($this->database);
-		echo $this->settings->setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']);
+		echo Settings::setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']);
 
 	}
 
 	private function setSorting() {
 
 		Module::dependencies(isset($_POST['typeAlbums'], $_POST['orderAlbums'], $_POST['typePhotos'], $_POST['orderPhotos']));
-		$this->settings = new Settings($this->database);
 
-		$sA = $this->settings->setSortingAlbums($_POST['typeAlbums'], $_POST['orderAlbums']);
-		$sP = $this->settings->setSortingPhotos($_POST['typePhotos'], $_POST['orderPhotos']);
+		$sA = Settings::setSortingAlbums($_POST['typeAlbums'], $_POST['orderAlbums']);
+		$sP = Settings::setSortingPhotos($_POST['typePhotos'], $_POST['orderPhotos']);
 
 		if ($sA===true&&$sP===true)	echo true;
 		else						echo false;
@@ -294,8 +291,7 @@ final class Admin extends Access {
 	private function setDropboxKey() {
 
 		Module::dependencies(isset($_POST['key']));
-		$this->settings = new Settings($this->database);
-		echo $this->settings->setDropboxKey($_POST['key']);
+		echo Settings::setDropboxKey($_POST['key']);
 
 	}
 
@@ -304,7 +300,7 @@ final class Admin extends Access {
 	private function getAlbumArchive() {
 
 		Module::dependencies(isset($_GET['albumID']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_GET['albumID']);
+		$album = new Album($_GET['albumID']);
 		$album->getArchive();
 
 	}
@@ -312,7 +308,7 @@ final class Admin extends Access {
 	private function getPhotoArchive() {
 
 		Module::dependencies(isset($_GET['photoID']));
-		$photo = new Photo($this->database, $this->plugins, null, $_GET['photoID']);
+		$photo = new Photo($_GET['photoID']);
 		$photo->getArchive();
 
 	}

+ 10 - 11
php/access/Guest.php

@@ -6,7 +6,6 @@
 ###
 
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
-if (!defined('LYCHEE_ACCESS_GUEST')) exit('Error: You are not allowed to access this area!');
 
 final class Guest extends Access {
 
@@ -45,7 +44,7 @@ final class Guest extends Access {
 
 	private function getAlbums() {
 
-		$album = new Album($this->database, $this->plugins, $this->settings, null);
+		$album = new Album(null);
 		echo json_encode($album->getAll(true));
 
 	}
@@ -53,7 +52,7 @@ final class Guest extends Access {
 	private function getAlbum() {
 
 		Module::dependencies(isset($_POST['albumID'], $_POST['password']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
+		$album = new Album($_POST['albumID']);
 
 		if ($album->getPublic()) {
 
@@ -73,7 +72,7 @@ final class Guest extends Access {
 	private function checkAlbumAccess() {
 
 		Module::dependencies(isset($_POST['albumID'], $_POST['password']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
+		$album = new Album($_POST['albumID']);
 
 		if ($album->getPublic()) {
 
@@ -95,7 +94,7 @@ final class Guest extends Access {
 	private function getPhoto() {
 
 		Module::dependencies(isset($_POST['photoID'], $_POST['albumID'], $_POST['password']));
-		$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
+		$photo = new Photo($_POST['photoID']);
 
 		$pgP = $photo->getPublic($_POST['password']);
 
@@ -111,22 +110,22 @@ final class Guest extends Access {
 
 		global $dbName;
 
-		$session = new Session($this->plugins, $this->settings);
-		echo json_encode($session->init($this->database, $dbName, true));
+		$session = new Session();
+		echo json_encode($session->init(true));
 
 	}
 
 	private function login() {
 
 		Module::dependencies(isset($_POST['user'], $_POST['password']));
-		$session = new Session($this->plugins, $this->settings);
+		$session = new Session();
 		echo $session->login($_POST['user'], $_POST['password']);
 
 	}
 
 	private function logout() {
 
-		$session = new Session($this->plugins, $this->settings);
+		$session = new Session();
 		echo $session->logout();
 
 	}
@@ -136,7 +135,7 @@ final class Guest extends Access {
 	private function getAlbumArchive() {
 
 		Module::dependencies(isset($_GET['albumID'], $_GET['password']));
-		$album = new Album($this->database, $this->plugins, $this->settings, $_GET['albumID']);
+		$album = new Album($_GET['albumID']);
 
 		if ($album->getPublic()&&$album->getDownloadable()) {
 
@@ -156,7 +155,7 @@ final class Guest extends Access {
 	private function getPhotoArchive() {
 
 		Module::dependencies(isset($_GET['photoID'], $_GET['password']));
-		$photo = new Photo($this->database, $this->plugins, null, $_GET['photoID']);
+		$photo = new Photo($_GET['photoID']);
 
 		$pgP = $photo->getPublic($_GET['password']);
 

+ 4 - 5
php/access/Installation.php

@@ -6,7 +6,6 @@
 ###
 
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
-if (!defined('LYCHEE_ACCESS_INSTALLATION')) exit('Error: You are not allowed to access this area!');
 
 final class Installation extends Access {
 
@@ -14,10 +13,10 @@ final class Installation extends Access {
 
 		switch ($fn) {
 
-			case 'Database::createConfig':	$this->dbCreateConfig(); break;
+			case 'Config::create':	$this->configCreate(); break;
 
 			# Error
-			default:						$this->init(); break;
+			default:				$this->init(); break;
 
 		}
 
@@ -25,10 +24,10 @@ final class Installation extends Access {
 
 	}
 
-	private function dbCreateConfig() {
+	private function configCreate() {
 
 		Module::dependencies(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']));
-		echo Database::createConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']);
+		echo Config::create($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']);
 
 	}
 

+ 6 - 27
php/api.php

@@ -29,49 +29,30 @@ if (!empty($fn)) {
 	if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1)		exit('Error: Wrong parameter type for photoID!');
 
 	# Check if a configuration exists
-	if (file_exists(LYCHEE_CONFIG_FILE)) require(LYCHEE_CONFIG_FILE);
-	else {
+	if (Config::exists()===false) {
 
 		###
 		# Installation Access
 		# Limited access to configure Lychee. Only available when the config.php file is missing.
 		###
 
-		define('LYCHEE_ACCESS_INSTALLATION', true);
-
-		$installation = new Installation(null, null, null);
-		$installation->check($_POST['function']);
+		$installation = new Installation();
+		$installation->check($fn);
 
 		exit();
 
 	}
 
-	# Define the table prefix
-	defineTablePrefix(@$dbTablePrefix);
-
-	# Connect to database
-	$database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName);
-
-	# Load settings
-	$settings = new Settings($database);
-	$settings = $settings->get();
-
-	# Init plugins
-	$plugins = explode(';', $settings['plugins']);
-	$plugins = new Plugins($plugins, $database, $settings);
-
 	# Check if user is logged
 	if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&&
-		(isset($_SESSION['identifier'])&&$_SESSION['identifier']===$settings['identifier'])) {
+		(isset($_SESSION['identifier'])&&$_SESSION['identifier']===Settings::get()['identifier'])) {
 
 		###
 		# Admin Access
 		# Full access to Lychee. Only with correct password/session.
 		###
 
-		define('LYCHEE_ACCESS_ADMIN', true);
-
-		$admin = new Admin($database, $plugins, $settings);
+		$admin = new Admin();
 		$admin->check($fn);
 
 	} else {
@@ -81,9 +62,7 @@ if (!empty($fn)) {
 		# Access to view all public folders and photos in Lychee.
 		###
 
-		define('LYCHEE_ACCESS_GUEST', true);
-
-		$guest = new Guest($database, $plugins, $settings);
+		$guest = new Guest();
 		$guest->check($fn);
 
 	}

+ 8 - 0
php/autoload.php

@@ -23,4 +23,12 @@ spl_autoload_register(function($class) {
 
 });
 
+spl_autoload_register(function($class) {
+
+	$file = LYCHEE . 'plugins/' . $class . '/' . $class . '.php';
+
+	if (file_exists($file)===true) require $file;
+
+});
+
 ?>

+ 12 - 12
php/database/update_020700.php

@@ -8,12 +8,12 @@
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 # Add medium to photos
-$query = Database::prepare($database, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS));
-if (!$database->query($query)) {
-	$query	= Database::prepare($database, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS));
-	$result	= $database->query($query);
+$query = Database::prepare($connection, "SELECT `medium` FROM `?` LIMIT 1", array(LYCHEE_TABLE_PHOTOS));
+if (!$connection->query($query)) {
+	$query	= Database::prepare($connection, "ALTER TABLE `?` ADD `medium` TINYINT(1) NOT NULL DEFAULT 0", array(LYCHEE_TABLE_PHOTOS));
+	$result	= $connection->query($query);
 	if (!$result) {
-		Log::error($database, 'update_020700', __LINE__, 'Could not update database (' . $database->error . ')');
+		Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')');
 		return false;
 	}
 }
@@ -22,22 +22,22 @@ if (!$database->query($query)) {
 if (is_dir(LYCHEE_UPLOADS_MEDIUM)===false) {
 	# Only create the folder when it is missing
 	if (@mkdir(LYCHEE_UPLOADS_MEDIUM)===false)
-		Log::error($database, 'update_020700', __LINE__, 'Could not create medium-folder');
+		Log::error('update_020700', __LINE__, 'Could not create medium-folder');
 }
 
 # Add medium to settings
-$query	= Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
-$result	= $database->query($query);
+$query	= Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'medium' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
+$result	= $connection->query($query);
 if ($result->num_rows===0) {
-	$query	= Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS));
-	$result	= $database->query($query);
+	$query	= Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('medium', '1')", array(LYCHEE_TABLE_SETTINGS));
+	$result	= $connection->query($query);
 	if (!$result) {
-		Log::error($database, 'update_020700', __LINE__, 'Could not update database (' . $database->error . ')');
+		Log::error('update_020700', __LINE__, 'Could not update database (' . $connection->error . ')');
 		return false;
 	}
 }
 
 # Set version
-if (Database::setVersion($database, '020700')===false) return false;
+if (Database::setVersion($connection, '020700')===false) return false;
 
 ?>

+ 10 - 10
php/database/update_030000.php

@@ -9,29 +9,29 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 # Remove login
 # Login now saved as crypt without md5. Legacy code has been removed.
-$query			= Database::prepare($database, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
-$resetUsername	= $database->query($query);
+$query			= Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'username' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
+$resetUsername	= $connection->query($query);
 if (!$resetUsername) {
-	Log::error($database, 'update_030000', __LINE__, 'Could not reset username (' . $database->error . ')');
+	Log::error('update_030000', __LINE__, 'Could not reset username (' . $connection->error . ')');
 	return false;
 }
-$query			= Database::prepare($database, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
-$resetPassword	= $database->query($query);
+$query			= Database::prepare($connection, "UPDATE `?` SET `value` = '' WHERE `key` = 'password' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
+$resetPassword	= $connection->query($query);
 if (!$resetPassword) {
-	Log::error($database, 'update_030000', __LINE__, 'Could not reset password (' . $database->error . ')');
+	Log::error('update_030000', __LINE__, 'Could not reset password (' . $connection->error . ')');
 	return false;
 }
 
 # Make public albums private and reset password
 # Password now saved as crypt without md5. Legacy code has been removed.
-$query			= Database::prepare($database, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS));
-$resetPublic	= $database->query($query);
+$query			= Database::prepare($connection, "UPDATE `?` SET `public` = 0, `password` = NULL", array(LYCHEE_TABLE_ALBUMS));
+$resetPublic	= $connection->query($query);
 if (!$resetPublic) {
-	Log::error($database, 'update_030000', __LINE__, 'Could not reset public albums (' . $database->error . ')');
+	Log::error('update_030000', __LINE__, 'Could not reset public albums (' . $connection->error . ')');
 	return false;
 }
 
 # Set version
-if (Database::setVersion($database, '030000')===false) return false;
+if (Database::setVersion($connection, '030000')===false) return false;
 
 ?>

+ 20 - 20
php/database/update_030001.php

@@ -8,55 +8,55 @@
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 # Change length of photo title
-$query	= Database::prepare($database, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS));
-$result	= $database->query($query);
+$query	= Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_PHOTOS));
+$result	= $connection->query($query);
 if (!$result) {
-	Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')');
+	Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')');
 	return false;
 }
 
 # Change length of album title
-$query	= Database::prepare($database, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS));
-$result	= $database->query($query);
+$query	= Database::prepare($connection, "ALTER TABLE `?` CHANGE `title` `title` VARCHAR( 100 ) NOT NULL DEFAULT ''", array(LYCHEE_TABLE_ALBUMS));
+$result	= $connection->query($query);
 if (!$result) {
-	Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')');
+	Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')');
 	return false;
 }
 
 # Add album sorting to settings
-$query	= Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
-$result	= $database->query($query);
+$query	= Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'sortingAlbums' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
+$result	= $connection->query($query);
 if ($result->num_rows===0) {
-	$query	= Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS));
-	$result	= $database->query($query);
+	$query	= Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('sortingAlbums', 'ORDER BY id DESC')", array(LYCHEE_TABLE_SETTINGS));
+	$result	= $connection->query($query);
 	if (!$result) {
-		Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')');
+		Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')');
 		return false;
 	}
 }
 
 # Rename sorting to sortingPhotos
-$query	= Database::prepare($database, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
-$result	= $database->query($query);
+$query	= Database::prepare($connection, "UPDATE ? SET `key` = 'sortingPhotos' WHERE `key` = 'sorting' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
+$result	= $connection->query($query);
 if (!$result) {
-	Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')');
+	Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')');
 	return false;
 }
 
 # Add identifier to settings
-$query	= Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
-$result	= $database->query($query);
+$query	= Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
+$result	= $connection->query($query);
 if ($result->num_rows===0) {
 	$identifier	= md5(microtime(true));
-	$query		= Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier));
-	$result		= $database->query($query);
+	$query		= Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('identifier', '?')", array(LYCHEE_TABLE_SETTINGS, $identifier));
+	$result		= $connection->query($query);
 	if (!$result) {
-		Log::error($database, 'update_030001', __LINE__, 'Could not update database (' . $database->error . ')');
+		Log::error('update_030001', __LINE__, 'Could not update database (' . $connection->error . ')');
 		return false;
 	}
 }
 
 # Set version
-if (Database::setVersion($database, '030001')===false) return false;
+if (Database::setVersion($connection, '030001')===false) return false;
 
 ?>

+ 6 - 6
php/database/update_030003.php

@@ -8,18 +8,18 @@
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 # Add skipDuplicates to settings
-$query	= Database::prepare($database, "SELECT `key` FROM `?` WHERE `key` = 'skipDuplicates' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
-$result	= $database->query($query);
+$query	= Database::prepare($connection, "SELECT `key` FROM `?` WHERE `key` = 'skipDuplicates' LIMIT 1", array(LYCHEE_TABLE_SETTINGS));
+$result	= $connection->query($query);
 if ($result->num_rows===0) {
-	$query	= Database::prepare($database, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS));
-	$result	= $database->query($query);
+	$query	= Database::prepare($connection, "INSERT INTO `?` (`key`, `value`) VALUES ('skipDuplicates', '0')", array(LYCHEE_TABLE_SETTINGS));
+	$result	= $connection->query($query);
 	if (!$result) {
-		Log::error($database, 'update_030003', __LINE__, 'Could not update database (' . $database->error . ')');
+		Log::error('update_030003', __LINE__, 'Could not update database (' . $connection->error . ')');
 		return false;
 	}
 }
 
 # Set version
-if (Database::setVersion($database, '030003')===false) return false;
+if (Database::setVersion($connection, '030003')===false) return false;
 
 ?>

+ 90 - 97
php/modules/Album.php

@@ -9,26 +9,18 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Album extends Module {
 
-	private $database	= null;
-	private $settings	= null;
 	private $albumIDs	= null;
 
-	public function __construct($database, $plugins, $settings, $albumIDs) {
+	public function __construct($albumIDs) {
 
 		# Init vars
-		$this->database	= $database;
-		$this->plugins	= $plugins;
-		$this->settings	= $settings;
 		$this->albumIDs	= $albumIDs;
 
 		return true;
 
 	}
 
-	public function add($title = 'Untitled', $public = 0, $visible = 1) {
-
-		# Check dependencies
-		self::dependencies(isset($this->database));
+	public function add($title = 'Untitled') {
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -36,19 +28,23 @@ final class Album extends Module {
 		# Parse
 		if (strlen($title)>50) $title = substr($title, 0, 50);
 
+		# Properties
+		$public		= 0;
+		$visible	= 1;
+
 		# Database
 		$sysstamp	= time();
-		$query		= Database::prepare($this->database, "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible));
-		$result		= $this->database->query($query);
+		$query		= Database::prepare(Database::get(), "INSERT INTO ? (title, sysstamp, public, visible) VALUES ('?', '?', '?', '?')", array(LYCHEE_TABLE_ALBUMS, $title, $sysstamp, $public, $visible));
+		$result		= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
-		return $this->database->insert_id;
+		return Database::get()->insert_id;
 
 	}
 
@@ -91,7 +87,7 @@ final class Album extends Module {
 	public function get() {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->settings, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -100,32 +96,32 @@ final class Album extends Module {
 		switch ($this->albumIDs) {
 
 			case 'f':	$return['public'] = '0';
-						$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE star = 1 " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+						$query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE star = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
 						break;
 
 			case 's':	$return['public'] = '0';
-						$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE public = 1 " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+						$query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE public = 1 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
 						break;
 
 			case 'r':	$return['public'] = '0';
-						$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+						$query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
 						break;
 
 			case '0':	$return['public'] = '0';
-						$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = 0 " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+						$query = Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = 0 " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
 						break;
 
-			default:	$query	= Database::prepare($this->database, "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
-						$albums = $this->database->query($query);
+			default:	$query	= Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+						$albums = Database::get()->query($query);
 						$return = $albums->fetch_assoc();
 						$return = Album::prepareData($return);
-						$query	= Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
+						$query	= Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
 						break;
 
 		}
 
 		# Get photos
-		$photos				= $this->database->query($query);
+		$photos				= Database::get()->query($query);
 		$previousPhotoID	= '';
 		while ($photo = $photos->fetch_assoc()) {
 
@@ -178,7 +174,7 @@ final class Album extends Module {
 	public function getAll($public) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->settings, $public));
+		self::dependencies(isset($public));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -194,14 +190,14 @@ final class Album extends Module {
 		if ($public===false) $return['smartalbums'] = $this->getSmartInfo();
 
 		# Albums query
-		if ($public===false)	$query = Database::prepare($this->database, 'SELECT id, title, public, sysstamp, password FROM ? ' . $this->settings['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS));
-		else					$query = Database::prepare($this->database, 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . $this->settings['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS));
+		if ($public===false)	$query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS));
+		else					$query = Database::prepare(Database::get(), 'SELECT id, title, public, sysstamp, password FROM ? WHERE public = 1 AND visible <> 0 ' . Settings::get()['sortingAlbums'], array(LYCHEE_TABLE_ALBUMS));
 
 		# Execute query
-		$albums = $this->database->query($query);
+		$albums = Database::get()->query($query);
 		if (!$albums) {
-			Log::error($this->database, __METHOD__, __LINE__, 'Could not get all albums (' . $this->database->error . ')');
-			exit('Error: ' . $this->database->error);
+			Log::error(__METHOD__, __LINE__, 'Could not get all albums (' . Database::get()->error . ')');
+			exit('Error: ' . Database::get()->error);
 		}
 
 		# For each album
@@ -215,8 +211,8 @@ final class Album extends Module {
 				($public===false)) {
 
 					# Execute query
-					$query	= Database::prepare($this->database, "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr($this->settings['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id']));
-					$thumbs	= $this->database->query($query);
+					$query	= Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' ORDER BY star DESC, " . substr(Settings::get()['sortingPhotos'], 9) . " LIMIT 3", array(LYCHEE_TABLE_PHOTOS, $album['id']));
+					$thumbs	= Database::get()->query($query);
 
 					# For each thumb
 					$k = 0;
@@ -244,9 +240,6 @@ final class Album extends Module {
 
 	private function getSmartInfo() {
 
-		# Check dependencies
-		self::dependencies(isset($this->database, $this->settings));
-
 		# Initialize return var
 		$return = array(
 			'unsorted'	=> null,
@@ -259,8 +252,8 @@ final class Album extends Module {
 		# Unsorted
 		###
 
-		$query		= Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE album = 0 ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
-		$unsorted	= $this->database->query($query);
+		$query		= Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE album = 0 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+		$unsorted	= Database::get()->query($query);
 		$i			= 0;
 
 		$return['unsorted'] = array(
@@ -279,8 +272,8 @@ final class Album extends Module {
 		# Starred
 		###
 
-		$query		= Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE star = 1 ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
-		$starred	= $this->database->query($query);
+		$query		= Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE star = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+		$starred	= Database::get()->query($query);
 		$i			= 0;
 
 		$return['starred'] = array(
@@ -299,8 +292,8 @@ final class Album extends Module {
 		# Public
 		###
 
-		$query		= Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE public = 1 ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
-		$public		= $this->database->query($query);
+		$query		= Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE public = 1 ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+		$public		= Database::get()->query($query);
 		$i			= 0;
 
 		$return['public'] = array(
@@ -319,8 +312,8 @@ final class Album extends Module {
 		# Recent
 		###
 
-		$query		= Database::prepare($this->database, 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . $this->settings['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
-		$recent		= $this->database->query($query);
+		$query		= Database::prepare(Database::get(), 'SELECT thumbUrl FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) ' . Settings::get()['sortingPhotos'], array(LYCHEE_TABLE_PHOTOS));
+		$recent		= Database::get()->query($query);
 		$i			= 0;
 
 		$return['recent'] = array(
@@ -343,7 +336,7 @@ final class Album extends Module {
 	public function getArchive() {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -357,31 +350,31 @@ final class Album extends Module {
 		# Photos query
 		switch($this->albumIDs) {
 			case 's':
-				$photos		= Database::prepare($this->database, 'SELECT title, url FROM ? WHERE public = 1', array(LYCHEE_TABLE_PHOTOS));
+				$photos		= Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE public = 1', array(LYCHEE_TABLE_PHOTOS));
 				$zipTitle	= 'Public';
 				break;
 			case 'f':
-				$photos		= Database::prepare($this->database, 'SELECT title, url FROM ? WHERE star = 1', array(LYCHEE_TABLE_PHOTOS));
+				$photos		= Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE star = 1', array(LYCHEE_TABLE_PHOTOS));
 				$zipTitle	= 'Starred';
 				break;
 			case 'r':
-				$photos		= Database::prepare($this->database, 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS));
+				$photos		= Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS));
 				$zipTitle	= 'Recent';
 				break;
 			default:
-				$photos		= Database::prepare($this->database, "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
+				$photos		= Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
 				$zipTitle	= 'Unsorted';
 		}
 
 		# Get title from database when album is not a SmartAlbum
 		if ($this->albumIDs!=0&&is_numeric($this->albumIDs)) {
 
-			$query = Database::prepare($this->database, "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
-			$album = $this->database->query($query);
+			$query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+			$album = Database::get()->query($query);
 
 			# Error in database query
 			if (!$album) {
-				Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+				Log::error(__METHOD__, __LINE__, Database::get()->error);
 				return false;
 			}
 
@@ -390,7 +383,7 @@ final class Album extends Module {
 
 			# Photo not found
 			if ($album===null) {
-				Log::error($this->database, __METHOD__, __LINE__, 'Album not found. Cannot start download.');
+				Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.');
 				return false;
 			}
 
@@ -407,16 +400,16 @@ final class Album extends Module {
 		# Create zip
 		$zip = new ZipArchive();
 		if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {
-			Log::error($this->database, __METHOD__, __LINE__, 'Could not create ZipArchive');
+			Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive');
 			return false;
 		}
 
 		# Execute query
-		$photos = $this->database->query($photos);
+		$photos = Database::get()->query($photos);
 
 		# Check if album empty
 		if ($photos->num_rows==0) {
-			Log::error($this->database, __METHOD__, __LINE__, 'Could not create ZipArchive without images');
+			Log::error(__METHOD__, __LINE__, 'Could not create ZipArchive without images');
 			return false;
 		}
 
@@ -483,20 +476,20 @@ final class Album extends Module {
 	public function setTitle($title = 'Untitled') {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Execute query
-		$query	= Database::prepare($this->database, "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs));
-		$result = $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $title, $this->albumIDs));
+		$result = Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -506,20 +499,20 @@ final class Album extends Module {
 	public function setDescription($description = '') {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Execute query
-		$query	= Database::prepare($this->database, "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $description, $this->albumIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -529,7 +522,7 @@ final class Album extends Module {
 	public function getPublic() {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -537,8 +530,8 @@ final class Album extends Module {
 		if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f') return false;
 
 		# Execute query
-		$query	= Database::prepare($this->database, "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
-		$albums	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+		$albums	= Database::get()->query($query);
 		$album	= $albums->fetch_object();
 
 		# Call plugins
@@ -552,7 +545,7 @@ final class Album extends Module {
 	public function getDownloadable() {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -560,8 +553,8 @@ final class Album extends Module {
 		if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f'||$this->albumIDs==='r') return false;
 
 		# Execute query
-		$query	= Database::prepare($this->database, "SELECT downloadable FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
-		$albums	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT downloadable FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+		$albums	= Database::get()->query($query);
 		$album	= $albums->fetch_object();
 
 		# Call plugins
@@ -575,7 +568,7 @@ final class Album extends Module {
 	public function setPublic($public, $password, $visible, $downloadable) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -586,19 +579,19 @@ final class Album extends Module {
 		$downloadable	= ($downloadable==='1' ? 1 : 0);
 
 		# Set public
-		$query	= Database::prepare($this->database, "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET public = '?', visible = '?', downloadable = '?', password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $public, $visible, $downloadable, $this->albumIDs));
+		$result	= Database::get()->query($query);
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 
 		# Reset permissions for photos
 		if ($public===1) {
-			$query	= Database::prepare($this->database, "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
-			$result	= $this->database->query($query);
+			$query	= Database::prepare(Database::get(), "UPDATE ? SET public = 0 WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
+			$result	= Database::get()->query($query);
 			if (!$result) {
-				Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+				Log::error(__METHOD__, __LINE__, Database::get()->error);
 				return false;
 			}
 		}
@@ -616,7 +609,7 @@ final class Album extends Module {
 	private function setPassword($password) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -629,23 +622,23 @@ final class Album extends Module {
 			# Set hashed password
 			# Do not prepare $password because it is hashed and save
 			# Preparing (escaping) the password would destroy the hash
-			$query	= Database::prepare($this->database, "UPDATE ? SET password = '$password' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+			$query	= Database::prepare(Database::get(), "UPDATE ? SET password = '$password' WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
 
 		} else {
 
 			# Unset password
-			$query	= Database::prepare($this->database, "UPDATE ? SET password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+			$query	= Database::prepare(Database::get(), "UPDATE ? SET password = NULL WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
 
 		}
 
 		# Execute query
-		$result	= $this->database->query($query);
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -655,14 +648,14 @@ final class Album extends Module {
 	public function checkPassword($password) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Execute query
-		$query	= Database::prepare($this->database, "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
-		$albums	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT password FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+		$albums	= Database::get()->query($query);
 		$album	= $albums->fetch_object();
 
 		# Call plugins
@@ -677,7 +670,7 @@ final class Album extends Module {
 	public function merge() {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -689,11 +682,11 @@ final class Album extends Module {
 		$albumID = array_splice($albumIDs, 0, 1);
 		$albumID = $albumID[0];
 
-		$query	= Database::prepare($this->database, "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs));
+		$result	= Database::get()->query($query);
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 
@@ -701,14 +694,14 @@ final class Album extends Module {
 		# Convert to string
 		$filteredIDs = implode(',', $albumIDs);
 
-		$query	= Database::prepare($this->database, "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $filteredIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $filteredIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -718,7 +711,7 @@ final class Album extends Module {
 	public function delete() {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->albumIDs));
+		self::dependencies(isset($this->albumIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -727,27 +720,27 @@ final class Album extends Module {
 		$error = false;
 
 		# Execute query
-		$query	= Database::prepare($this->database, "SELECT id FROM ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
-		$photos = $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT id FROM ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
+		$photos = Database::get()->query($query);
 
 		# For each album delete photo
 		while ($row = $photos->fetch_object()) {
 
-			$photo = new Photo($this->database, $this->plugins, null, $row->id);
+			$photo = new Photo($row->id);
 			if (!$photo->delete($row->id)) $error = true;
 
 		}
 
 		# Delete albums
-		$query	= Database::prepare($this->database, "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "DELETE FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if ($error) return false;
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;

+ 79 - 0
php/modules/Config.php

@@ -0,0 +1,79 @@
+<?php
+
+###
+# @name			Database Module
+# @copyright	2015 by Tobias Reich
+###
+
+if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
+
+final class Config extends Module {
+
+	public static function create($host, $user, $password, $name = 'lychee', $prefix = '') {
+
+		# Open a new connection to the MySQL server
+		$connection = Database::connect($host, $user, $password);
+
+		# Check if the connection was successful
+		if ($connection===false) return 'Warning: Connection failed!';
+
+		# Check if user can create the database before saving the configuration
+		if (!Database::createDatabase($connection, $name)) return 'Warning: Creation failed!';
+
+		# Escape data
+		$host		= mysqli_real_escape_string($connection, $host);
+		$user		= mysqli_real_escape_string($connection, $user);
+		$password	= mysqli_real_escape_string($connection, $password);
+		$name		= mysqli_real_escape_string($connection, $name);
+		$prefix		= mysqli_real_escape_string($connection, $prefix);
+
+		# Save config.php
+$config = "<?php
+
+###
+# @name			Configuration
+# @author		Tobias Reich
+# @copyright	2015 Tobias Reich
+###
+
+if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
+
+# Database configuration
+\$dbHost = '$host'; # Host of the database
+\$dbUser = '$user'; # Username of the database
+\$dbPassword = '$password'; # Password of the database
+\$dbName = '$name'; # Database name
+\$dbTablePrefix = '$prefix'; # Table prefix
+
+?>";
+
+		# Save file
+		if (file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!';
+
+		return true;
+
+	}
+
+	public static function exists() {
+
+		return file_exists(LYCHEE_CONFIG_FILE);
+
+	}
+
+	public static function get() {
+
+		require(LYCHEE_CONFIG_FILE);
+
+		return(array(
+			'host'		=> $dbHost,
+			'user'		=> $dbUser,
+			'password'	=> $dbPassword,
+			'name'		=> $dbName,
+			'prefix'	=> $dbTablePrefix
+		));
+
+	}
+
+}
+
+?>

+ 121 - 114
php/modules/Database.php

@@ -9,6 +9,9 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Database extends Module {
 
+	private $connection = null;
+	private static $instance = null;
+
 	private static $versions = array(
 		'020700', #2.7.0
 		'030000', #3.0.0
@@ -16,136 +19,115 @@ final class Database extends Module {
 		'030003' #3.0.3
 	);
 
-	public static function connect($host = 'localhost', $user, $password, $name = 'lychee') {
-
-		# Check dependencies
-		Module::dependencies(isset($host, $user, $password, $name));
-
-		$database = new mysqli($host, $user, $password);
+	public static function get() {
 
-		# Check connection
-		if ($database->connect_errno) exit('Error: ' . $database->connect_error);
+		if (!self::$instance) {
 
-		# Avoid sql injection on older MySQL versions by using GBK
-		if ($database->server_version<50500) @$database->set_charset('GBK');
-		else @$database->set_charset('utf8');
+			$credentials = Config::get();
 
-		# Set unicode
-		$database->query('SET NAMES utf8;');
+			self::$instance = new self(
+				$credentials['host'],
+				$credentials['user'],
+				$credentials['password'],
+				$credentials['name'],
+				$credentials['prefix']
+			);
 
-		# Create database
-		if (!self::createDatabase($database, $name)) exit('Error: Could not create database!');
-
-		# Create tables
-		if (!self::createTables($database)) exit('Error: Could not create tables!');
-
-		# Update database
-		if (!self::update($database, $name)) exit('Error: Could not update database and tables!');
+		}
 
-		return $database;
+		return self::$instance->connection;
 
 	}
 
-	private static function update($database, $dbName) {
+	private function __construct($host, $user, $password, $name = 'lychee', $dbTablePrefix) {
 
 		# Check dependencies
-		Module::dependencies(isset($database, $dbName));
+		Module::dependencies(isset($host, $user, $password, $name));
 
-		# Get current version
-		$query		= self::prepare($database, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS));
-		$results	= $database->query($query);
-		$current	= $results->fetch_object()->value;
+		# Define the table prefix
+		defineTablePrefix($dbTablePrefix);
 
-		# For each update
-		foreach (self::$versions as $version) {
+		# Open a new connection to the MySQL server
+		$connection = self::connect($host, $user, $password);
 
-			# Only update when newer version available
-			if ($version<=$current) continue;
+		# Check if the connection was successful
+		if ($connection===false) exit('Error: ' . $connection->connect_error);
 
-			# Load update
-			include(__DIR__ . '/../database/update_' . $update . '.php');
+		if (!self::setCharset($connection)) exit('Error: Could not set database charset!');
 
-		}
+		# Create database
+		if (!self::createDatabase($connection, $name)) exit('Error: Could not create database!');
 
-		return true;
+		# Create tables
+		if (!self::createTables($connection)) exit('Error: Could not create tables!');
 
-	}
+		# Update database
+		if (!self::update($connection, $name)) exit('Error: Could not update database and tables!');
 
-	public static function createConfig($host = 'localhost', $user, $password, $name = 'lychee', $prefix = '') {
+		$this->connection = $connection;
 
-		# Check dependencies
-		Module::dependencies(isset($host, $user, $password, $name));
+	}
 
-		$database = new mysqli($host, $user, $password);
+	private function __clone() {
 
-		if ($database->connect_errno) return 'Warning: Connection failed!';
+		# Magic method clone is empty to prevent duplication of connection
 
-		# Check if user can create the database before saving the configuration
-		if (!self::createDatabase($database, $name)) return 'Warning: Creation failed!';
+	}
 
-		# Escape data
-		$host		= mysqli_real_escape_string($database, $host);
-		$user		= mysqli_real_escape_string($database, $user);
-		$password	= mysqli_real_escape_string($database, $password);
-		$name		= mysqli_real_escape_string($database, $name);
-		$prefix		= mysqli_real_escape_string($database, $prefix);
+	public static function connect($host = 'localhost', $user, $password) {
 
-		# Save config.php
-$config = "<?php
+		# Open a new connection to the MySQL server
+		$connection = new mysqli($host, $user, $password);
 
-###
-# @name			Configuration
-# @author		Tobias Reich
-# @copyright	2015 Tobias Reich
-###
+		# Check if the connection was successful
+		if ($connection->connect_errno) return false;
 
-if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
+		return $connection;
 
-# Database configuration
-\$dbHost = '$host'; # Host of the database
-\$dbUser = '$user'; # Username of the database
-\$dbPassword = '$password'; # Password of the database
-\$dbName = '$name'; # Database name
-\$dbTablePrefix = '$prefix'; # Table prefix
+	}
+
+	private static function setCharset($connection) {
 
-?>";
+		# Avoid sql injection on older MySQL versions by using GBK
+		if ($connection->server_version<50500) @$connection->set_charset('GBK');
+		else @$connection->set_charset('utf8');
 
-		# Save file
-		if (file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!';
+		# Set unicode
+		$connection->query('SET NAMES utf8;');
 
 		return true;
 
 	}
 
-	private static function createDatabase($database, $name = 'lychee') {
+	public static function createDatabase($connection, $name = 'lychee') {
 
 		# Check dependencies
-		Module::dependencies(isset($database, $name));
+		Module::dependencies(isset($connection, $name));
 
 		# Check if database exists
-		if ($database->select_db($name)) return true;
+		if ($connection->select_db($name)) return true;
 
 		# Create database
-		$query	= self::prepare($database, 'CREATE DATABASE IF NOT EXISTS ?', array($name));
-		$result = $database->query($query);
+		$query	= self::prepare($connection, 'CREATE DATABASE IF NOT EXISTS ?', array($name));
+		$result = $connection->query($query);
 
-		if (!$database->select_db($name)||!$result) return false;
+		if (!$connection->select_db($name)) return false;
 		return true;
 
 	}
 
-	private static function createTables($database) {
+	private static function createTables($connection) {
 
 		# Check dependencies
-		Module::dependencies(isset($database));
+		Module::dependencies(isset($connection));
 
 		# Check if tables exist
-		$query = self::prepare($database, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG));
-		if ($database->query($query)) return true;
+		$query = self::prepare($connection, 'SELECT * FROM ?, ?, ?, ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, LYCHEE_TABLE_SETTINGS, LYCHEE_TABLE_LOG));
+		if ($connection->query($query)) return true;
 
 		# Create log
-		$exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG));
-		if (!$database->query($exist)) {
+		$exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_LOG));
+		if (!$connection->query($exist)) {
 
 			# Read file
 			$file	= __DIR__ . '/../database/log_table.sql';
@@ -154,28 +136,28 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 			if (!isset($query)||$query===false) return false;
 
 			# Create table
-			$query = self::prepare($database, $query, array(LYCHEE_TABLE_LOG));
-			if (!$database->query($query)) return false;
+			$query = self::prepare($connection, $query, array(LYCHEE_TABLE_LOG));
+			if (!$connection->query($query)) return false;
 
 		}
 
 		# Create settings
-		$exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS));
-		if (!$database->query($exist)) {
+		$exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_SETTINGS));
+		if (!$connection->query($exist)) {
 
 			# Read file
 			$file	= __DIR__ . '/../database/settings_table.sql';
 			$query	= @file_get_contents($file);
 
 			if (!isset($query)||$query===false) {
-				Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_settings');
+				Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_settings');
 				return false;
 			}
 
 			# Create table
-			$query = self::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS));
-			if (!$database->query($query)) {
-				Log::error($database, __METHOD__, __LINE__, $database->error);
+			$query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS));
+			if (!$connection->query($query)) {
+				Log::error(__METHOD__, __LINE__, $connection->error);
 				return false;
 			}
 
@@ -184,66 +166,66 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 			$query	= @file_get_contents($file);
 
 			if (!isset($query)||$query===false) {
-				Log::error($database, __METHOD__, __LINE__, 'Could not load content-query for lychee_settings');
+				Log::error(__METHOD__, __LINE__, 'Could not load content-query for lychee_settings');
 				return false;
 			}
 
 			# Add content
-			$query = self::prepare($database, $query, array(LYCHEE_TABLE_SETTINGS));
-			if (!$database->query($query)) {
-				Log::error($database, __METHOD__, __LINE__, $database->error);
+			$query = self::prepare($connection, $query, array(LYCHEE_TABLE_SETTINGS));
+			if (!$connection->query($query)) {
+				Log::error(__METHOD__, __LINE__, $connection->error);
 				return false;
 			}
 
 			# Generate identifier
 			$identifier	= md5(microtime(true));
-			$query		= self::prepare($database, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier));
-			if (!$database->query($query)) {
-				Log::error($database, __METHOD__, __LINE__, $database->error);
+			$query		= self::prepare($connection, "UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1", array(LYCHEE_TABLE_SETTINGS, $identifier));
+			if (!$connection->query($query)) {
+				Log::error(__METHOD__, __LINE__, $connection->error);
 				return false;
 			}
 
 		}
 
 		# Create albums
-		$exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS));
-		if (!$database->query($exist)) {
+		$exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_ALBUMS));
+		if (!$connection->query($exist)) {
 
 			# Read file
 			$file	= __DIR__ . '/../database/albums_table.sql';
 			$query	= @file_get_contents($file);
 
 			if (!isset($query)||$query===false) {
-				Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_albums');
+				Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_albums');
 				return false;
 			}
 
 			# Create table
-			$query = self::prepare($database, $query, array(LYCHEE_TABLE_ALBUMS));
-			if (!$database->query($query)) {
-				Log::error($database, __METHOD__, __LINE__, $database->error);
+			$query = self::prepare($connection, $query, array(LYCHEE_TABLE_ALBUMS));
+			if (!$connection->query($query)) {
+				Log::error(__METHOD__, __LINE__, $connection->error);
 				return false;
 			}
 
 		}
 
 		# Create photos
-		$exist = self::prepare($database, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS));
-		if (!$database->query($exist)) {
+		$exist = self::prepare($connection, 'SELECT * FROM ? LIMIT 0', array(LYCHEE_TABLE_PHOTOS));
+		if (!$connection->query($exist)) {
 
 			# Read file
 			$file	= __DIR__ . '/../database/photos_table.sql';
 			$query	= @file_get_contents($file);
 
 			if (!isset($query)||$query===false) {
-				Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_photos');
+				Log::error(__METHOD__, __LINE__, 'Could not load query for lychee_photos');
 				return false;
 			}
 
 			# Create table
-			$query = self::prepare($database, $query, array(LYCHEE_TABLE_PHOTOS));
-			if (!$database->query($query)) {
-				Log::error($database, __METHOD__, __LINE__, $database->error);
+			$query = self::prepare($connection, $query, array(LYCHEE_TABLE_PHOTOS));
+			if (!$connection->query($query)) {
+				Log::error(__METHOD__, __LINE__, $connection->error);
 				return false;
 			}
 
@@ -253,21 +235,46 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 	}
 
-	public static function setVersion($database, $version) {
+	private static function update($connection, $dbName) {
+
+		# Check dependencies
+		Module::dependencies(isset($connection));
+
+		# Get current version
+		$query		= self::prepare($connection, "SELECT * FROM ? WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS));
+		$results	= $connection->query($query);
+		$current	= $results->fetch_object()->value;
+
+		# For each update
+		foreach (self::$versions as $version) {
+
+			# Only update when newer version available
+			if ($version<=$current) continue;
+
+			# Load update
+			include(__DIR__ . '/../database/update_' . $version . '.php');
+
+		}
+
+		return true;
+
+	}
+
+	public static function setVersion($connection, $version) {
 
-		$query	= self::prepare($database, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version));
-		$result = $database->query($query);
+		$query	= self::prepare($connection, "UPDATE ? SET value = '?' WHERE `key` = 'version'", array(LYCHEE_TABLE_SETTINGS, $version));
+		$result = $connection->query($query);
 		if (!$result) {
-			Log::error($database, __METHOD__, __LINE__, 'Could not update database (' . $database->error . ')');
+			Log::error(__METHOD__, __LINE__, 'Could not update database (' . $connection->error . ')');
 			return false;
 		}
 
 	}
 
-	public static function prepare($database, $query, $data) {
+	public static function prepare($connection, $query, $data) {
 
 		# Check dependencies
-		Module::dependencies(isset($database, $query, $data));
+		Module::dependencies(isset($connection, $query, $data));
 
 		# Count the number of placeholders and compare it with the number of arguments
 		# If it doesn't match, calculate the difference and skip this number of placeholders before starting the replacement
@@ -280,12 +287,12 @@ if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 			'data'			=> count($data)
 		);
 
-		if (($num['data']-$num['placeholder'])<0) Log::notice($database, __METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.');
+		if (($num['data']-$num['placeholder'])<0) Log::notice(__METHOD__, __LINE__, 'Could not completely prepare query. Query has more placeholders than values.');
 
 		foreach ($data as $value) {
 
 			# Escape
-			$value = mysqli_real_escape_string($database, $value);
+			$value = mysqli_real_escape_string($connection, $value);
 
 			# Recalculate number of placeholders
 			$num['placeholder'] = substr_count($query, '?');

+ 14 - 31
php/modules/Import.php

@@ -9,31 +9,17 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Import extends Module {
 
-	private $database	= null;
-	private $settings	= null;
-
-	public function __construct($database, $plugins, $settings) {
-
-		# Init vars
-		$this->database	= $database;
-		$this->plugins	= $plugins;
-		$this->settings	= $settings;
-
-		return true;
-
-	}
-
 	private function photo($path, $albumID = 0, $description = '', $tags = '') {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->plugins, $this->settings, $path));
+		self::dependencies(isset($path));
 
 		# No need to validate photo type and extension in this function.
 		# $photo->add will take care of it.
 
 		$info	= getimagesize($path);
 		$size	= filesize($path);
-		$photo	= new Photo($this->database, $this->plugins, $this->settings, null);
+		$photo	= new Photo(null);
 
 		$nameFile					= array(array());
 		$nameFile[0]['name']		= $path;
@@ -51,7 +37,7 @@ final class Import extends Module {
 	public function url($urls, $albumID = 0) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $urls));
+		self::dependencies(isset($urls));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -71,7 +57,7 @@ final class Import extends Module {
 			$extension = getExtension($url);
 			if (!in_array(strtolower($extension), Photo::$validExtensions, true)) {
 				$error = true;
-				Log::error($this->database, __METHOD__, __LINE__, 'Photo format not supported (' . $url . ')');
+				Log::error(__METHOD__, __LINE__, 'Photo format not supported (' . $url . ')');
 				continue;
 			}
 
@@ -79,7 +65,7 @@ final class Import extends Module {
 			$type = @exif_imagetype($url);
 			if (!in_array($type, Photo::$validTypes, true)) {
 				$error = true;
-				Log::error($this->database, __METHOD__, __LINE__, 'Photo type not supported (' . $url . ')');
+				Log::error(__METHOD__, __LINE__, 'Photo type not supported (' . $url . ')');
 				continue;
 			}
 
@@ -89,14 +75,14 @@ final class Import extends Module {
 
 			if (@copy($url, $tmp_name)===false) {
 				$error = true;
-				Log::error($this->database, __METHOD__, __LINE__, 'Could not copy file (' . $tmp_name . ') to temp-folder (' . $tmp_name . ')');
+				Log::error(__METHOD__, __LINE__, 'Could not copy file (' . $tmp_name . ') to temp-folder (' . $tmp_name . ')');
 				continue;
 			}
 
 			# Import photo
 			if (!$this->photo($tmp_name, $albumID)) {
 				$error = true;
-				Log::error($this->database, __METHOD__, __LINE__, 'Could not import file: ' . $tmp_name);
+				Log::error(__METHOD__, __LINE__, 'Could not import file: ' . $tmp_name);
 				continue;
 			}
 
@@ -112,15 +98,12 @@ final class Import extends Module {
 
 	public function server($path, $albumID = 0) {
 
-		# Check dependencies
-		self::dependencies(isset($this->database, $this->plugins, $this->settings));
-
 		# Parse path
 		if (!isset($path))				$path = LYCHEE_UPLOADS_IMPORT;
 		if (substr($path, -1)==='/')	$path = substr($path, 0, -1);
 
 		if (is_dir($path)===false) {
-			Log::error($this->database, __METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')');
+			Log::error(__METHOD__, __LINE__, 'Given path is not a directory (' . $path . ')');
 			return 'Error: Given path is not a directory!';
 		}
 
@@ -128,7 +111,7 @@ final class Import extends Module {
 		if ($path===LYCHEE_UPLOADS_BIG||($path . '/')===LYCHEE_UPLOADS_BIG||
 			$path===LYCHEE_UPLOADS_MEDIUM||($path . '/')===LYCHEE_UPLOADS_MEDIUM||
 			$path===LYCHEE_UPLOADS_THUMB||($path . '/')===LYCHEE_UPLOADS_THUMB) {
-				Log::error($this->database, __METHOD__, __LINE__, 'The given path is a reserved path of Lychee (' . $path . ')');
+				Log::error(__METHOD__, __LINE__, 'The given path is a reserved path of Lychee (' . $path . ')');
 				return 'Error: Given path is a reserved path of Lychee!';
 		}
 
@@ -150,7 +133,7 @@ final class Import extends Module {
 			# the file may still be unreadable by the user
 			if (!is_readable($file)) {
 				$error = true;
-				Log::error($this->database, __METHOD__, __LINE__, 'Could not read file or directory: ' . $file);
+				Log::error(__METHOD__, __LINE__, 'Could not read file or directory: ' . $file);
 				continue;
 			}
 
@@ -162,7 +145,7 @@ final class Import extends Module {
 
 				if (!$this->photo($file, $albumID)) {
 					$error = true;
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not import file: ' . $file);
+					Log::error(__METHOD__, __LINE__, 'Could not import file: ' . $file);
 					continue;
 				}
 
@@ -170,13 +153,13 @@ final class Import extends Module {
 
 				# Folder
 
-				$album				= new Album($this->database, $this->plugins, $this->settings, null);
+				$album				= new Album(null);
 				$newAlbumID			= $album->add('[Import] ' . basename($file));
 				$contains['albums']	= true;
 
 				if ($newAlbumID===false) {
 					$error = true;
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not create album in Lychee (' . $newAlbumID . ')');
+					Log::error(__METHOD__, __LINE__, 'Could not create album in Lychee (' . $newAlbumID . ')');
 					continue;
 				}
 
@@ -184,7 +167,7 @@ final class Import extends Module {
 
 				if ($import!==true&&$import!=='Notice: Import only contains albums!') {
 					$error = true;
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not import folder. Function returned warning.');
+					Log::error(__METHOD__, __LINE__, 'Could not import folder. Function returned warning.');
 					continue;
 				}
 

+ 10 - 10
php/modules/Log.php

@@ -9,35 +9,35 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Log extends Module {
 
-	public static function notice($database, $function, $line, $text = '') {
+	public static function notice($function, $line, $text = '') {
 
-		return Log::text($database, 'notice', $function, $line, $text);
+		return Log::text('notice', $function, $line, $text);
 
 	}
 
-	public static function warning($database, $function, $line, $text = '') {
+	public static function warning($function, $line, $text = '') {
 
-		return Log::text($database, 'warning', $function, $line, $text);
+		return Log::text('warning', $function, $line, $text);
 
 	}
 
-	public static function error($database, $function, $line, $text = '') {
+	public static function error($function, $line, $text = '') {
 
-		return Log::text($database, 'error', $function, $line, $text);
+		return Log::text('error', $function, $line, $text);
 
 	}
 
-	public static function text($database, $type, $function, $line, $text = '') {
+	private static function text($type, $function, $line, $text = '') {
 
 		# Check dependencies
-		Module::dependencies(isset($database, $type, $function, $line, $text));
+		Module::dependencies(isset($type, $function, $line, $text));
 
 		# Get time
 		$sysstamp = time();
 
 		# Save in database
-		$query	= Database::prepare($database, "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text));
-		$result	= $database->query($query);
+		$query	= Database::prepare(Database::get(), "INSERT INTO ? (time, type, function, line, text) VALUES ('?', '?', '?', '?', '?')", array(LYCHEE_TABLE_LOG, $sysstamp, $type, $function, $line, $text));
+		$result	= Database::get()->query($query);
 
 		if (!$result) return false;
 		return true;

+ 2 - 4
php/modules/Module.php

@@ -9,17 +9,15 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 abstract class Module {
 
-	protected $plugins = null;
-
 	protected function plugins($name, $location, $args) {
 
-		if (!isset($this->plugins, $name, $location, $args)) return false;
+		self::dependencies(isset($name, $location, $args));
 
 		# Parse
 		$location = ($location===0 ? 'before' : 'after');
 
 		# Call plugins
-		$this->plugins->activate($name . ":" . $location, $args);
+		Plugins::get()->activate($name . ":" . $location, $args);
 
 		return true;
 

+ 100 - 105
php/modules/Photo.php

@@ -9,9 +9,7 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Photo extends Module {
 
-	private $database	= null;
-	private $settings	= null;
-	private $photoIDs	= null;
+	private $photoIDs = null;
 
 	public static $validTypes = array(
 		IMAGETYPE_JPEG,
@@ -26,12 +24,9 @@ final class Photo extends Module {
 		'.gif'
 	);
 
-	public function __construct($database, $plugins, $settings, $photoIDs) {
+	public function __construct($photoIDs) {
 
 		# Init vars
-		$this->database	= $database;
-		$this->plugins	= $plugins;
-		$this->settings	= $settings;
 		$this->photoIDs	= $photoIDs;
 
 		return true;
@@ -44,13 +39,13 @@ final class Photo extends Module {
 		# e.g. when calling this functions inside an if-condition
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->settings, $files));
+		self::dependencies(isset($files));
 
 		# Check permissions
 		if (hasPermissions(LYCHEE_UPLOADS)===false||
 			hasPermissions(LYCHEE_UPLOADS_BIG)===false||
 			hasPermissions(LYCHEE_UPLOADS_THUMB)===false) {
-				Log::error($this->database, __METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable');
+				Log::error(__METHOD__, __LINE__, 'An upload-folder is missing or not readable and writable');
 				exit('Error: An upload-folder is missing or not readable and writable!');
 		}
 
@@ -91,35 +86,35 @@ final class Photo extends Module {
 
 			# Check if file exceeds the upload_max_filesize directive
 			if ($file['error']===UPLOAD_ERR_INI_SIZE) {
-				Log::error($this->database, __METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini');
+				Log::error(__METHOD__, __LINE__, 'The uploaded file exceeds the upload_max_filesize directive in php.ini');
 				if ($returnOnError===true) return false;
 				exit('Error: The uploaded file exceeds the upload_max_filesize directive in php.ini!');
 			}
 
 			# Check if file was only partially uploaded
 			if ($file['error']===UPLOAD_ERR_PARTIAL) {
-				Log::error($this->database, __METHOD__, __LINE__, 'The uploaded file was only partially uploaded');
+				Log::error(__METHOD__, __LINE__, 'The uploaded file was only partially uploaded');
 				if ($returnOnError===true) return false;
 				exit('Error: The uploaded file was only partially uploaded!');
 			}
 
 			# Check if writing file to disk failed
 			if ($file['error']===UPLOAD_ERR_CANT_WRITE) {
-				Log::error($this->database, __METHOD__, __LINE__, 'Failed to write photo to disk');
+				Log::error(__METHOD__, __LINE__, 'Failed to write photo to disk');
 				if ($returnOnError===true) return false;
 				exit('Error: Failed to write photo to disk!');
 			}
 
 			# Check if a extension stopped the file upload
 			if ($file['error']===UPLOAD_ERR_EXTENSION) {
-				Log::error($this->database, __METHOD__, __LINE__, 'A PHP extension stopped the file upload');
+				Log::error(__METHOD__, __LINE__, 'A PHP extension stopped the file upload');
 				if ($returnOnError===true) return false;
 				exit('Error: A PHP extension stopped the file upload!');
 			}
 
 			# Check if the upload was successful
 			if ($file['error']!==UPLOAD_ERR_OK) {
-				Log::error($this->database, __METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')');
+				Log::error(__METHOD__, __LINE__, 'Upload contains an error (' . $file['error'] . ')');
 				if ($returnOnError===true) return false;
 				exit('Error: Upload failed!');
 			}
@@ -127,7 +122,7 @@ final class Photo extends Module {
 			# Verify extension
 			$extension = getExtension($file['name']);
 			if (!in_array(strtolower($extension), self::$validExtensions, true)) {
-				Log::error($this->database, __METHOD__, __LINE__, 'Photo format not supported');
+				Log::error(__METHOD__, __LINE__, 'Photo format not supported');
 				if ($returnOnError===true) return false;
 				exit('Error: Photo format not supported!');
 			}
@@ -135,7 +130,7 @@ final class Photo extends Module {
 			# Verify image
 			$type = @exif_imagetype($file['tmp_name']);
 			if (!in_array($type, self::$validTypes, true)) {
-				Log::error($this->database, __METHOD__, __LINE__, 'Photo type not supported');
+				Log::error(__METHOD__, __LINE__, 'Photo type not supported');
 				if ($returnOnError===true) return false;
 				exit('Error: Photo type not supported!');
 			}
@@ -152,7 +147,7 @@ final class Photo extends Module {
 			# Calculate checksum
 			$checksum = sha1_file($tmp_name);
 			if ($checksum===false) {
-				Log::error($this->database, __METHOD__, __LINE__, 'Could not calculate checksum for photo');
+				Log::error(__METHOD__, __LINE__, 'Could not calculate checksum for photo');
 				if ($returnOnError===true) return false;
 				exit('Error: Could not calculate checksum for photo!');
 			}
@@ -182,13 +177,13 @@ final class Photo extends Module {
 				# Import if not uploaded via web
 				if (!is_uploaded_file($tmp_name)) {
 					if (!@copy($tmp_name, $path)) {
-						Log::error($this->database, __METHOD__, __LINE__, 'Could not copy photo to uploads');
+						Log::error(__METHOD__, __LINE__, 'Could not copy photo to uploads');
 						if ($returnOnError===true) return false;
 						exit('Error: Could not copy photo to uploads!');
 					} else @unlink($tmp_name);
 				} else {
 					if (!@move_uploaded_file($tmp_name, $path)) {
-						Log::error($this->database, __METHOD__, __LINE__, 'Could not move photo to uploads');
+						Log::error(__METHOD__, __LINE__, 'Could not move photo to uploads');
 						if ($returnOnError===true) return false;
 						exit('Error: Could not move photo to uploads!');
 					}
@@ -198,8 +193,8 @@ final class Photo extends Module {
 
 				# Photo already exists
 				# Check if the user wants to skip duplicates
-				if ($this->settings['skipDuplicates']==='1') {
-					Log::notice($this->database, __METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated');
+				if (Settings::get()['skipDuplicates']==='1') {
+					Log::notice(__METHOD__, __LINE__, 'Skipped upload of existing photo because skipDuplicates is activated');
 					if ($returnOnError===true) return false;
 					exit('Warning: This photo has been skipped because it\'s already in your library.');
 				}
@@ -221,7 +216,7 @@ final class Photo extends Module {
 				if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&$info['orientation']!=='') {
 					$adjustFile = $this->adjustFile($path, $info);
 					if ($adjustFile!==false) $info = $adjustFile;
-					else Log::notice($this->database, __METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')');
+					else Log::notice(__METHOD__, __LINE__, 'Skipped adjustment of photo (' . $info['title'] . ')');
 				}
 
 				# Set original date
@@ -229,7 +224,7 @@ final class Photo extends Module {
 
 				# Create Thumb
 				if (!$this->createThumb($path, $photo_name, $info['type'], $info['width'], $info['height'])) {
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not create thumbnail for photo');
+					Log::error(__METHOD__, __LINE__, 'Could not create thumbnail for photo');
 					if ($returnOnError===true) return false;
 					exit('Error: Could not create thumbnail for photo!');
 				}
@@ -245,11 +240,11 @@ final class Photo extends Module {
 
 			# Save to DB
 			$values	= array(LYCHEE_TABLE_PHOTOS, $id, $info['title'], $photo_name, $description, $tags, $info['type'], $info['width'], $info['height'], $info['size'], $info['iso'], $info['aperture'], $info['make'], $info['model'], $info['shutter'], $info['focal'], $info['takestamp'], $path_thumb, $albumID, $public, $star, $checksum, $medium);
-			$query	= Database::prepare($this->database, "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values);
-			$result = $this->database->query($query);
+			$query	= Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum, medium) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')", $values);
+			$result = Database::get()->query($query);
 
 			if (!$result) {
-				Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+				Log::error(__METHOD__, __LINE__, Database::get()->error);
 				if ($returnOnError===true) return false;
 				exit('Error: Could not save photo in database!');
 			}
@@ -266,16 +261,16 @@ final class Photo extends Module {
 	private function exists($checksum, $photoID = null) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $checksum));
+		self::dependencies(isset($checksum));
 
 		# Exclude $photoID from select when $photoID is set
-		if (isset($photoID)) $query = Database::prepare($this->database, "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID));
-		else $query = Database::prepare($this->database, "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum));
+		if (isset($photoID)) $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' AND id <> '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum, $photoID));
+		else $query = Database::prepare(Database::get(), "SELECT id, url, thumbUrl, medium FROM ? WHERE checksum = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $checksum));
 
-		$result	= $this->database->query($query);
+		$result	= Database::get()->query($query);
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, 'Could not check for existing photos with the same checksum');
+			Log::error(__METHOD__, __LINE__, 'Could not check for existing photos with the same checksum');
 			return false;
 		}
 
@@ -301,7 +296,7 @@ final class Photo extends Module {
 	private function createThumb($url, $filename, $type, $width, $height) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->settings, $url, $filename, $type, $width, $height));
+		self::dependencies(isset($url, $filename, $type, $width, $height));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -315,12 +310,12 @@ final class Photo extends Module {
 		$newUrl2x	= LYCHEE_UPLOADS_THUMB . $photoName[0] . '@2x.jpeg';
 
 		# Create thumbnails with Imagick
-		if(extension_loaded('imagick')&&$this->settings['imagick']==='1') {
+		if(extension_loaded('imagick')&&Settings::get()['imagick']==='1') {
 
 			# Read image
 			$thumb = new Imagick();
 			$thumb->readImage($url);
-			$thumb->setImageCompressionQuality($this->settings['thumbQuality']);
+			$thumb->setImageCompressionQuality(Settings::get()['thumbQuality']);
 			$thumb->setImageFormat('jpeg');
 
 			# Copy image for 2nd thumb version
@@ -360,19 +355,19 @@ final class Photo extends Module {
 				case 'image/jpeg':	$sourceImg = imagecreatefromjpeg($url); break;
 				case 'image/png':	$sourceImg = imagecreatefrompng($url); break;
 				case 'image/gif':	$sourceImg = imagecreatefromgif($url); break;
-				default:			Log::error($this->database, __METHOD__, __LINE__, 'Type of photo is not supported');
+				default:			Log::error(__METHOD__, __LINE__, 'Type of photo is not supported');
 									return false;
 									break;
 			}
 
 			# Create thumb
 			fastimagecopyresampled($thumb, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth, $newHeight, $newSize, $newSize);
-			imagejpeg($thumb, $newUrl, $this->settings['thumbQuality']);
+			imagejpeg($thumb, $newUrl, Settings::get()['thumbQuality']);
 			imagedestroy($thumb);
 
 			# Create retina thumb
 			fastimagecopyresampled($thumb2x, $sourceImg, 0, 0, $startWidth, $startHeight, $newWidth*2, $newHeight*2, $newSize, $newSize);
-			imagejpeg($thumb2x, $newUrl2x, $this->settings['thumbQuality']);
+			imagejpeg($thumb2x, $newUrl2x, Settings::get()['thumbQuality']);
 			imagedestroy($thumb2x);
 
 			# Free memory
@@ -400,7 +395,7 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->settings, $url, $filename, $width, $height));
+		self::dependencies(isset($url, $filename, $width, $height));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -418,7 +413,7 @@ final class Photo extends Module {
 		if (hasPermissions(LYCHEE_UPLOADS_MEDIUM)===false) {
 
 			# Permissions are missing
-			Log::notice($this->database, __METHOD__, __LINE__, 'Skipped creation of medium-photo, because uploads/medium/ is missing or not readable and writable.');
+			Log::notice(__METHOD__, __LINE__, 'Skipped creation of medium-photo, because uploads/medium/ is missing or not readable and writable.');
 			$error = true;
 
 		}
@@ -428,8 +423,8 @@ final class Photo extends Module {
 		# Is Imagick installed and activated?
 		if (($error===false)&&
 			($width>$newWidth||$height>$newHeight)&&
-			($this->settings['medium']==='1')&&
-			(extension_loaded('imagick')&&$this->settings['imagick']==='1')) {
+			(Settings::get()['medium']==='1')&&
+			(extension_loaded('imagick')&&Settings::get()['imagick']==='1')) {
 
 			$newUrl = LYCHEE_UPLOADS_MEDIUM . $filename;
 
@@ -443,7 +438,7 @@ final class Photo extends Module {
 			# Save image
 			try { $medium->writeImage($newUrl); }
 			catch (ImagickException $err) {
-				Log::notice($this->database, __METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage());
+				Log::notice(__METHOD__, __LINE__, 'Could not save medium-photo: ' . $err->getMessage());
 				$error = true;
 			}
 
@@ -485,7 +480,7 @@ final class Photo extends Module {
 
 		$swapSize = false;
 
-		if (extension_loaded('imagick')&&$this->settings['imagick']==='1') {
+		if (extension_loaded('imagick')&&Settings::get()['imagick']==='1') {
 
 			switch ($info['orientation']) {
 
@@ -655,14 +650,14 @@ final class Photo extends Module {
 		# (array) $photo
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Get photo
-		$query	= Database::prepare($this->database, "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
-		$photos	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
+		$photos	= Database::get()->query($query);
 		$photo	= $photos->fetch_assoc();
 
 		# Parse photo
@@ -684,8 +679,8 @@ final class Photo extends Module {
 			if ($photo['album']!=='0') {
 
 				# Get album
-				$query	= Database::prepare($this->database, "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album']));
-				$albums	= $this->database->query($query);
+				$query	= Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $photo['album']));
+				$albums	= Database::get()->query($query);
 				$album	= $albums->fetch_assoc();
 
 				# Parse album
@@ -714,7 +709,7 @@ final class Photo extends Module {
 		# (array) $return
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $url));
+		self::dependencies(isset($url));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -821,32 +816,32 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Get photo
-		$query	= Database::prepare($this->database, "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
-		$photos	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
+		$photos	= Database::get()->query($query);
 		$photo	= $photos->fetch_object();
 
 		# Error in database query
 		if (!$photos) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 
 		# Photo not found
 		if ($photo===null) {
-			Log::error($this->database, __METHOD__, __LINE__, 'Album not found. Cannot start download.');
+			Log::error(__METHOD__, __LINE__, 'Album not found. Cannot start download.');
 			return false;
 		}
 
 		# Get extension
 		$extension = getExtension($photo->url);
 		if ($extension===false) {
-			Log::error($this->database, __METHOD__, __LINE__, 'Invalid photo extension');
+			Log::error(__METHOD__, __LINE__, 'Invalid photo extension');
 			return false;
 		}
 
@@ -887,20 +882,20 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Set title
-		$query	= Database::prepare($this->database, "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET title = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $title, $this->photoIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -917,20 +912,20 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Set description
-		$query	= Database::prepare($this->database, "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET description = '?' WHERE id IN ('?')", array(LYCHEE_TABLE_PHOTOS, $description, $this->photoIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -945,7 +940,7 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -954,8 +949,8 @@ final class Photo extends Module {
 		$error	= false;
 
 		# Get photos
-		$query	= Database::prepare($this->database, "SELECT id, star FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
-		$photos	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT id, star FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
+		$photos	= Database::get()->query($query);
 
 		# For each photo
 		while ($photo = $photos->fetch_object()) {
@@ -964,8 +959,8 @@ final class Photo extends Module {
 			$star = ($photo->star==0 ? 1 : 0);
 
 			# Set star
-			$query	= Database::prepare($this->database, "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id));
-			$star	= $this->database->query($query);
+			$query	= Database::prepare(Database::get(), "UPDATE ? SET star = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $star, $photo->id));
+			$star	= Database::get()->query($query);
 			if (!$star) $error = true;
 
 		}
@@ -974,7 +969,7 @@ final class Photo extends Module {
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if ($error===true) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -990,14 +985,14 @@ final class Photo extends Module {
 		# (int) 2 = Photo public or album public and password correct
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Get photo
-		$query	= Database::prepare($this->database, "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
-		$photos	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
+		$photos	= Database::get()->query($query);
 		$photo	= $photos->fetch_object();
 
 		# Check if public
@@ -1009,7 +1004,7 @@ final class Photo extends Module {
 		} else {
 
 			# Check if album public
-			$album	= new Album($this->database, null, null, $photo->album);
+			$album	= new Album($photo->album);
 			$agP	= $album->getPublic();
 			$acP	= $album->checkPassword($password);
 
@@ -1037,28 +1032,28 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Get public
-		$query	= Database::prepare($this->database, "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
-		$photos	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT public FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
+		$photos	= Database::get()->query($query);
 		$photo	= $photos->fetch_object();
 
 		# Invert public
 		$public = ($photo->public==0 ? 1 : 0);
 
 		# Set public
-		$query	= Database::prepare($this->database, "UPDATE ? SET public = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $public, $this->photoIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET public = '?' WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $public, $this->photoIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -1073,20 +1068,20 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Set album
-		$query	= Database::prepare($this->database, "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET album = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->photoIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -1103,7 +1098,7 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
@@ -1113,14 +1108,14 @@ final class Photo extends Module {
 		$tags = preg_replace('/,$|^,|(\ ){0,}$/', '', $tags);
 
 		# Set tags
-		$query	= Database::prepare($this->database, "UPDATE ? SET tags = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $tags, $this->photoIDs));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET tags = '?' WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $tags, $this->photoIDs));
+		$result	= Database::get()->query($query);
 
 		# Call plugins
 		$this->plugins(__METHOD__, 1, func_get_args());
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
@@ -1135,16 +1130,16 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Get photos
-		$query	= Database::prepare($this->database, "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
-		$photos	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT id, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
+		$photos	= Database::get()->query($query);
 		if (!$photos) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 
@@ -1157,10 +1152,10 @@ final class Photo extends Module {
 
 			# Duplicate entry
 			$values		= array(LYCHEE_TABLE_PHOTOS, $id, LYCHEE_TABLE_PHOTOS, $photo->id);
-			$query		= Database::prepare($this->database, "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values);
-			$duplicate	= $this->database->query($query);
+			$query		= Database::prepare(Database::get(), "INSERT INTO ? (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum) SELECT '?' AS id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star, checksum FROM ? WHERE id = '?'", $values);
+			$duplicate	= Database::get()->query($query);
 			if (!$duplicate) {
-				Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+				Log::error(__METHOD__, __LINE__, Database::get()->error);
 				return false;
 			}
 
@@ -1178,16 +1173,16 @@ final class Photo extends Module {
 		# (boolean) false = Failure
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $this->photoIDs));
+		self::dependencies(isset($this->photoIDs));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Get photos
-		$query	= Database::prepare($this->database, "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
-		$photos	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT id, url, thumbUrl, checksum FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs));
+		$photos	= Database::get()->query($query);
 		if (!$photos) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 
@@ -1204,35 +1199,35 @@ final class Photo extends Module {
 
 				# Delete big
 				if (file_exists(LYCHEE_UPLOADS_BIG . $photo->url)&&!unlink(LYCHEE_UPLOADS_BIG . $photo->url)) {
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/big/');
+					Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/big/');
 					return false;
 				}
 
 				# Delete medium
 				if (file_exists(LYCHEE_UPLOADS_MEDIUM . $photo->url)&&!unlink(LYCHEE_UPLOADS_MEDIUM . $photo->url)) {
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/medium/');
+					Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/medium/');
 					return false;
 				}
 
 				# Delete thumb
 				if (file_exists(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)&&!unlink(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)) {
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/');
+					Log::error(__METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/');
 					return false;
 				}
 
 				# Delete thumb@2x
 				if (file_exists(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)&&!unlink(LYCHEE_UPLOADS_THUMB . $thumbUrl2x))	 {
-					Log::error($this->database, __METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/');
+					Log::error(__METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/');
 					return false;
 				}
 
 			}
 
 			# Delete db entry
-			$query	= Database::prepare($this->database, "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id));
-			$delete	= $this->database->query($query);
+			$query	= Database::prepare(Database::get(), "DELETE FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photo->id));
+			$delete	= Database::get()->query($query);
 			if (!$delete) {
-				Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+				Log::error(__METHOD__, __LINE__, Database::get()->error);
 				return false;
 			}
 

+ 27 - 18
php/modules/Plugins.php

@@ -9,32 +9,35 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Plugins implements \SplSubject {
 
-	private $files		= array();
-	private $observers	= array();
+	private static $instance = null;
 
-	public $action	= null;
-	public $args	= null;
+	private $observers = array();
 
-	public function __construct(array $files, $database, array $settings) {
+	public $action = null;
+	public $args = null;
 
-		if (!isset($files)) return false;
+	public static function get() {
 
-		# Init vars
-		$this->files = $files;
+		if (!self::$instance) {
 
-		# Load plugins
-		foreach ($this->files as $file) {
+			$files = Settings::get()['plugins'];
+
+			self::$instance = new self($files);
+
+		}
+
+		return self::$instance;
+
+	}
 
-			if ($file==='') continue;
+	private function __construct(array $plugins) {
 
-			$file = LYCHEE_PLUGINS . $file;
+		# Load plugins
+		foreach ($plugins as $plugin) {
 
-			if (file_exists($file)===false) {
-				Log::warning($database, __METHOD__, __LINE__, 'Could not include plugin. File does not exist (' . $file . ').');
-				continue;
-			}
+			if ($plugin==='') continue;
 
-			include($file);
+			$this->attach(new $plugin);
 
 		}
 
@@ -42,6 +45,12 @@ final class Plugins implements \SplSubject {
 
 	}
 
+	private function __clone() {
+
+		# Magic method clone is empty to prevent duplication of plugins
+
+	}
+
 	public function attach(\SplObserver $observer) {
 
 		if (!isset($observer)) return false;
@@ -91,4 +100,4 @@ final class Plugins implements \SplSubject {
 
 }
 
-?>
+?>

+ 12 - 27
php/modules/Session.php

@@ -9,28 +9,16 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Session extends Module {
 
-	private $settings = null;
-
-	public function __construct($plugins, $settings) {
-
-		# Init vars
-		$this->plugins	= $plugins;
-		$this->settings	= $settings;
-
-		return true;
-
-	}
-
-	public function init($database, $dbName, $public) {
+	public function init($public) {
 
 		# Check dependencies
-		self::dependencies(isset($this->settings, $public));
+		self::dependencies(isset($public));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
 		# Return settings
-		$return['config'] = $this->settings;
+		$return['config'] = Settings::get();
 
 		# Path to Lychee for the server-import dialog
 		$return['config']['location'] = LYCHEE;
@@ -83,19 +71,19 @@ final class Session extends Module {
 	public function login($username, $password) {
 
 		# Check dependencies
-		self::dependencies(isset($this->settings, $username, $password));
+		self::dependencies(isset($username, $password));
 
 		# Call plugins
 		$this->plugins(__METHOD__, 0, func_get_args());
 
-		$username = crypt($username, $this->settings['username']);
-		$password = crypt($password, $this->settings['password']);
+		$username = crypt($username, Settings::get()['username']);
+		$password = crypt($password, Settings::get()['password']);
 
 		# Check login with crypted hash
-		if ($this->settings['username']===$username&&
-			$this->settings['password']===$password) {
+		if (Settings::get()['username']===$username&&
+			Settings::get()['password']===$password) {
 				$_SESSION['login']		= true;
-				$_SESSION['identifier']	= $this->settings['identifier'];
+				$_SESSION['identifier']	= Settings::get()['identifier'];
 				return true;
 		}
 
@@ -111,14 +99,11 @@ final class Session extends Module {
 
 	private function noLogin() {
 
-		# Check dependencies
-		self::dependencies(isset($this->settings));
-
 		# Check if login credentials exist and login if they don't
-		if ($this->settings['username']===''&&
-			$this->settings['password']==='') {
+		if (Settings::get()['username']===''&&
+			Settings::get()['password']==='') {
 				$_SESSION['login']		= true;
-				$_SESSION['identifier']	= $this->settings['identifier'];
+				$_SESSION['identifier']	= Settings::get()['identifier'];
 				return true;
 		}
 

+ 40 - 51
php/modules/Settings.php

@@ -9,51 +9,40 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
 final class Settings extends Module {
 
-	private $database = null;
+	private static $cache = null;
 
-	public function __construct($database) {
+	public static function get() {
 
-		# Init vars
-		$this->database = $database;
-
-		return true;
-
-	}
-
-	public function get() {
-
-		# Check dependencies
-		self::dependencies(isset($this->database));
+		if (self::$cache) return self::$cache;
 
 		# Execute query
-		$query		= Database::prepare($this->database, "SELECT * FROM ?", array(LYCHEE_TABLE_SETTINGS));
-		$settings	= $this->database->query($query);
+		$query		= Database::prepare(Database::get(), "SELECT * FROM ?", array(LYCHEE_TABLE_SETTINGS));
+		$settings	= Database::get()->query($query);
 
 		# Add each to return
 		while ($setting = $settings->fetch_object()) $return[$setting->key] = $setting->value;
 
-		# Fallback for versions below v2.5
-		if (!isset($return['plugins'])) $return['plugins'] = '';
+		# Convert plugins to array
+		$return['plugins'] = explode(';', $return['plugins']);
+
+		self::$cache = $return;
 
 		return $return;
 
 	}
 
-	public function setLogin($oldPassword = '', $username, $password) {
+	public static function setLogin($oldPassword = '', $username, $password) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database));
-
-		# Load settings
-		$settings = $this->get();
+		self::dependencies(isset($oldPassword, $username, $password));
 
-		if ($oldPassword===$settings['password']||$settings['password']===crypt($oldPassword, $settings['password'])) {
+		if ($oldPassword===self::get()['password']||self::get()['password']===crypt($oldPassword, self::get()['password'])) {
 
 			# Save username
-			if ($this->setUsername($username)!==true) exit('Error: Updating username failed!');
+			if (self::setUsername($username)!==true) exit('Error: Updating username failed!');
 
 			# Save password
-			if ($this->setPassword($password)!==true) exit('Error: Updating password failed!');
+			if (self::setPassword($password)!==true) exit('Error: Updating password failed!');
 
 			return true;
 
@@ -63,10 +52,10 @@ final class Settings extends Module {
 
 	}
 
-	private function setUsername($username) {
+	private static function setUsername($username) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database));
+		self::dependencies(isset($username));
 
 		# Hash username
 		$username = getHashedString($username);
@@ -74,21 +63,21 @@ final class Settings extends Module {
 		# Execute query
 		# Do not prepare $username because it is hashed and save
 		# Preparing (escaping) the username would destroy the hash
-		$query	= Database::prepare($this->database, "UPDATE ? SET value = '$username' WHERE `key` = 'username'", array(LYCHEE_TABLE_SETTINGS));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET value = '$username' WHERE `key` = 'username'", array(LYCHEE_TABLE_SETTINGS));
+		$result	= Database::get()->query($query);
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
 
 	}
 
-	private function setPassword($password) {
+	private static function setPassword($password) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database));
+		self::dependencies(isset($password));
 
 		# Hash password
 		$password = getHashedString($password);
@@ -96,43 +85,43 @@ final class Settings extends Module {
 		# Execute query
 		# Do not prepare $password because it is hashed and save
 		# Preparing (escaping) the password would destroy the hash
-		$query	= Database::prepare($this->database, "UPDATE ? SET value = '$password' WHERE `key` = 'password'", array(LYCHEE_TABLE_SETTINGS));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET value = '$password' WHERE `key` = 'password'", array(LYCHEE_TABLE_SETTINGS));
+		$result	= Database::get()->query($query);
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
 
 	}
 
-	public function setDropboxKey($key) {
+	public static function setDropboxKey($key) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $key));
+		self::dependencies(isset($key));
 
 		if (strlen($key)<1||strlen($key)>50) {
-			Log::notice($this->database, __METHOD__, __LINE__, 'Dropbox key is either too short or too long');
+			Log::notice(__METHOD__, __LINE__, 'Dropbox key is either too short or too long');
 			return false;
 		}
 
 		# Execute query
-		$query	= Database::prepare($this->database, "UPDATE ? SET value = '?' WHERE `key` = 'dropboxKey'", array(LYCHEE_TABLE_SETTINGS, $key));
-		$result = $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET value = '?' WHERE `key` = 'dropboxKey'", array(LYCHEE_TABLE_SETTINGS, $key));
+		$result = Database::get()->query($query);
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
 
 	}
 
-	public function setSortingPhotos($type, $order) {
+	public static function setSortingPhotos($type, $order) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $type, $order));
+		self::dependencies(isset($type, $order));
 
 		$sorting = 'ORDER BY ';
 
@@ -183,21 +172,21 @@ final class Settings extends Module {
 		# Do not prepare $sorting because it is a true statement
 		# Preparing (escaping) the sorting would destroy it
 		# $sorting is save and can't contain user-input
-		$query	= Database::prepare($this->database, "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingPhotos'", array(LYCHEE_TABLE_SETTINGS));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingPhotos'", array(LYCHEE_TABLE_SETTINGS));
+		$result	= Database::get()->query($query);
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;
 
 	}
 
-	public function setSortingAlbums($type, $order) {
+	public static function setSortingAlbums($type, $order) {
 
 		# Check dependencies
-		self::dependencies(isset($this->database, $type, $order));
+		self::dependencies(isset($type, $order));
 
 		$sorting = 'ORDER BY ';
 
@@ -239,11 +228,11 @@ final class Settings extends Module {
 		# Do not prepare $sorting because it is a true statement
 		# Preparing (escaping) the sorting would destroy it
 		# $sorting is save and can't contain user-input
-		$query	= Database::prepare($this->database, "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingAlbums'", array(LYCHEE_TABLE_SETTINGS));
-		$result	= $this->database->query($query);
+		$query	= Database::prepare(Database::get(), "UPDATE ? SET value = '$sorting' WHERE `key` = 'sortingAlbums'", array(LYCHEE_TABLE_SETTINGS));
+		$result	= Database::get()->query($query);
 
 		if (!$result) {
-			Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
+			Log::error(__METHOD__, __LINE__, Database::get()->error);
 			return false;
 		}
 		return true;

+ 11 - 15
php/modules/misc.php

@@ -7,9 +7,7 @@
 
 if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
 
-function search($database, $settings, $term) {
-
-	if (!isset($database, $settings, $term)) return false;
+function search($term) {
 
 	$return['albums'] = '';
 
@@ -24,8 +22,8 @@ function search($database, $settings, $term) {
 	# Photos
 	###
 
-	$query	= Database::prepare($database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term));
-	$result	= $database->query($query);
+	$query	= Database::prepare(Database::get(), "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%' OR tags LIKE '%?%'", array(LYCHEE_TABLE_PHOTOS, $term, $term, $term));
+	$result	= Database::get()->query($query);
 
 	while($photo = $result->fetch_assoc()) {
 
@@ -38,8 +36,8 @@ function search($database, $settings, $term) {
 	# Albums
 	###
 
-	$query	= Database::prepare($database, "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term));
-	$result = $database->query($query);
+	$query	= Database::prepare(Database::get(), "SELECT id, title, public, sysstamp, password FROM ? WHERE title LIKE '%?%' OR description LIKE '%?%'", array(LYCHEE_TABLE_ALBUMS, $term, $term));
+	$result = Database::get()->query($query);
 
 	while($album = $result->fetch_assoc()) {
 
@@ -47,8 +45,8 @@ function search($database, $settings, $term) {
 		$album = Album::prepareData($album);
 
 		# Thumbs
-		$query	= Database::prepare($database, "SELECT thumbUrl FROM ? WHERE album = '?' " . $settings['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id']));
-		$thumbs	= $database->query($query);
+		$query	= Database::prepare(Database::get(), "SELECT thumbUrl FROM ? WHERE album = '?' " . Settings::get()['sortingPhotos'] . " LIMIT 0, 3", array(LYCHEE_TABLE_PHOTOS, $album['id']));
+		$thumbs	= Database::get()->query($query);
 
 		# For each thumb
 		$k = 0;
@@ -69,15 +67,13 @@ function search($database, $settings, $term) {
 
 }
 
-function getGraphHeader($database, $photoID) {
-
-	if (!isset($database, $photoID)) return false;
+function getGraphHeader($photoID) {
 
-	$photo = new Photo($database, null, null, $photoID);
+	$photo = new Photo($photoID);
 	if ($photo->getPublic('')===false) return false;
 
-	$query	= Database::prepare($database, "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID));
-	$result	= $database->query($query);
+	$query	= Database::prepare(Database::get(), "SELECT title, description, url, medium FROM ? WHERE id = '?'", array(LYCHEE_TABLE_PHOTOS, $photoID));
+	$result	= Database::get()->query($query);
 	$row	= $result->fetch_object();
 
 	if (!$result||!$row) return false;

+ 2 - 6
plugins/check/index.php

@@ -58,16 +58,12 @@ if (!$gdVersion['GIF Read Support'] || !$gdVersion['GIF Create Support'])	$error
 if (!file_exists(LYCHEE_CONFIG_FILE))	exit('Error: Configuration not found. Please install Lychee for additional tests');
 else									require(LYCHEE_CONFIG_FILE);
 
-# Define the table prefix
-defineTablePrefix(@$dbTablePrefix);
-
 # Database
 $database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
 if (mysqli_connect_errno()!=0) $error .= ('Error: ' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . '' . PHP_EOL);
 
 # Load settings
-$settings = new Settings($database);
-$settings = $settings->get();
+$settings = Settings::get();
 
 # Config
 if (!isset($dbName)||$dbName==='')	$error .= ('Error: No property for $dbName in config.php' . PHP_EOL);
@@ -130,7 +126,7 @@ if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&&
 	echo('Imagick Active:  ' . $settings['imagick'] . PHP_EOL);
 	echo('Imagick Version: ' . $imagickVersion . PHP_EOL);
 	echo('GD Version:      ' . $gdVersion['GD Version'] . PHP_EOL);
-	echo('Plugins:         ' . $settings['plugins'] . PHP_EOL);
+	echo('Plugins:         ' . implode($settings['plugins'], ', ') . PHP_EOL);
 
 } else {
 

+ 1 - 8
plugins/displaylog/index.php

@@ -25,12 +25,6 @@ header('content-type: text/plain');
 if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error 001: Configuration not found. Please install Lychee first.');
 require(LYCHEE_CONFIG_FILE);
 
-# Define the table prefix
-defineTablePrefix(@$dbTablePrefix);
-
-# Declare
-$result = '';
-
 # Database
 $database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
 
@@ -40,8 +34,7 @@ if (mysqli_connect_errno()!=0) {
 }
 
 # Load settings
-$settings = new Settings($database);
-$settings = $settings->get();
+$settings = Settings::get();
 
 # Ensure that user is logged in
 if ((isset($_SESSION['login'])&&$_SESSION['login']===true)&&

+ 1 - 1
src/scripts/settings.js

@@ -31,7 +31,7 @@ settings.createConfig = function() {
 			dbTablePrefix
 		}
 
-		api.post('Database::createConfig', params, function(data) {
+		api.post('Config::create', params, function(data) {
 
 			if (data!==true) {
 

+ 1 - 7
view.php

@@ -26,14 +26,8 @@
 				require(__DIR__ . '/php/define.php');
 				require(__DIR__ . '/php/autoload.php');
 				require(__DIR__ . '/php/modules/misc.php');
-				require(LYCHEE_CONFIG_FILE);
 
-				# Define the table prefix
-				defineTablePrefix(@$dbTablePrefix);
-
-				$database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName);
-
-				echo getGraphHeader($database, $_GET['p']);
+				echo getGraphHeader($_GET['p']);
 
 			}
 

Some files were not shown because too many files changed in this diff