<?php

declare(strict_types=1);

/**
 * This file is part of LEPTON Core, released under the GNU GPL
 * Please see LICENSE and COPYING files in your package for details, specially for terms and warranties.
 * 
 * NOTICE:LEPTON CMS Package has several different licenses.
 * Please see the individual license in the header of each single file or info.php of modules and templates.
 *
 * @author          LEPTON Project
 * @copyright       2010-2026 LEPTON Project
 * @link            https://lepton-cms.org
 * @license         https://gnu.org/licenses/gpl.html
 * @license_terms   please see LICENSE and COPYING files in your package
 *
 */


/**
 *	@notice		Please keep in mind, that class "frontend" extends class "LEPTON_core"
 *
 */
class LEPTON_frontend extends LEPTON_core
{
    use LEPTON_singleton;

	public LEPTON_database $database;
	public static $instance;
	
	// [1] Defaults
	public string $default_link = "/";
	public int $default_page_id = 1;
	 
	// [2] Page details
	public array $page = [];
	public int $page_id = 0;
	
	public array $page_trail = [];
	
	public bool $page_access_denied = false;
	public bool $page_no_active_sections = false;

    public function __construct()
    {	
		global $TEXT;
		
		LEPTON_core::registerBasicFunctions();
		LEPTON_core::loadCodeSnippets();
		$this->database = LEPTON_database::getInstance();

		// include cronjob file for external call
		// @DEPRECATED_TEMP 20251010: this class will be removed in L* > 7.5.0, use external cronjobs instead
		if(CRONJOB == 1 || CRONJOB == 3)
		{
			$_POST['ikey'] = LEPTON_cronjob::getInstance()->cj_key;
			LEPTON_handle::include_files("/modules/cronjob.php");
		}

        self::$instance = $this;
		if (TFA != 'none')	// first step in process to display page and set vars
		{		
			if (!isset($_SESSION['USER_ID']))
			{
				$pin_set = -1;
			}
			else
			{
				$pin_set = $this->database->get_one("SELECT pin_set FROM ".TABLE_PREFIX."users WHERE user_id = '".$_SESSION['USER_ID']."' ");
				
			}
			
			switch ($pin_set )
			{
				case 0:
				case 1:
					header('Location: '.LEPTON_URL.'/account/logout.php');
					break;    
				
				case -1:
				case 2:
					LEPTON_SecureCMS::clearLepTokens();
					break; 					
				
				default:
					LEPTON_SecureCMS::clearLepTokens();
					header('Location: '.LEPTON_URL.'/account/logout.php');		
			}	
		}	
    }

    public function page_select()
    {
        global $page_id;

        // Check if we should add page language sql code
        if (PAGE_LANGUAGES == true)
        {
            $sql_where_language = " AND p.language = '".LANGUAGE."'";
        }
        else
        {
            $sql_where_language = "";
        }

        // Get default page
        $now            = time();
        $query_default  = "
            SELECT      * 
            FROM        ".TABLE_PREFIX . "pages AS p 
            INNER JOIN  ".TABLE_PREFIX . "sections AS s
            
            ON (s.page_id = p.page_id)
            
            WHERE   p.parent = 0 
                
            AND p.visibility = 'public'	
            
            AND (
                    ((".$now." >= s.publ_start) OR (s.publ_start = 0)) 
                AND 
                    ((".$now." <= s.publ_end) OR (s.publ_end = 0))
            )
            ".$sql_where_language."
            ORDER BY
                p.position
            
            ASC LIMIT 1
        ";

        $fetch_default = [];
        $this->database->execute_query(
            $query_default,
            true,
            $fetch_default,
            false
        );

        if (!isset($page_id) || !is_numeric($page_id))
        {
            // Display default page
            if (!empty($fetch_default))
            {
                $this->default_link    = $fetch_default[ 'link' ];
                $this->default_page_id = intval($fetch_default[ 'page_id' ]);

                // Check if we should redirect or include page inline
                if (HOMEPAGE_REDIRECTION)
                {
                    // Redirect to page
                    header("Location: ".$this->buildPageLink($this->default_link));
                    exit();
                }
                else
                {
                    // Include page inline
                    $this->page_id = $this->default_page_id;
                }
            }
            else
            {
                // PAGE_LANGUAGES == true, therefore you want to have pages with different languages. In this case there is no page in "your" language available!
                die(LEPTON_tools::display_dev('[300]:Please check if you have pages in your language!', 'pre','ui blue message'));
            }
        }
        else
        {
            if (!isset($fetch_default[ 'link' ]))
            {
                die(LEPTON_tools::display('This installation has no content yet', 'pre','ui red message'));
            }

            $this->page_id = intval($page_id);
            $this->default_link     = $fetch_default[ 'link' ];
            $this->default_page_id  = intval($fetch_default[ 'page_id' ]);
            $this->page             = $fetch_default;

        }

        return true;
    }

