<?php
/**
 * Open Source Social Network
 *
 * @package   Open Source Social Network (OSSN)
 * @author    OSSN Core Team <info@openteknik.com>
 * @copyright (C) OpenTeknik LLC
 * @license   Open Source Social Network License (OSSN LICENSE)  http://www.opensource-socialnetwork.org/licence
 * @link      https://www.opensource-socialnetwork.org/
 */
class OssnInstallation extends stdClass {
		/**
		 * Installation Url;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public static function url() {
				return str_replace('installation/', '', ossn_installation_paths()->url);
		}

		/**
		 * Get data directory;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public static function DefaultDataDir() {
				$return = dirname(dirname(__FILE__));
				$return = str_replace('\\', '/', dirname(dirname($return)));
				return "{$return}/ossn_data/";
		}

		/**
		 * Check if mod_rewrite exist or not;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public static function is_mod_rewrite() {
				$file    = ossn_url();
				$rewrite = ossn_installation_simple_curl($file . 'rewrite.php');
				return $rewrite;
		}

		/**
		 * Check if php curl library installed or not
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public static function isCurl() {
				return function_exists('curl_version');
		}

		/**
		 * Check if php GD library is installed or not
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public static function isPhpGd() {
				if(extension_loaded('gd') && function_exists('gd_info')) {
						return true;
				}
				return false;
		}
		/**
		 * Check if the ZipArchive class exists or not
		 *
		 * @return boolean
		 */
		public static function isZipClass() {
				return class_exists('ZipArchive');
		}
		/**
		 * Check if allow_url_fopen is available or not
		 *
		 * @return boolean
		 */
		public static function allowUrlFopen() {
				return ini_get('allow_url_fopen');
		}
		/**
		 * Check if php is > than 8.0
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public static function isPhp() {
				//$phpversion >= 5.6 , works fine with php 5.6
				//Support php 5.6 or larger remove support for < 5.6 #1287
				//8tH April 2020, remove support for outdated PHP version
				//9th Feb 2022 remove support for php 7.x
				if(version_compare(PHP_VERSION, '8.0', '>=')) {
						return true;
				}
				return false;
		}

		/**
		 * Check if server is running apache or litespeed
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public static function isApache() {
				if(preg_match('/apache/i', $_SERVER['SERVER_SOFTWARE']) || preg_match('/LiteSpeed/i', $_SERVER['SERVER_SOFTWARE'])) {
						return true;
				}
				return false;
		}

		/**
		 * Check if configuration directory is writeable or not
		 *
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 * @return bool;
		 */
		public static function isCon_WRITEABLE() {
				$path = str_replace('installation/', '', ossn_installation_paths()->root);
				$path = $path . 'configurations';
				if(is_dir($path) && is_writable($path)) {
						return true;
				}
				return false;
		}
		/**
		 * Check if cache directory is writeable or not
		 *
		 * @return boolean
		 */
		public static function isCacheWriteable() {
				$path = str_replace('installation/', '', ossn_installation_paths()->root);
				$path = $path . 'cache';
				if(!is_dir($path)) {
						if(mkdir($path, 0755, true)) {
								rmdir($path);
								return true;
						} else {
								return false;
						}
				}
				return false;
		}
		/**
		 * Check if mysqli class exist exist or not
		 *
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 * @return bool;
		 */
		public static function is_mysqli_enabled() {
				return class_exists('mysqli');
		}

		/**
		 * Get database user;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public function dbusername($username) {
				if(!empty($username)) {
						$this->dbusername = $username;
				} else {
						$this->dbusername = 'root';
				}
		}

		/**
		 * Get db password;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public function dbpassword($password) {
				$this->dbpassword = $password;
		}

		/**
		 * Get databasename;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public function dbname($dbname) {
				if(!empty($dbname)) {
						$this->dbname = $dbname;
				} else {
						$this->dbname = 'Ossn';
				}
		}

		/**
		 * Get db host;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public function dbhost($dbhost) {
				preg_match('/([\w\.-]+)(|\:(\d+))$/', $dbhost, $matches);
				//set the host without port
				if(isset($matches[1])) {
						$dbhost = $matches[1];
				}
				if(!empty($dbhost)) {
						$this->dbhost = $dbhost;
				} else {
						$this->dbhost = 'localhost';
				}
				//set the port
				if(isset($matches[3]) && !empty($matches[3])) {
						$this->dbport($matches[3]);
				} else {
						$port = ini_get('mysqli.default_port');
						if(empty($port)) {
								$port = 3306;
						}
						$this->dbport($port);
				}
		}

		/**
		 * Get db host;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public function dbport($dbport) {
				if(!empty($dbport) && (int) $dbport > 0) {
						$this->dbport = $dbport;
				}
		}

		/**
		 * Get web url;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 *
		 */
		public function weburl($weburl) {
				if(!empty($weburl)) {
						$this->weburl = $weburl;
				}
		}

		/**
		 * Set a datadriectory;
		 * @last edit: $arsalanshah
		 * @retun void;
		 *
		 */
		public function datadir($dir) {
				$this->datadir = $dir;
		}

		public function setStartupSettings($data) {
				$this->startup_settings = $data;
		}

