<?php
declare(strict_types = 1);

/**
 * Informations système.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class System
{
	/**
	 * Nom de l'application.
	 *
	 * @param string
	 */
	const APP_NAME = 'iGalerie';

	/**
	 * Numéro de version de l'application.
	 *
	 * @var string
	 */
	const APP_VERSION = '3.1.2';

	/**
	 * Site Web de l'application.
	 *
	 * @var string
	 */
	const APP_WEBSITE = 'https://www.igalerie.org/';

	/**
	 * Nom des tables de la base de données.
	 *
	 * @var array
	 */
	const DB_TABLES =
	[
		'cameras_brands', 'cameras_items', 'cameras_models', 'categories', 'comments',
		'config', 'favorites', 'groups', 'groups_permissions', 'items', 'items_pending',
		'passwords', 'search', 'selection', 'sessions', 'sessions_categories',
		'sessions_users', 'stats', 'tags', 'tags_items', 'users', 'users_logs', 'votes'
	];



	/**
	 * Extensions PHP utilisées par l'application.
	 *
	 * @var array
	 */
	private static $_phpExtensions =
	[
		'curl',
		'exif',
		'fileinfo',
		'gd',
		'iconv',
		'intl',
		'mbstring',
		'pcre',
		'PDO',
		'pdo_mysql',
		'pdo_pgsql',
		'pdo_sqlite',
		'SimpleXML',
		'zip',
		'zlib'
	];

	/**
	 * Fonctions utilisées par l'application, et susceptibles
	 * d'être désactivées par la configuration de PHP.
	 *
	 * @var array
	 */
	private static $_phpFunctions =
	[
		'chmod',
		'get_loaded_extensions',
		'fsockopen',
		'ini_get',
		'ini_set',
		'ignore_user_abort',
		'imagealphablending',
		'imagecolorallocatealpha',
		'imagecolortransparent',
		'imagecreatefromavif',
		'imagecreatefromgif',
		'imagecreatefromjpeg',
		'imagecreatefrompng',
		'imagecreatefromwebp',
		'imagesavealpha',
		'imagetypes',
		'mail',
		'mime_content_type',
		'php_uname',
		'rmdir',
		'set_time_limit'
	];

	/**
	 * Directives PHP importantes.
	 *
	 * @var array
	 */
	private static $_phpDirectives =
	[
		'allow_url_fopen' =>
		[
			'type' => 'bin',
			'recommended' => 'On'
		],
		'disable_classes' =>
		[
			'type' => 'val'
		],
		'disable_functions' =>
		[
			'type' => 'val'
		],
		'display_errors' =>
		[
			'type' => 'bin',
			'recommended' => 'Off'
		],
		'file_uploads' =>
		[
			'type' => 'bin',
			'recommended' => 'On'
		],
		'max_execution_time' =>
		[
			'type' => 'val'
		],
		'max_input_vars' =>
		[
			'type' => 'val'
		],
		'memory_limit' =>
		[
			'type' => 'val'
		],
		'open_basedir' =>
		[
			'type' => 'val'
		],
		'post_max_size' =>
		[
			'type' => 'val'
		],
		'upload_max_filesize' =>
		[
			'type' => 'val'
		],
		'zlib.output_compression' =>
		[
			'type' => 'bin'
		]
	];



	/**
	 * Retourne des informations concernant l'extension GD.
	 *
	 * @return array
	 */
	public static function getGDInfos(): array
	{
		$gd_infos = [];

		$gd = function_exists('gd_info') ? gd_info() : [];
		
		$attrs = ['GD Version', 'FreeType Support', 'AVIF Support', 'GIF Read Support',
			'GIF Create Support', 'JPEG Support', 'PNG Support', 'WebP Support'];

		foreach ($attrs as $name)
		{
			$value = $gd[$name] ?? 'undefined';
			$gd_infos[$name] =
			[
				'status' => $value && $value !== 'undefined' ? 'ok' : 'warning',
				'value' => is_string($value) ? $value : ($value ? __('activé') : __('désactivé'))
			];
		}

		return $gd_infos;
	}

	/**
	 * Retourne la valeur booléenne d'un paramètre de configuration PHP.
	 *
	 * @param string $varname
	 *
	 * @return bool
	 */
	public static function getIniBool(string $varname): bool
	{
		$value = ini_get($varname);

		switch (strtolower($value))
		{
			case 'on':
			case 'yes':
			case 'true':
				return 'assert.active' !== $varname;

			case 'stdout':
			case 'stderr':
				return 'display_errors' === $varname;

			default:
				return (bool) (int) $value;
		}
	}

	/**
	 * Retourne les informations du système d'exploitation.
	 *
	 * @param string $mode
	 *
	 * @return string
	 */
	public static function getOSInfos(string $mode): string
	{
		if (!function_exists('php_uname'))
		{
			return PHP_OS_FAMILY;
		}

		$infos = '';
		for ($i = 0; $i < strlen($mode); $i++)
		{
			$infos .= php_uname($mode[$i]) . ' ';
		}

		return trim($infos);
	}

	/**
	 * Retourne la liste et la valeur des directives PHP importantes.
	 *
	 * @return array
	 */
	public static function getPHPDirectives(): array
	{
		$directives_values = [];

		foreach (self::$_phpDirectives as $name => &$params)
		{
			// Valeur.
			if (!function_exists('ini_get'))
			{
				$directives_values[$name]['value'] = '?';
				$directives_values[$name]['status'] = 'info';
				continue;
			}
			else if ($params['type'] == 'bin')
			{
				$directives_values[$name]['value'] = self::getIniBool($name)
					? 'On'
					: 'Off';
			}
			else
			{
				$directives_values[$name]['value'] = ini_get($name);
			}

			// Valeur recommandée.
			if (!isset($params['recommended']))
			{
				$directives_values[$name]['status'] = 'info';
			}
			else if ($params['recommended'] == $directives_values[$name]['value'])
			{
				$directives_values[$name]['status'] = 'ok';
			}
			else
			{
				$directives_values[$name]['status'] = 'warning';
			}
		}

		return $directives_values;
	}

	/**
	 * Retourne la liste des extensions PHP activées et utilisées par l'application.
	 *
	 * @return array
	 */
	public static function getPHPExtensions(): array
	{
		$loaded_extensions = get_loaded_extensions();
		$values = [];
		foreach (self::$_phpExtensions as &$extension)
		{
			$values[$extension] = (int) in_array($extension, $loaded_extensions);
		}

		return $values;
	}

	/**
	 * Retourne la liste des fonctions utilisées par l'application
	 * et susceptibles d'être désactivées par la configuration de PHP.
	 *
	 * @return array
	 */
	public static function getPHPFunctions(): array
	{
		$values = [];
		foreach (self::$_phpFunctions as &$function)
		{
			$values[$function] = (int) function_exists($function);
		}

		return $values;
	}

	/**
	 * Retourne le type d'interface utilisé par PHP.
	 *
	 * @return string
	 */
	public static function getPHPSAPI(): string
	{
		return PHP_SAPI;
	}

	/**
	 * Retourne la version de PHP.
	 *
	 * @param bool $details
	 *   Doit-on retourner la description complète ?
	 *
	 * @return string
	 */
	public static function getPHPVersion($details = FALSE): string
	{
		if (!defined('PHP_VERSION'))
		{
			return '?';
		}

		return $details ? PHP_VERSION : preg_replace('`[^\d.]`', '', PHP_VERSION);
	}

	/**
	 * Retourne le temps serveur.
	 *
	 * @return mixed
	 */
	public static function getServerTime()
	{
		return date('Y-m-d H:i:s P (e)');
	}

	/**
	 * Retourne le type de serveur.
	 *
	 * @return string
	 */
	public static function getServerType(): string
	{
		if (empty($_SERVER['SERVER_SOFTWARE']))
		{
			return '?';
		}

		return strip_tags($_SERVER['SERVER_SOFTWARE']);
	}
}
?>