    public function get_page_details()
    {
		$this->page_id = intval($this->page_id);
        if ($this->page_id != 0)
		{
			$this->page = [];
			$query_page = "SELECT * FROM ".TABLE_PREFIX."pages WHERE page_id = ".$this->page_id;
			$this->database->execute_query(
			    $query_page,
			    true,
			    $this->page,
			    false
			);
			
			// Make sure page was found in database
			if (empty($this->page))
			{
				// Print page not found message
				exit( "Page not found." );
			}
			else
			{
				foreach ($this->page as $key => $value)
				{
					// set members of array to constants
					$key = strtoupper($key);
					if (!defined($key))
					{			
						if ($key === 'TEMPLATE' && empty($value))
						{						
							$value = $this->database->get_one("SELECT value FROM ".TABLE_PREFIX."settings WHERE name = 'default_template' ");
						}
						
						if ($key === 'DESCRIPTION' && empty($value))
						{						
							$value = WEBSITE_DESCRIPTION;
						}
						
						if ($key === 'KEYWORDS' && empty($value))
						{						
							$value = WEBSITE_KEYWORDS;
						}						
						
						define($key, $value);
					}
				}
			}

			
			// Page trail
			foreach ( explode( ',', $this->page[ 'page_trail' ] ) AS $pid )
			{
				$this->page_trail[ $pid ] = $pid;
			}					
		}
				
		
		// Set the template dir
		if(!defined('TEMPLATE'))
		{
			define('TEMPLATE', DEFAULT_TEMPLATE);
		}
		define( 'TEMPLATE_DIR', LEPTON_URL . '/templates/' . TEMPLATE );
		// Check if user is allowed to view this page
		if ($this->page_is_visible($this->page) === false)
		{
			if ( VISIBILITY == 'deleted' || VISIBILITY == 'none' )
			{
				// User isn't allowed on this page so tell them
				$this->page_access_denied = true;
			}
			elseif ( VISIBILITY == 'private' || VISIBILITY == 'registered' )
			{
				// Check if the user is authenticated
				if ( $this->is_authenticated() === false )
				{
					// User needs to log-in first
					header( "Location: " . LEPTON_URL . "/account/login.php?redirect=" . $this->buildPageLink($this->page['link']) );
					exit( 0 );
				}
				else
				{
					$aAllowedGroupsId = explode(',',$this->page['viewing_groups']);
					$aSessionGroupsId = LEPTON_core::getValue('groups_id','string_clean','session',',');
					$result = array_intersect( $aSessionGroupsId,$aAllowedGroupsId);
					if(!empty($result))
					{
						
						$this->page_access_denied = false;
					}
					else
					{
						// User is not allowed on this page so tell them
						$this->page_access_denied = true;
					}		
				}													
			}
		}

        $this->maintainConstants();

		// check if there is at least one active section
        if ($this->page_is_active($this->page) === false)
		{
			$this->page_no_active_sections = true;
		}
	}
	
	public function get_website_settings()
	{				
		// Work-out if any possible in-line search boxes should be shown
		if ( SEARCH == 'public' )
		{
			define( 'SHOW_SEARCH', true );
		}
		elseif ( SEARCH == 'private' && VISIBILITY == 'private' )
		{
			define( 'SHOW_SEARCH', true );
		}
		elseif ( SEARCH == 'private' && $this->is_authenticated() === true )
		{
			define( 'SHOW_SEARCH', true );
		}
		elseif ( SEARCH == 'registered' && $this->is_authenticated() === true )
		{
			define( 'SHOW_SEARCH', true );
		}
		else
		{
			define( 'SHOW_SEARCH', false );
		}
		// Work-out if menu should be shown
		if ( !defined( 'SHOW_MENU' ) )
		{
			define( 'SHOW_MENU', true );
		}
		// Work-out if login menu constants should be set
		if ( FRONTEND_LOGIN )
		{
			// Set login menu constants
			define( 'LOGIN_URL', LEPTON_URL . '/account/login.php' );
			define( 'LOGOUT_URL', LEPTON_URL . '/account/logout.php' );
			define( 'FORGOT_URL', LEPTON_URL . '/account/forgot.php' );
			define( 'PREFERENCES_URL', LEPTON_URL . '/account/preferences.php' );
			define( 'SIGNUP_URL', LEPTON_URL . '/account/signup.php' );
		}
	}
	