		/**
		 * Process Data;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 * @return bool;
		 */
		public function INSTALL() {
				if(stripos($this->datadir, $this->ossnInstallationDir()) === 0) {
						$this->error_mesg = ossn_installation_print('data:directory:outside');
						return false;
				}
				if(!is_dir($this->datadir) && !mkdir($this->datadir, 0755, true)) {
						$this->error_mesg = ossn_installation_print('data:directory:unabletoautocreate');
						return false;
				}
				if(!is_dir($this->datadir) && !is_writable($this->datadir)) {
						$this->error_mesg = ossn_installation_print('data:directory:invalid');
						return false;
				}
				if(!file_put_contents($this->datadir . 'writeable', 1)) {
						$this->error_mesg = ossn_installation_print('data:directory:invalid');
						return false;
				} else {
						$writeable = file_get_contents($this->datadir . 'writeable');
						if(!$writeable || ($writeable && $writeable != 1)) {
								$this->error_mesg = ossn_installation_print('data:directory:invalid');
								return false;
						}
				}
				unlink($this->datadir . 'writeable');

				try {
						$this->dbconnect();
				} catch (Exception $e) {
						$this->error_mesg = $e->getCode() . ' ' . $e->getMessage();
						return false;
				}
				if($script = file_get_contents(ossn_installation_paths()->root . 'sql/opensource-socialnetwork.sql')) {
						$script         = str_replace('<<owner_email>>', $this->startup_settings['owner_email'], $script);
						$script         = str_replace('<<notification_email>>', $this->startup_settings['notification_email'], $script);
						$script         = str_replace('<<sitename>>', $this->startup_settings['sitename'], $script);
						$script         = str_replace('<<secret>>', substr(md5('ossn' . bin2hex(random_bytes(6))), 3, 8), $script);
						$errors         = array();
						$script         = preg_replace('/\-\-.*\n/', '', $script);
						$sql_statements = preg_split('/;[\n\r]+/', $script);

						foreach ($sql_statements as $statement) {
								$statement = trim($statement);
								if(!empty($statement)) {
										try {
												$this->dbconnect()->query($statement);
										} catch (Exception $e) {
												$errors[] = $e->getMessage();
										}
								}
						}
						$this->configurations_db();
						$this->configurations_site();
						if(!empty($errors)) {
								$errortxt = '';
								foreach ($errors as $error) {
										$errortxt .= " {$error};";
								}

								$msg = $errortxt;
								throw new Exception($msg);
						}
				}
				//[E] Improve installation script #2294
				//for custom installations scripts
				$post_install = ossn_installation_paths()->root . 'post_install/';
				$iterator     = new GlobIterator("{$post_install}post_install*.php", FilesystemIterator::KEY_AS_FILENAME);
				if($iterator) {
						//start OSSN engine
						define('OSSN_ALLOW_SYSTEM_START', true);
						require_once dirname(dirname(dirname(__FILE__))) . '/system/start.php';
						foreach ($iterator as $item) {
								$path = $item->getPathname();
								if(file_exists($path)) {
										require_once $path;
								}
						}
				}
				return true;
		}

		/**
		 * Get Installation dir path;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 * @return string
		 */
		public static function ossnInstallationDir() {
				return str_replace('\\', '/', dirname(dirname(dirname(__FILE__)))) . '/';
		}

		/**
		 * Connect to database;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 */
		public function dbconnect() {
				$connect = new mysqli($this->dbhost, $this->dbusername, $this->dbpassword, $this->dbname, $this->dbport);
				return $connect;
		}

		/**
		 * Database configuration;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 */
		function configurations_db() {
				$params = array(
						'host'     => $this->dbhost,
						'port'     => $this->dbport,
						'user'     => $this->dbusername,
						'password' => $this->dbpassword,
						'dbname'   => $this->dbname,
				);
				$this->path   = str_replace('installation/', '', ossn_installation_paths()->root);
				$templateFile = $this->path . 'configurations/ossn.config.db.example.php';
				$template     = file_get_contents($templateFile);
				if(!$template) {
						throw new Exception(ossn_installation_print('all:files:required'));
				}

				foreach ($params as $k => $v) {
						$template = str_replace('<<' . $k . '>>', $v, $template);
				}

				$settingsFilename = $this->path . 'configurations/ossn.config.db.php';
				$result           = file_put_contents($settingsFilename, $template);
				if(!$result) {
						return false;
				}

				return true;
		}

		/**
		 * Web site configuration;
		 * @last edit: $arsalanshah
		 * @Reason: Initial;
		 * @return bool;
		 */
		function configurations_site() {
				$params = array(
						'siteurl' => $this->weburl,
						'datadir' => $this->datadir,
				);
				$this->path   = str_replace('installation/', '', ossn_installation_paths()->root);
				$templateFile = $this->path . 'configurations/ossn.config.site.example.php';
				$template     = file_get_contents($templateFile);
				if(!$template) {
						throw new Exception(ossn_installation_print('all:files:required'));
				}

				foreach ($params as $k => $v) {
						$template = str_replace('<<' . $k . '>>', $v, $template);
				}

				$settingsFilename = $this->path . 'configurations/ossn.config.site.php';
				$result           = file_put_contents($settingsFilename, $template);
				if(!$result) {
						return false;
				}

				return true;
		}
} //class