	/**
	 *	replace all "[LEPTONlink{page_id}]" with real links
	 *	@param	string &$content : reference to global $content
	 *	@return	void
	 */
    public function preprocess(string &$content): void
	{
		$content = str_ireplace( ["%5B","%5D"], ["[", "]"], $content);

		// starting with L*5 LEPTONlink replaces wblink
        if (preg_match_all('/\[LEPTONlink([0-9]+)\]/isU', $content, $ids))
		{
			$new_ids = array_unique( $ids[ 1 ] );
            foreach ($new_ids as $key => $temp_page_id)
			{
				$link = $this->database->get_one( "SELECT `link` FROM `" . TABLE_PREFIX . "pages` WHERE `page_id` = " . $temp_page_id );
                if (!is_null($link))
				{
                    $content = str_replace($ids[0][$key], $this->buildPageLink($link), $content);
				}
			}
			unset($temp_page_id);
		}
	}

    /**
     * This is necessary if, for example, the views of search results.
     *
     * @return void
     */
    public function maintainConstants(): void
    {
        $lookFor = [
            "DESCRIPTION" => WEBSITE_DESCRIPTION,
            "KEYWORDS" => WEBSITE_KEYWORDS
        ];

        foreach ($lookFor as $key => $value)
        {
            if (!defined($key))
            {
                define($key, $value);
            }
        }
    }
    

    /**
     *  Displays a frontend-message-box via template.
     *
     *  @param string   $sType          The "class" type off the message: success, error, positiv, whatever.
     *  @param string   $sMessage       Any Message array | string.
     *  @param string   $sRedirect      Any redirect (URL), mostly the current page itself.
     *  @param int      $iRedirectTime  The redirect time. Keep in mind that this are js-milliseconds! 3000 are 3 sec! A value like -1 means no timeout; stand still.
     *  @param string   $sTemplateName  Any name of the .lte file in folder DEFAULT_TEMPLATE."/frontend/core/
     *  @param bool     $bDirectOutput  Prompt the message direct (echo), false returns the generated source. Default is true == prompt!
     *
     *  @code:
     *      $aMessage = ['header','text1']
     *      LEPTON_frontend::displayFEMessage(
     *           "success",
     *           $aMessage,
     *           "https://domain.tld/page/start.php",
     *           5000 // very long time; -1 means: stand still
     *          "message_custom.lte"
     *        );
     */ 
    public static function displayFEMessage(
        string       $sType ="success",
        array|string $aMessage = [],
        string       $sRedirect = "",
        int          $iRedirectTime = -1,
        string       $sTemplateName = "message.lte",
        bool         $bDirectOutput = true
    ): string
    {
        $oTwig = lib_twig_box::getInstance();

        if (!is_array($aMessage))
        {
            $aMessage = [$aMessage];
        }

        if (empty($sRedirect))
        {
            // Try to get a valid full link to the current page
            $link = self::$instance->page['link'];
            $sRedirect = LEPTON_core::getInstance()->buildPageLink($link);
        }

        // [1] Is there a lte file inside the frontend-template dir?
        if (file_exists(LEPTON_PATH."/templates/".DEFAULT_TEMPLATE."/frontend/core/message.lte"))
        {
            // [1.1] File is inside the frontend-template - so we are using this path.
            $oTwig->registerPath(LEPTON_PATH."/templates/".DEFAULT_TEMPLATE."/frontend/core/", "core");
        }
        else
        {
            // [1.2] File not found so we are using the "default" path inside the "account" directory.
            die(LEPTON_tools::display('There is no message file in your FE-Template available!', 'pre','ui orange message'));
        }

        $data = [
            'type' => $sType,
            'message' => $aMessage,
            'redirect' => $sRedirect,
            'redirect_time' => $iRedirectTime
        ];

        $sHTML_rendered = $oTwig->render(
            "@core/".$sTemplateName,
            $data
        );
        
        if ($bDirectOutput == true)
        {
            echo $sHTML_rendered;
            return "";
        }
        
        return $sHTML_rendered;
    }


    public static function getSessionAndClean(string $sKey, string $sType = "string"): string|int
    {
        $returnValue = LEPTON_core::getValue($sKey, $sType, "session") ?? "";
        unset($_SESSION[$sKey]);
        return $returnValue;
    }
}
