<?php
/**
 * @package jDownloads
 * @version 4.1  
 * @copyright (C) 2007 - 2025 - Arno Betz - www.jdownloads.com
 * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.txt
 * 
 * jDownloads is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
 
defined('_JEXEC') or die('Restricted access');

setlocale(LC_ALL, 'C.UTF-8', 'C');

use Joomla\CMS\Application\ApplicationHelper;
use Joomla\Utilities\ArrayHelper; 
use Joomla\String\StringHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Installer\Installer;
use Joomla\CMS\Installer\InstallerScript;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Installer\InstallerAdapter;
use Joomla\CMS\Version;
use Joomla\Database\DatabaseInterface;
use Joomla\Database\DatabaseAwareInterface;
use Joomla\Database\DatabaseAwareTrait;

HtmlHelper::_('behavior.formvalidator');
HtmlHelper::_('behavior.keepalive');


/**
 * Install Script file of jDownloads component
 */
#[\AllowDynamicProperties]
class com_jdownloadsInstallerScript extends InstallerScript
{
	private $new_version;
    private $new_version_short;
    private $target_joomla_version;
    private $old_version_short;
    private $install_msg;
    private $categories_table;
    private $files_table;
    private $templates_table;
    private $licenses_table;
    private $logs_table;
    private $usergroups_limits;
    private $wrong_table = array();
    private $wrong_fields = array();
    private $asset_title_max_length = null;

    /**
     * Executes the current database query and forwards failures to the installer error state.
     *
     * @param DatabaseInterface $db
     *
     * @return bool
     */
    private function executeQuery(DatabaseInterface $db): bool
    {
        try {
            $db->execute();

            return true;
        } catch (\RuntimeException $e) {
            $this->setError($e->getMessage());

            return false;
        }
    }
    
    /**
	 * Method to install the component
	 *
	 * @return void
	 */
	public function install($parent) 
	{
        // Try to set time limit
        @set_time_limit(0);

        // Try to increase memory limit
        if ((int) ini_get( 'memory_limit' ) < 32){
            @ini_set( 'memory_limit', '32M' );
        }
        
        Factory::getContainer()->get(DatabaseInterface::class);
        $user = Factory::getApplication()->getIdentity();

        $db = Factory::getContainer()->get(DatabaseInterface::class);

        // Add a log entry
        self::addLog(Text::sprintf('COM_JDOWNLOADS_INSTALL_LOG_START', $user->id, $user->name, $this->new_version), 'Log::INFO', false);                
        
        $params = ComponentHelper::getParams('com_jdownloads');
        $files_upload_dir = $params->get( 'files_uploaddir' );
        
		// Insert the default layouts.
		require_once (JPATH_ADMINISTRATOR.'/components/com_jdownloads/src/Helper/StandardLayouts.php');
		
        /*
        / Copy frontend images to the joomla images folder
        */
        $target = JPATH_ROOT.'/images/jdownloads';
        $source = dirname(__FILE__).'/site/assets/images/jdownloads';
        
        $images_copy_result   = false;
        $images_folder_exists = false;
        
        if (!Folder::exists($target)){
            $images_copy_result = Folder::copy($source,$target);
        } else {
            $images_folder_exists = true;
        }       

        // Check whether custom css file already exist
        $custom_css_path = JPATH_ROOT.'/components/com_jdownloads/assets/css/jdownloads_custom.css';
        if (!File::exists($custom_css_path)){
            // create a new css file
            $text  = "/* Custom CSS File for jDownloads\n";
            $text .= "   If this file already exist then jDownloads does not overwrite it when installing or upgrading jDownloads.\n";
            $text .= "   This file is loaded after the standard jdownloads_fe.css.\n";   
            $text .= "   So you can use it to overwrite the standard css classes for your own customising.\n*/";               
            $x = file_put_contents($custom_css_path, $text, FILE_APPEND);
        }
        
        /*
        / Install modules and plugins
        */
        $status = new \stdClass();
        $status->modules = array();
        $status->plugins = array();
        $src_modules = dirname(__FILE__).'/modules';
        $src_plugins = dirname(__FILE__).'/plugins';

        // Install Plugins
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_system_jdownloads');
        $status->plugins[] = array('name'=>'jDownloads System Plugin','group'=>'system', 'result'=>$result);
        
        // System plugin must be enabled for user group limits
        $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `name` = 'plg_system_jdownloads' AND `type` = 'plugin'");
        $db->execute();

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/editor_button_plugin_jdownloads_downloads');
        $status->plugins[] = array('name'=>'jDownloads Download Content Button Plugin','group'=>'editors-xtd', 'result'=>$result);        
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_content_jdownloads');
        $status->plugins[] = array('name'=>'jDownloads Content Plugin','group'=>'content', 'result'=>$result);        

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_finder_jdownloads');
        $status->plugins[] = array('name'=>'jDownloads Finder Plugin','group'=>'finder', 'result'=>$result);

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_finder_folder');
        $status->plugins[] = array('name'=>'jDownloads Finder Categories Plugin','group'=>'finder', 'result'=>$result);
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_content_jdownloads_tags_fix');
        $status->plugins[] = array('name'=>'jDownloads Tags Fix Content Plugin','group'=>'content', 'result'=>$result);        

		// 'Tags' fix plugin must be enabled 
        $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `name` = 'plg_content_jdownloads_tags_fix' AND `type` = 'plugin'");
        $db->execute();		

        // Install Modules
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_latest');
        $status->modules[] = array('name'=>'jDownloads Latest Module','client'=>'site', 'result'=>$result);

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_top');
        $status->modules[] = array('name'=>'jDownloads Top Module','client'=>'site', 'result'=>$result);

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_last_updated');
        $status->modules[] = array('name'=>'jDownloads Last Updated Module','client'=>'site', 'result'=>$result);

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_most_recently_downloaded');
        $status->modules[] = array('name'=>'jDownloads Most Recently Downloaded Module','client'=>'site', 'result'=>$result);
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_stats');
        $status->modules[] = array('name'=>'jDownloads Stats Module','client'=>'site', 'result'=>$result);        

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_tree');
        $status->modules[] = array('name'=>'jDownloads Tree Module','client'=>'site', 'result'=>$result);
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_related');
        $status->modules[] = array('name'=>'jDownloads Related Module','client'=>'site', 'result'=>$result);        

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_rated');
        $status->modules[] = array('name'=>'jDownloads Rated Module','client'=>'site', 'result'=>$result);

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_featured');
        $status->modules[] = array('name'=>'jDownloads Featured Module','client'=>'site', 'result'=>$result);
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_view_limits');
        $status->modules[] = array('name'=>'jDownloads View Limits Module','client'=>'site', 'result'=>$result);
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_admin_stats');
        $status->modules[] = array('name'=>'jDownloads Admin Stats Module','client'=>'admin', 'result'=>$result);
        
        // Admin stats module (should be published on position 'jdcpanel').
        $mod_array = array ("view_latest" => "1", "view_popular" => "1", "view_featured" => "1", "view_most_rated" => "1", "view_top_rated" => "1", "amount_items" => "5", "view_statistics" => "1", "view_monitoring_log" => "1", "view_restore_log" => "1", "view_server_info" => "1", "layout" => "_:default", "moduleclass_sfx" => "", "cache" => "0", "cache_time" => "900", "module_tag" => "div", "bootstrap_size" => "0", "header_tag" => "h3", "header_class" => "", "style" => "0");
        $mod_params = json_encode($mod_array, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        $db->setQuery("UPDATE #__modules SET `published` = '1', `title` = '".Text::_('COM_JDOWNLOADS_STATS_MODULE_TITLE')."', `position` = 'jdcpanel', `ordering` = '1', `showtitle` = '1', `params` = '".$mod_params."' WHERE `module` = 'mod_jdownloads_admin_stats'");
        $db->execute();
        
        // It must also exist a dataset in the _modules_menu table to get the module visible!
        // Get the right ID
        $db->setQuery("SELECT id FROM #__modules WHERE `module` = 'mod_jdownloads_admin_stats'");
        $module_id = (int)$db->loadResult();
        
        if ($module_id){
            $db->setQuery("SELECT COUNT(*) FROM #__modules_menu WHERE `moduleid` = '$module_id'");
            $result = (int)$db->loadResult();
            // Insert it only when not already exist            
            if (!$result){
            	$db->setQuery("INSERT INTO #__modules_menu (moduleid, menuid) VALUES ('$module_id' , '0')");
            	$db->execute();
        	}
        }
        
        // Monitoring admin module
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_admin_monitoring');
        $status->modules[] = array('name'=>'jDownloads Admin Monitoring Module','client'=>'admin', 'result'=>$result);
        
        // Admin monitoring module should be published on position 'jdcpanel'.
        $mod_array = array ("layout" => "_:default", "moduleclass_sfx" => "", "cache" => "0", "cache_time" => "900", "module_tag" => "div", "bootstrap_size" => "0", "header_tag" => "h3", "header_class" => "", "style" => "0");
        $mod_params = json_encode($mod_array, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        $db->setQuery("UPDATE #__modules SET `published` = '1', `title` = '".Text::_('COM_JDOWNLOADS_MONITORING_MODULE_TITLE')."', `position` = 'jdcpanel', `ordering` = '2', `showtitle` = '1', `params` = '".$mod_params."' WHERE `module` = 'mod_jdownloads_admin_monitoring'");
        $db->execute();
        
        // It must also exist a dataset in the _modules_menu table to get the module visible!
        // Get the right ID
        $db->setQuery("SELECT id FROM #__modules WHERE `module` = 'mod_jdownloads_admin_monitoring'");
        $module_id = (int)$db->loadResult();
        
        if ($module_id){
            $db->setQuery("SELECT COUNT(*) FROM #__modules_menu WHERE `moduleid` = '$module_id'");
            $result = (int)$db->loadResult();
            // Insert it only when not already exist            
            if (!$result){
	            $db->setQuery("INSERT INTO #__modules_menu (moduleid, menuid) VALUES ('$module_id' , '0')");
	            $db->execute();
        	}
        }
        
        ?>
        <hr>
        <div class="adminlist">
            <h4 style="color:#555;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_0'); ?></h4>
        <ul>

        <?php
        
        // Exist the jDownloads tables?
        // Get DB prefix string
        $prefix = self::getCorrectDBPrefix();
        $tablelist = $db->getTableList();
       
        if ( !in_array ( $prefix.'jdownloads_files', $tablelist ) ){
           Factory::getApplication()->enqueueMessage( Text::_('COM_JDOWNLOADS_INSTALL_ERROR_NO_TABLES'), 'warning');
           return false;  
       
        } else {
       
            $jd_version = $this->new_version_short;

            // Fresh installation - Build upload root path
            $jd_upload_root = JPATH_ROOT.'/jdownloads';

                /*
                / Install default configuration data - but only when we have really a 'fresh' installation and we have not found any old DB tables
                */
                $query = array();
                 
                // Write default layouts in database      
                $sum_layouts = 0;
				$name_extension = ' v4.1';

                // At first the new bootstrap layouts for version 4.1

                // Categories Standard Layout  (activated by installation as default)
                $cats_layout_before = stripslashes($JLIST_TEMPLATES_BOOT_CATS_DEFAULT_BEFORE);
                $cats_layout        = stripslashes($JLIST_TEMPLATES_BOOT_CATS_DEFAULT);
                $cats_layout_after  = stripslashes($JLIST_TEMPLATES_BOOT_CATS_DEFAULT_AFTER);
                $cats_header        = stripslashes($cats_header_boot);
                $cats_subheader     = stripslashes($cats_subheader_boot);
                $cats_footer        = stripslashes($cats_footer_boot);
                $cats_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_CATS_DEFAULT_NAME_V41_NOTE'); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_CATS_DEFAULT_NAME_V41')).$name_extension."', 1, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '".$cats_layout_before."', '".$cats_layout_after."', '".$cats_notes."', 1, 1, 1, 1, '*', 0)");
                $db->execute();
                $sum_layouts++;

                // Sub Categories Standard Layout  (activated by installation as default)
                $cats_layout_before = stripslashes($JLIST_TEMPLATES_SUBCATS_BOOT_PAGINATION_BEFORE);
                $cats_layout        = stripslashes($JLIST_TEMPLATES_SUBCATS_BOOT_PAGINATION_DEFAULT);
                $cats_layout_after  = stripslashes($JLIST_TEMPLATES_SUBCATS_BOOT_PAGINATION_AFTER);
                $cats_header        = stripslashes('');
                $cats_subheader     = stripslashes('');
                $cats_footer        = stripslashes('');
                $cats_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_SUBCATS_DEFAULT_NAME_V41_NOTE'); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_SUBCATS_DEFAULT_NAME_V41')).$name_extension."', 8, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '".$cats_layout_before."', '".$cats_layout_after."', '".$cats_notes."', 1, 1, 1, 1, '*', 0)");
                $db->execute();
                $sum_layouts++;

                // Category Standard Layout  (activated by installation as default)
                $cat_layout_before = stripslashes($JLIST_TEMPLATES_CAT_BOOT_BEFORE);
                $cat_layout        = stripslashes($JLIST_TEMPLATES_CAT_BOOT_DEFAULT);
                $cat_layout_after  = stripslashes($JLIST_TEMPLATES_CAT_BOOT_AFTER);
                $cat_header        = stripslashes($cat_boot_header);
                $cat_subheader     = stripslashes($cat_boot_subheader);
                $cat_footer        = stripslashes($cat_boot_footer);
                $cat_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_CAT_DEFAULT_NAME_V41_NOTE'); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_CAT_DEFAULT_NAME_V41')).$name_extension."', 4, '".$cat_layout."', '".$cat_header."', '".$cat_subheader."', '".$cat_footer."', '".$cat_layout_before."', '".$cat_layout_after."', '".$cat_notes."', 1, 1, 1, 1, '*', 0)");
                $db->execute();
                $sum_layouts++;

                // Files/Downloads Standard Layout  (activated by installation as default)
                $files_layout_before = stripslashes($JLIST_TEMPLATES_FILES_BOOT_BEFORE);
                $files_layout        = stripslashes($JLIST_TEMPLATES_FILES_BOOT_DEFAULT);
                $files_layout_after  = stripslashes('');
                $files_header        = stripslashes($file_boot_header);
                $files_subheader     = stripslashes($file_boot_subheader);
                $files_footer        = stripslashes($file_boot_footer);
                $files_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_V41_NOTE'); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, checkbox_off, cols, uses_bootstrap, symbol_off, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_V41')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '".$files_layout_before."', '".$files_layout_after."', '".$files_notes."', 1, 1, 1, 1, 1, 1, '*', 0)");
                $db->execute();
                $sum_layouts++;

                // Files/Downloads Standard Layout with checkboxes (NOT activated by installation)
                $files_layout_before = stripslashes($JLIST_TEMPLATES_FILES_BOOT_BEFORE_2);
                $files_layout        = stripslashes($JLIST_TEMPLATES_FILES_BOOT_DEFAULT_2);
                $files_layout_after  = stripslashes('');
                $files_header        = stripslashes($file_boot_header_2);
                $files_subheader     = stripslashes($file_boot_subheader_2);
                $files_footer        = stripslashes($file_boot_footer_2);
                $files_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_CHECKBOX_V41_NOTE'); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, checkbox_off, cols, uses_bootstrap, symbol_off, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_CHECKBOX_V41')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '".$files_layout_before."', '".$files_layout_after."', '".$files_notes."', 0, 1, 1, 1, 0, 1, '*', 0)");
                $db->execute();
                $sum_layouts++;

                // Download Details Standard Layout  (activated by installation as default)
                $file_layout_before = stripslashes('');
                $file_layout        = stripslashes($JLIST_TEMPLATES_DETAILS_BOOTSTRAP_GRID);
                $file_layout_after  = stripslashes('');
                $file_header        = stripslashes($det_boot_header);
                $file_subheader     = stripslashes($det_boot_subheader);
                $file_footer        = stripslashes($det_boot_footer);
                $file_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_DETAILS_DEFAULT_NAME_V41_NOTE'); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_DETAILS_DEFAULT_NAME_V41')).$name_extension."', 5, '".$file_layout."', '".$file_header."', '".$file_subheader."', '".$file_footer."', '".$file_layout_before."', '".$file_layout_after."', '".$file_notes."', 1, 1, 1, 1, '*', 0)");
                $db->execute();
                $sum_layouts++;
                
                // Summary Standard Layout  (activated by installation as default)
                $sum_layout_before = stripslashes($JLIST_TEMPLATES_SUM_BOOT_BEFORE);
                $sum_layout        = stripslashes($JLIST_TEMPLATES_SUM_BOOT_DEFAULT);
                $sum_layout_after  = stripslashes($JLIST_TEMPLATES_SUM_BOOT_AFTER);
                $sum_header        = stripslashes($sum_boot_header);
                $sum_subheader     = stripslashes($sum_boot_subheader);
                $sum_footer        = stripslashes($sum_boot_footer);
                $sum_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_SUM_DEFAULT_NAME_V41_NOTE'); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_SUM_DEFAULT_NAME_V41')).$name_extension."', 3, '".$sum_layout."', '".$sum_header."', '".$sum_subheader."', '".$sum_footer."', '".$sum_layout_before."', '".$sum_layout_after."', '".$sum_notes."', 1, 1, 1, 1, '*', 0)");
                $db->execute();
                $sum_layouts++;                               
                
                // Now the older layouts for backward compatibility
                
                $name_extension = ' v3.9';

                // Categories Standard Layout  
                $cats_layout       = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_CATS_DEFAULT);
                $cats_header       = stripslashes($cats_header);
                $cats_subheader    = stripslashes($cats_subheader);
                $cats_footer       = stripslashes($cats_footer);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_CATS_DEFAULT_NAME')).$name_extension."', 1, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '', '', '', 0, 1, '*', 1)");
                $db->execute();
                $sum_layouts++;

                // Categories Layout with 4 columns
                $cats_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_CATS_COL_DEFAULT); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, cols, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_CATS_COL_TITLE')).$name_extension."', 1, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '', '', 0, 1, '".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_CATS_COL_NOTE'))."', 4, '*', 2)");
                $db->execute();
                $sum_layouts++;

                // Categories Layout with 2 columns
                $cats_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_CATS_COL2_DEFAULT); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, cols, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_CATS_COL2_TITLE')).$name_extension."', 1, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '', '', 0, 1, '', 2, '*', 3)");
                $db->execute();
                $sum_layouts++;
                                      
                // This layout is used to view the subcategories from a category. 
                $cats_layout        = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SUBCATS_PAGINATION_DEFAULT);
                $cats_layout_before = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SUBCATS_PAGINATION_BEFORE);
                $cats_layout_after  = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SUBCATS_PAGINATION_AFTER);
                $cats_header       = '';
                $cats_subheader    = '';
                $cats_footer       = '';
                $note              = stripslashes(Text::_('COM_JDOWNLOADS_BACKEND_TEMPEDIT_USE_SUBCATS_NOTE'));
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, cols, language, preview_id )  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_CATS_DEFAULT_PAGINATION_NAME')).$name_extension."', 8, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '".$cats_layout_before."', '".$cats_layout_after."', '".$db->escape($note)."', 0, 1, 1, '*', 4)");
                $db->execute();
                $sum_layouts++;

                // This layout is used to view the subcategories from a category in a multi column example. 
                $cats_layout        = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SUBCATS_MULTICOLUMN_DEFAULT);
                $cats_layout_before = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SUBCATS_PAGINATION_BEFORE);
                $cats_layout_after  = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SUBCATS_PAGINATION_AFTER);
                $cats_header       = '';
                $cats_subheader    = '';
                $cats_footer       = '';
                $note              = stripslashes(Text::_('COM_JDOWNLOADS_BACKEND_TEMPEDIT_USE_SUBCATS_NOTE'));
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, cols, language, preview_id )  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_SUBCAT_DEFAULT_NAME')).$name_extension."', 8, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '".$cats_layout_before."', '".$cats_layout_after."', '".$db->escape($note)."', 0, 1, 4, '*', 5)");
                $db->execute();
                $sum_layouts++;
                                      
                // Category Standard Layout 
                $cat_layout       = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_CAT_DEFAULT);
                $cat_header       = stripslashes($cat_header);
                $cat_subheader    = stripslashes($cat_subheader);
                $cat_footer       = stripslashes($cat_footer);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_CAT_DEFAULT_NAME')).$name_extension."', 4, '".$cat_layout."', '".$cat_header."', '".$cat_subheader."', '".$cat_footer."', '', '', '', 0, 1, '*', 6)");
                $db->execute();              
                $sum_layouts++;

                // Files Standard Layout (with mini icons)
                $files_layout       = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT);
                $files_header       = stripslashes($files_header);
                $files_subheader    = stripslashes($files_subheader);
                $files_footer       = stripslashes($files_footer);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_NAME')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 1, 0, '*', 7)");
                $db->execute();
                $sum_layouts++;

                // Files Simple Layout with Checkboxes
                $files_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_NEW_SIMPLE_1); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_NEW_SIMPLE_1_NAME')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 0, 1, '*', 8)");
                $db->execute();
                $sum_layouts++;
                    
                // Files Simple Layout without Checkboxes 
                $files_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_NEW_SIMPLE_2); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_NEW_SIMPLE_2_NAME')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 1, 1, '*', 9)");
                $db->execute();
                $sum_layouts++;

                // Files Layout - Alternate
                $files_layout        = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_NEW_ALTERNATE_1);
                $files_layout_before = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_NEW_ALTERNATE_1_BEFORE);
                $files_layout_after  = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_NEW_ALTERNATE_1_AFTER);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_NEW_ALTERNATE_1_NAME')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '".$files_layout_before."', '".$files_layout_after."', 0, 1, '', 1, 1, '*', 10)");
                $db->execute();
                $sum_layouts++;                            

                // Files Layout with Full Info
                $files_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_FULL_INFO); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_FULL_INFO_NAME')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 1, 1, '*', 11)");
                $db->execute();
                $sum_layouts++;

                // Files Layout - Just a Link
                $files_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_JUST_LINK); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_JUST_LINK_NAME')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 1, 1, '*', 12)");
                $db->execute();
                $sum_layouts++;

                // Files Layout - Single Line
                $files_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_SINGLE_LINE); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_SINGLE_LINE_NAME')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 1, 1, '*', 13)");
                $db->execute();
                $sum_layouts++;

                // Files Layout - Compact with checkboxes v.3.9 (by Colin)
                $files_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_COMPACT_CHECKBOXES); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_COMPACT_NAME_2')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 0, 1, '*', 14)");
                $db->execute();
                $sum_layouts++;

                // Files Layout - Compact with download buttons v.3.9 (by Colin)
                $files_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_FILES_COMPACT_WITHOUT_CHECKBOXES); 
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, checkbox_off, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_COMPACT_NAME_1')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '', '', 0, 1, '', 1, 1, '*', 15)");
                $db->execute();
                $sum_layouts++;

                // Details Standard Layout
                $detail_layout        = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_DETAILS_DEFAULT);
                $details_header       = stripslashes($details_header);
                $details_subheader    = stripslashes($details_subheader);
                $details_footer       = stripslashes($details_footer);               
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_DETAILS_DEFAULT_NAME')).$name_extension."', 5, '$detail_layout', '".$details_header."', '".$details_subheader."', '".$details_footer."', '', '', '', 0, 1, 1, '*', 16)");
                $db->execute();
                $sum_layouts++;

                // Details Layout with Tabs
                $detail_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_DETAILS_DEFAULT_WITH_TABS);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_DETAILS_WITH_TABS_TITLE')).$name_extension."', 5, '$detail_layout', '".$details_header."', '".$details_subheader."', '".$details_footer."', '', '', '', '0', 1, 1, '*', 17)");
                $db->execute();
                $sum_layouts++;

                // Details Layout with all new Data Fields v2.5
                $detail_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_DETAILS_DEFAULT_NEW_25);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_DETAILS_25_TITLE')).$name_extension."', 5, '$detail_layout', '".$details_header."', '".$details_subheader."', '".$details_footer."', '', '', '', '0', 1, 1, '*', 18)");
                $db->execute();
                $sum_layouts++;

                // Details Layout with all new Data Fields (FULL Info with Related) v3.9
                $detail_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_DETAILS_DEFAULT_WITH_RELATED);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, symbol_off, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_DETAILS_WITH_RELATED_TITLE')).$name_extension."', 5, '$detail_layout', '".$details_header."', '".$details_subheader."', '".$details_footer."', '', '', '', '0', 1, 1, '*', 19)");
                $db->execute();
                $sum_layouts++;

                // New details Layout whsh use W3.CSS option v3.9
                $detail_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_DETAILS_DEFAULT_WITH_W3CSS);
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, symbol_off, uses_w3css, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_DETAILS_DEFAULT_WITH_W3CSS_NAME').' v3.9')."', 5, '$detail_layout', '".$details_header."', '".$details_subheader."', '".$details_footer."', '', '', '', '0', 1, 1, 1, '*', 23)");
                $db->execute();
                $sum_layouts++;              

                // Summary Standard Layout
                $summary_layout       = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SUMMARY_DEFAULT);
                $summary_header      = stripslashes($summary_header);
                $summary_subheader    = stripslashes($summary_subheader);
                $summary_footer       = stripslashes($summary_footer);              
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_SUMMARY_DEFAULT_NAME')).$name_extension."', 3, '".$summary_layout."', '".$summary_header."', '".$summary_subheader."', '".$summary_footer."', '', '', '', 0, 1, '*', 20)");
                $db->execute();
                $sum_layouts++;

                // Default search results layout vertical (for internal search function) - take it from $search2_header, $search2_subheader and $search2_footer
                $search_result_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SEARCH_DEFAULT);
                $search_header       = stripslashes($search_header);
                $search_subheader    = stripslashes($search_subheader);
                $search_footer       = stripslashes($search_footer);  
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, cols, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_SEARCH_DEFAULT_NAME')).$name_extension."', 7, '".$search_result_layout."', '".$search_header."', '".$search_subheader."', '".$search_footer."', '', '', 1, 1, '', 4, '*', 21)");
                $db->execute();
                $sum_layouts++;

                // Horizontal search results layout - (for internal search function) - take it from $search2_header, $search2_subheader and $search2_footer
                $search_result_layout = stripslashes($JLIST_BACKEND_SETTINGS_TEMPLATES_SEARCH_DEFAULT_HORIZONTAL);
                $search_header       = stripslashes($search2_header);
                $search_subheader    = stripslashes($search2_subheader);
                $search_footer       = stripslashes($search2_footer);  
                $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, template_active, locked, note, cols, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_SEARCH_DEFAULT2_NAME')).$name_extension."', 7, '".$search_result_layout."', '".$search_header."', '".$search_subheader."', '".$search_footer."', '', '', 0, 1, '', 4, '*', 22)");
                $db->execute();
                $sum_layouts++;                  

                echo '<li><font color="green">'.Text::sprintf('COM_JDOWNLOADS_INSTALL_4', $sum_layouts).'</font></li>';

                // Write default licenses in database      

                $sum_licenses = 7;

                $db->setQuery("INSERT INTO #__jdownloads_licenses (title, alias, description, url, language, published, ordering)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE1_TITLE'))."', '".ApplicationHelper::stringURLSafe(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE1_TITLE'))."', '', '".Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE1_URL')."', '*', 1, 1)");
                $db->execute();

                $db->setQuery("INSERT INTO #__jdownloads_licenses (title, alias, description, url, language, published, ordering)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE2_TITLE'))."', '".ApplicationHelper::stringURLSafe(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE2_TITLE'))."', '', '".Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE2_URL')."', '*', 1, 2)");
                $db->execute();

                $db->setQuery("INSERT INTO #__jdownloads_licenses (title, alias, description, url, language, published, ordering)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE3_TITLE'))."', '".ApplicationHelper::stringURLSafe(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE3_TITLE'))."', '".Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE3_TEXT')."', '', '*', 1, 3)");
                $db->execute();

                $db->setQuery("INSERT INTO #__jdownloads_licenses (title, alias, description, url, language, published, ordering)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE4_TITLE'))."', '".ApplicationHelper::stringURLSafe(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE4_TITLE'))."', '".Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE4_TEXT')."', '', '*', 1, 4)");
                $db->execute();

                $db->setQuery("INSERT INTO #__jdownloads_licenses (title, alias, description, url, language, published, ordering)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE5_TITLE'))."', '".ApplicationHelper::stringURLSafe(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE5_TITLE'))."', '".Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE5_TEXT')."', '', '*', 1, 5)");
                $db->execute();

                $db->setQuery("INSERT INTO #__jdownloads_licenses (title, alias, description, url, language, published, ordering)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE6_TITLE'))."', '".ApplicationHelper::stringURLSafe(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE6_TITLE'))."', '', '', '*', 1, 1)");
                $db->execute();

                $db->setQuery("INSERT INTO #__jdownloads_licenses (title, alias, description, url, language, published, ordering)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE7_TITLE'))."', '".ApplicationHelper::stringURLSafe(Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE7_TITLE'))."', '', '".Text::_('COM_JDOWNLOADS_SETTINGS_LICENSE7_URL')."', '*', 1, 6)");
                $db->execute();

                self::addLog(Text::sprintf('COM_JDOWNLOADS_INSTALL_6', $sum_licenses), 'Log::INFO');

                echo '<li><font color="green">'.Text::sprintf('COM_JDOWNLOADS_INSTALL_6', $sum_licenses).'</font></li>';
          
            // Final checks
          
            // Checked if exist Falang - if yes, move the files

            if (Folder::exists(JPATH_SITE.'/administrator/components/com_falang/contentelements') && !File::exists(JPATH_SITE.'/administrator/components/com_falang/contentelements/jdownloads_files.xml')){
                $fishresult = 1;
                File::copy( JPATH_SITE."/administrator/components/com_jdownloads/assets/falang/jdownloads_categories.xml", JPATH_SITE."/administrator/components/com_falang/contentelements/jdownloads_categories.xml");
                File::copy( JPATH_SITE."/administrator/components/com_jdownloads/assets/falang/jdownloads_files.xml", JPATH_SITE."/administrator/components/com_falang/contentelements/jdownloads_files.xml");
                File::copy( JPATH_SITE."/administrator/components/com_jdownloads/assets/falang/jdownloads_templates.xml", JPATH_SITE."/administrator/components/com_falang/contentelements/jdownloads_templates.xml");
                File::copy( JPATH_SITE."/administrator/components/com_jdownloads/assets/falang/jdownloads_licenses.xml", JPATH_SITE."/administrator/components/com_falang/contentelements/jdownloads_licenses.xml");
                File::copy( JPATH_SITE."/administrator/components/com_jdownloads/assets/falang/jdownloads_usergroups_limits.xml", JPATH_SITE."/administrator/components/com_falang/contentelements/jdownloads_usergroups_limits.xml");
                Folder::delete( JPATH_SITE."/administrator/components/com_jdownloads/assets/falang"); 
            } else { 
                $fishresult = 0;
            }               
          
            if ($fishresult) {
                self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_17')." ".JPATH_SITE.'/administrator/components/com_falang/contentelements', 'Log::INFO');
                echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_17')." ".JPATH_SITE.'/administrator/components/com_falang/contentelements'.'</font></li>';
            } else {
                self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_18')." ".JPATH_SITE.'/administrator/components/com_jdownloads/assets/falang'.'<br />'.Text::_('COM_JDOWNLOADS_INSTALL_19'), 'Log::INFO');
                echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_18')." ".JPATH_SITE.'/administrator/components/com_jdownloads/assets/falang'.'<br />'.Text::_('COM_JDOWNLOADS_INSTALL_19').'</font></li>';
            }        
    
            // Check if the default upload directory exists 
            $dir_exist = Folder::exists($jd_upload_root);
            
            if ($dir_exist) {
                if (is_writable($jd_upload_root)) {
                    // Exist and is writable!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_7'), 'Log::INFO');
                    echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_7').'</font></li>';
                } else {
                    // Exist but is NOT writable!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_8'), 'Log::INFO');
                    echo '<li><font color="red"><strong>'.Text::_('COM_JDOWNLOADS_INSTALL_8').'</strong></font></li>';
                }
            } else {
                // Try to create it
                if ($makedir =  Folder::create($jd_upload_root, 0755)) {
                    // Succesful created
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_9'), 'Log::INFO');
                    echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_9').'</font></li>';
                } else {
                    // Could not create the folder!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_10'), 'Log::INFO');
                    echo '<li><font color="red"><strong>'.Text::_('COM_JDOWNLOADS_INSTALL_10').'</strong></font></li>'; 
                }
            }
            
            // Check if the default 'preview files' directory exists
            $dir_exist_preview = Folder::exists($jd_upload_root.'/_preview_files');

            if ($dir_exist_preview) {
                if (is_writable($jd_upload_root.'/_preview_files')) {
                    // Exist and is writable!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_30'), 'Log::INFO');
                    echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_30').'</font></li>';
                } else {
                    // Exist but is NOT writable!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_31'), 'Log::INFO');
                    echo '<li><font color="red"><strong>'.Text::_('COM_JDOWNLOADS_INSTALL_31').'</strong></font></li>';
                }
            } else {
                if ($makedir =  Folder::create($jd_upload_root.'/_preview_files', 0755)) {
                    // Succesful created
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_28'), 'Log::INFO');
                    echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_28').'</font></li>';
                } else {
                    // Could not create the folder!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_29'), 'Log::INFO');
                    echo '<li><font color="red"><strong>'.Text::_('COM_JDOWNLOADS_INSTALL_29').'</strong></font></li>';
                }
            }            
            
            // Check if the default directory for the 'temporary files' (tempzipfiles) exist
            $dir_existzip = Folder::exists($jd_upload_root.'/_tempzipfiles');

            if ($dir_existzip) {
                if (is_writable($jd_upload_root.'/_tempzipfiles')) {
                    // Exist and is writable!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_11'), 'Log::INFO');
                    echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_11').'</font></li>';
                } else {
                    // Exist but is NOT writable!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_12'), 'Log::INFO');
                    echo '<li><font color="red"><strong>'.Text::_('COM_JDOWNLOADS_INSTALL_12').'</strong></font></li>';
                }
            } else {
                if ($makedir = Folder::create($jd_upload_root.'/_tempzipfiles/', 0755)) {
                    // Succesful created
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_13'), 'Log::INFO');
                    echo '<li><font color="green">'.Text::_('COM_JDOWNLOADS_INSTALL_13').'</font></li>';
                } else {
                    // Could not create the folder!
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_14'), 'Log::INFO');
                    echo '<li><font color="red"><strong>'.Text::_('COM_JDOWNLOADS_INSTALL_14').'</strong></font></li>';
                }
            }
       
        echo '</ul>';
        
        // Create the dashboard module
        // $this->addDashboardMenu('jDownloads', 'jdownloads');
        
        // Display finaly the results from the extension installation
        
        $rows = 0;
        ?>                           
        
        </div>
        <hr>

        <table class="adminlist" style="width: 100%; margin:10px 10px 10px 10px;">
            <thead>
                <tr>
                    <th class="title" style="text-align:left;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_EXTENSION'); ?></th>
                    <th style="width: 50%; text-align:center;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_STATUS'); ?></th>
                </tr>
            </thead>
            <tbody>
                <?php if (count($status->modules)) : ?>
                <tr>
                    <th style="text-align:left;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_MODULE'); ?></th>
                </tr>
                <?php foreach ($status->modules as $module) : ?>
                <tr class="row<?php echo (++ $rows % 2); ?>">
                    <td class="key"><?php echo $module['name']; ?></td>
                    <td style="text-align:center;"><?php echo ($module['result'])?Text::_('COM_JDOWNLOADS_INSTALL_INSTALLED'):Text::_('COM_JDOWNLOADS_INSTALL_NOT_INSTALLED'); ?></td>
                </tr>
                <?php endforeach;?>
                <?php endif;?>
                <?php if (count($status->plugins)) : ?>
                <tr>
                    <th style="text-align:left;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_PLUGIN'); ?></th>
                </tr>
                <?php foreach ($status->plugins as $plugin) : ?>
                <tr class="row<?php echo (++ $rows % 2); ?>">
                    <td class="key"><?php echo ucfirst($plugin['name']); ?></td>
                    <td style="text-align:center;"><?php echo ($plugin['result'])?Text::_('COM_JDOWNLOADS_INSTALL_INSTALLED'):Text::_('COM_JDOWNLOADS_INSTALL_NOT_INSTALLED'); ?></td>
                </tr>
                <?php endforeach; ?>
                <?php endif; ?>
            </tbody>
        </table>
        <?php
        }
	}
 
	/**
	 * Method to uninstall the component
	 *
	 * @return void
	 */
	public function uninstall($parent) 
	{
        $db       = Factory::getContainer()->get(DatabaseInterface::class);
        $app      = Factory::getApplication();
        $session  = Factory::getApplication()->getSession();
        
        $params = ComponentHelper::getParams('com_jdownloads');
        
        $uninstall_options_results = array();
        
        $del_images = $session->get('del_jd_images', -1);
        $del_files  = $session->get('del_jd_files', -1);
        $del_tables = $session->get('del_jd_tables', -1);
        
        if ($del_images == -1 && $del_files == -1 && $del_tables == -1){
            // Move the user to the uninstall options page 
            $app->redirect(Route::_('index.php?option=com_jdownloads&view=uninstall', false));
            exit;
        }        
        
        $status = new \stdClass();
        $status->modules = array();
        $status->plugins = array();
        $src = $src = dirname(__FILE__);

        // Top Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_top" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Top Module','client'=>'site', 'result'=>$result);
        }

        // Uninstall the Latest Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_latest" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Latest Module','client'=>'site', 'result'=>$result);
        }

        // Uninstall the Last Upadated Downloads Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_last_updated" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Last Updated Module','client'=>'site', 'result'=>$result);
        }        

        // Uninstall the Most Recently Downloaded Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_most_recently_downloaded" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Most Recently Downloaded Module','client'=>'site', 'result'=>$result);
        }  
        
        // Uninstall the Frontend Stats Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_stats" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Stats Module','client'=>'site', 'result'=>$result);
        }        
        
        // Uninstall the Tree Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_tree" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Tree Module','client'=>'site', 'result'=>$result);
        }        

        // Uninstall the Related Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_related" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Related Module','client'=>'site', 'result'=>$result);
        } 

        // Uninstall the Rated Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_rated" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Rated Module','client'=>'site', 'result'=>$result);
        }

        // Uninstall the View Limits Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_view_limits" AND `type` = "module"');
        $id = $db->loadResult();
        if($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads View Limits Module','client'=>'site', 'result'=>$result);
        }         
        
        // Uninstall the Featured Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_featured" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Featured Module','client'=>'site', 'result'=>$result);
        }
        
        // Uninstall the Admin Stats Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_admin_stats" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Admin Stats Module','client'=>'admin', 'result'=>$result);
        }

        // Uninstall the Admin Monitoring Module
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `element` = "mod_jdownloads_admin_monitoring" AND `type` = "module"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('module',$id,1);
            $status->modules[] = array('name'=>'jDownloads Admin Monitoring Module','client'=>'admin', 'result'=>$result);
        }
        
        // Uninstall the System Plugin
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `name` = "plg_system_jdownloads" AND `folder` = "system"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads System Plugin','group'=>'system', 'result'=>$result);
        }

        // Uninstall the old Search Plugin - not more supported in Joomla 4
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `name` = "plg_search_jdownloads" AND `folder` = "search"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Search Plugin','group'=>'search', 'result'=>$result);
        }        
        
        // Uninstall the Example Plugin
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `element` = "example" AND `folder` = "jdownloads"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Example Plugin','group'=>'jdownloads', 'result'=>$result);
        }
        
        // Uninstall the Button Plugin Download Link
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `element` = "downloadlink" AND `folder` = "editors-xtd"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Download Link Button Plugin','group'=>'editors-xtd', 'result'=>$result);
        }        		

        // Uninstall the Button Plugin Download Content
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `element` = "jdownloads" AND `folder` = "editors-xtd"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Download Content Button Plugin','group'=>'editors-xtd', 'result'=>$result);
        } 
		
        // Uninstall the Content Plugin
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `name` = "plg_content_jdownloads" AND `folder` = "content"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Content Plugin','group'=>'content', 'result'=>$result);
        }

        // Uninstall the Finder Plugin for Downloads
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `name` = "plg_finder_jdownloads" AND `folder` = "finder"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Finder Plugin','group'=>'finder', 'result'=>$result);
        }

        // Uninstall the Finder Plugin for Categories
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `name` = "plg_finder_folder" AND `folder` = "finder"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Finder Category Plugin','group'=>'finder', 'result'=>$result);
        }
        
        // Actionlog Plugin
        /* $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `name` = "plg_actionlog_jdownloads" AND `folder` = "actionlog"');
        $id = $db->loadResult();
        if($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Actionlog Plugin','group'=>'actionlog', 'result'=>$result);
        }
        */
		
		// Uninstall the Content Plugin 'Tags Fix'
        $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `name` = "plg_content_jdownloads_tags_fix" AND `folder` = "content"');
        $id = $db->loadResult();
        if ($id)
        {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
            $status->plugins[] = array('name'=>'jDownloads Content Tags Fix Plugin','group'=>'content', 'result'=>$result);
        }

        // Check Uninstall type from Session 
        
        // Use special font colors for some situations/options in results messages 
         
        if ($del_images == '0'){
            
            // We shall remove jDownloads completely
            
            // Delete the image folders
            $path = JPATH_ROOT.'/images/jdownloads';
            if (Folder::exists($path)){
                if (Folder::delete($path)){
                    // Add message for succesful action
                    $uninstall_options_results[] = '<p align="center"><b><span style="color:#00CC00">'.Text::_('COM_JDOWNLOADS_UNINSTALL_IMAGES_DELETED').'</b></p>';
                } else {
                    // Add message for not succesful action
                    $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF0000">'.Text::_('COM_JDOWNLOADS_UNINSTALL_IMAGES_NOT_DELETED').'</b></p>';
                }
            } else {
                // Folder not found
                $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF0000">Image folder not found!</b></p>';
            }
        } else {
            $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF8040">'.Text::_('COM_JDOWNLOADS_UNINSTALL_IMAGES_NOT_SELECTED').'</b></p>';
        }
            
        if ($del_files == '0'){            
            
            // Delete upload the upload folder with all files (Downloads)
            $path = $params->get('files_uploaddir');

            if ($path && Folder::exists($path)){
                if (Folder::delete($path)){
                    // Add message for succesful action
                    $uninstall_options_results[] = '<p align="center"><b><span style="color:#00CC00">'.Text::_('COM_JDOWNLOADS_UNINSTALL_FILES_DELETED').'</b></p>';
                } else {
                    // Add message for not succesful action
                    $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF0000">'.Text::_('COM_JDOWNLOADS_UNINSTALL_FILES_NOT_DELETED').'</b></p>';
                }
            } else {
                // Folder not found
                $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF0000">Upload folder not found!</b></p>';
            }
        } else {
            $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF8040">'.Text::_('COM_JDOWNLOADS_UNINSTALL_FILES_NOT_SELECTED').'</b></p>';
        }
        
        if ($del_tables == '0'){            
            
            // Delete all database tables 
            $db->setQuery('DROP TABLE IF EXISTS #__jdownloads_categories, #__jdownloads_files, #__jdownloads_licenses, #__jdownloads_logs, #__jdownloads_ratings, #__jdownloads_templates, #__jdownloads_usergroups_limits');
            $result = $db->execute();
            if ($result === true){
                // Add message for succesful action
                $uninstall_options_results[] = '<p align="center"><b><span style="color:#00CC00">'.Text::_('COM_JDOWNLOADS_UNINSTALL_TABLES_DELETED').'</b></p>';
            } else {
                // Add message for not succesful action
                $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF0000">'.Text::_('COM_JDOWNLOADS_UNINSTALL_TABLES_NOT_DELETED').'</b></p>';
            }
            
            // We now also remove all permission data in the asset table, if necessary - but is a complete restore still possible with
            // the help of a jDownloads data backup? Should be tested and possibly corrected if necessary.
            $db->setQuery('DELETE FROM #__assets WHERE name LIKE '.$db->quote('%com_jdownloads%'));
            $result = $db->execute();
            
        } else {
            $uninstall_options_results[] = '<p align="center"><b><span style="color:#FF8040">'.Text::_('COM_JDOWNLOADS_UNINSTALL_TABLES_NOT_SELECTED').'</b></p>';
        }
        
        $session->set('del_jd_images', -1);
        $session->set('del_jd_files',  -1);
        $session->set('del_jd_tables', -1);
        
        $msg = '<h4>'.Text::_('COM_JDOWNLOADS_DEINSTALL_0').'</h4><hr>';
        foreach ($uninstall_options_results as $result){
            $msg .= $result; 
        }
        $msg .= '<hr>';
                
        $msg .= '       
        <table class="adminlist" width="100%">
            <thead>
                <tr>
                    <th class="title" style="text-align:left;">'.Text::_('COM_JDOWNLOADS_INSTALL_EXTENSION').'</th>
                    <th style="width:50%; text-align:center;">'.Text::_('COM_JDOWNLOADS_INSTALL_STATUS').'</th>
                </tr>
            </thead>
            <tbody>
                <tr class="row0">
                    <td class="key">'.Text::_('COM_JDOWNLOADS_INSTALL_COMPONENT').' '.Text::_('COM_JDOWNLOADS_INSTALL_JDOWNLOADS').'</td>
                    <td style="text-align:center;">'.Text::_('COM_JDOWNLOADS_DEINSTALL_REMOVED').'</td>
                </tr>';

        if (count($status->modules)){
            $msg .=
            '<tr>
                <th style="text-align:left;">'.Text::_('COM_JDOWNLOADS_INSTALL_MODULE').'</th>
            </tr>';
        
            foreach ($status->modules as $module) {
                $msg .= 
                '<tr class="">
                <td class="key">'.$module['name'].'</td>
                <td style="text-align:center">';
                if ($module['result']){
                    $msg .= Text::_('COM_JDOWNLOADS_DEINSTALL_REMOVED').'</td></tr>';
                }else {
                    $msg .= Text::_('COM_JDOWNLOADS_DEINSTALL_NOT_REMOVED').'</td></tr>';
                }
            }
        }

        if (count($status->plugins)){
            $msg .=
            '<tr>
                <th style="text-align:left;">'.Text::_('COM_JDOWNLOADS_INSTALL_PLUGIN').'</th>
            </tr>';
            foreach ($status->plugins as $plugin){
                $msg .=
                '<tr class="">
                    <td class="key">'.ucfirst($plugin['name']).'</td>
                    <td style="text-align:center;">';
                if ($plugin['result']){
                    $msg .= Text::_('COM_JDOWNLOADS_DEINSTALL_REMOVED').'</td></tr>';
                }else {
                    $msg .= Text::_('COM_JDOWNLOADS_DEINSTALL_NOT_REMOVED').'</td></tr>';
                }
            }
        }
        $msg .=
            '</tbody>
        </table>
        <hr>';
        echo $msg;
        $session->set('jd_uninstall_msg', $msg);
	}
 
	/**
	 * Method to update the component
     * 
     * We can update only from a 4.0 series
	 * ====================================
     * 
	 * @return void
	 */
	public function update($parent) 
	{
        // Try to set time limit
        @set_time_limit(0);

        // Try to increase memory limit
        if ((int) ini_get( 'memory_limit' ) < 32){
            @ini_set( 'memory_limit', '32M' );
        }
        
        $user = Factory::getApplication()->getIdentity();
        $db   = Factory::getContainer()->get(DatabaseInterface::class);
        $params = ComponentHelper::getParams('com_jdownloads');
        
        // Currently we do not support the option to hide empty categories. This must first be overworked in the future.
        // So it must always be activated
        $params->set('view_empty_categories', 1);

        $prefix = self::getCorrectDBPrefix();
        $tablelist = $db->getTableList();

        // Add a log entry
        self::addLog(Text::sprintf('COM_JDOWNLOADS_UPDATE_LOG_START', $user->id, $user->name, $this->old_version_short, $this->new_version), 'Log::INFO');
        
        $rows = 0;
        $amount_mod = 0;
        $amount_plg = 0;

        $status = new \stdClass();
        $status->modules = array();
        $status->plugins = array();
        
        $src_modules = dirname(__FILE__).'/modules';
        $src_plugins = dirname(__FILE__).'/plugins';
        
        // We must install again all modules and plugins since it can be that we must also install here an update
        
        // Update Modules
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_latest');
        $status->modules[] = array('name'=>'jDownloads Latest Module','client'=>'site', 'result'=>$result);
        if ($result) $amount_mod ++;

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_top');
        $status->modules[] = array('name'=>'jDownloads Top Module','client'=>'site', 'result'=>$result);
        if ($result) $amount_mod ++;

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_last_updated');
        $status->modules[] = array('name'=>'jDownloads Last Updated Module','client'=>'site', 'result'=>$result);
        if ($result) $amount_mod ++;

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_most_recently_downloaded');
        $status->modules[] = array('name'=>'jDownloads Most Recently Downloaded Module','client'=>'site', 'result'=>$result);
        if ($result) $amount_mod ++;
        
        $installer = new Installer;                                                                                     
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_stats');
        $status->modules[] = array('name'=>'jDownloads Stats Module','client'=>'site', 'result'=>$result);        
        if ($result) $amount_mod ++;

        $installer = new Installer;                                                                                     
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_tree');
        $status->modules[] = array('name'=>'jDownloads Tree Module','client'=>'site', 'result'=>$result);         
        if ($result) $amount_mod ++;

        $installer = new Installer;                                                                                     
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_related');
        $status->modules[] = array('name'=>'jDownloads Related Module','client'=>'site', 'result'=>$result);        
        if ($result) $amount_mod ++;

        $installer = new Installer;                                                                                     
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_rated');
        $status->modules[] = array('name'=>'jDownloads Rated Module','client'=>'site', 'result'=>$result);
        if ($result) $amount_mod ++;
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_featured');
        $status->modules[] = array('name'=>'jDownloads Featured Module','client'=>'site', 'result'=>$result);
        if ($result) $amount_mod ++;

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_view_limits');
        $status->modules[] = array('name'=>'jDownloads View Limits Module','client'=>'site', 'result'=>$result);
        if ($result) $amount_mod ++;
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_admin_stats');
        $status->modules[] = array('name'=>'jDownloads Admin Stats Module','client'=>'admin', 'result'=>$result);
        if ($result) $amount_mod ++;

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_modules.'/mod_jdownloads_admin_monitoring');
        $status->modules[] = array('name'=>'jDownloads Admin Monitoring Module','client'=>'admin', 'result'=>$result);
        if ($result) $amount_mod ++;
        
        self::addLog(Text::sprintf('COM_JDOWNLOADS_UPDATE_LOG_MODS_INSTALLED_UPDATED', $amount_mod), 'Log::INFO');
        
        // Update Plugins
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_system_jdownloads');
        $status->plugins[] = array('name'=>'jDownloads System Plugin','group'=>'system', 'result'=>$result);
        if ($result) $amount_plg ++;
                
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/editor_button_plugin_jdownloads_downloads');
        $status->plugins[] = array('name'=>'jDownloads Download Content Button Plugin','group'=>'editors-xtd', 'result'=>$result);               
        if ($result) $amount_plg ++;

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_content_jdownloads');
        $status->plugins[] = array('name'=>'jDownloads Content Plugin','group'=>'content', 'result'=>$result);               
        if ($result) $amount_plg ++;

        /* $installer = new Installer;
        $result = $installer->install($src_plugins.'/plg_jdownloads_example');
        $status->plugins[] = array('name'=>'jDownloads Example Plugin','group'=>'jdownloads', 'result'=>$result);
        if ($result) $amount_plg ++;
        */
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_finder_jdownloads');
        $status->plugins[] = array('name'=>'jDownloads Finder Plugin','group'=>'finder', 'result'=>$result);
        if ($result) $amount_plg ++;

        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_finder_folder');
        $status->plugins[] = array('name'=>'jDownloads Finder Category Plugin','group'=>'finder', 'result'=>$result);
        if ($result) $amount_plg ++;
        
        $installer = new Installer;
        $installer->setDatabase($db);
        $result = $installer->install($src_plugins.'/plg_content_jdownloads_tags_fix');
        $status->plugins[] = array('name'=>'jDownloads Content Tags Fix Plugin','group'=>'content', 'result'=>$result);
        if ($result) $amount_plg ++;
        
		// Tags fix plugin must be enabled 
        $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `name` = 'plg_content_jdownloads_tags_fix' AND `type` = 'plugin'");
        $db->execute();		
        
        // Delete old tags fix plugin from 3.2 when exist - 
        // Removed in 4.0 as we deinstall here the new installed 4.0 plugin instead to delete correct the old one. The element identifier is here wrong.
        /* $db->setQuery('SELECT `extension_id` FROM #__extensions WHERE `type` = "plugin" AND `element` = "jdownloads_tags_fix" AND `folder` = "content"');
        $id = $db->loadResult();
        if ($id) {
            $installer = new Installer;
            $installer->setDatabase($db);
            $result = $installer->uninstall('plugin',$id,1);
        } */

        self::addLog(Text::sprintf('COM_JDOWNLOADS_UPDATE_LOG_PLGS_INSTALLED_UPDATED', $amount_plg), 'Log::INFO');
        
        echo '<h4 style="color:#555;">' . Text::_('COM_JDOWNLOADS_UPDATE_TEXT') . '</h4>';
        
        if (count($status->modules) || count($status->plugins)){
            ?>    
            <hr>
            <table class="adminlist" style="width:100%; margin:10px 10px 10px 10px;">
                <thead>
                    <tr>
                        <th class="title" style="text-align:left;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_EXTENSION'); ?></th>
                        <th style="width:50%; text-align:center;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_STATUS'); ?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php if (count($status->modules)) : ?>
                    <tr>
                        <th style="text-align:left;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_MODULE'); ?></th>
                    </tr>
                    <?php foreach ($status->modules as $module) : ?>
                    <tr class="row<?php echo (++ $rows % 2); ?>">
                        <td class="key"><?php echo $module['name']; ?></td>
                        <td style="text-align:center;"><?php echo ($module['result'])?Text::_('COM_JDOWNLOADS_INSTALL_INSTALLED'):Text::_('COM_JDOWNLOADS_INSTALL_NOT_INSTALLED'); ?></td>
                    </tr>
                    <?php endforeach;?>
                    <?php endif;?>
                    <?php if (count($status->plugins)) : ?>
                    <tr>
                        <th style="text-align:left;"><?php echo Text::_('COM_JDOWNLOADS_INSTALL_PLUGIN'); ?></th>
                    </tr>
                    <?php foreach ($status->plugins as $plugin) : ?>
                    <tr class="row<?php echo (++ $rows % 2); ?>">
                        <td class="key"><?php echo ucfirst($plugin['name']); ?></td>
                        <td style="text-align:center;"><?php echo ($plugin['result'])?Text::_('COM_JDOWNLOADS_INSTALL_INSTALLED'):Text::_('COM_JDOWNLOADS_INSTALL_NOT_INSTALLED'); ?></td>
                    </tr>
                    <?php endforeach; ?>
                    <?php endif; ?>
                </tbody>
            </table>            
            <?php            
        }
        
        // When updating to version 4.1 for the first time (from v4.0.49), the new bootstrap layouts must be added.
        // Unlike a new installation, however, we should not activate these, as the user is already using the old layouts
        // and would like to continue using them. They can then activate the new layouts if they wish.
                
        $db->setQuery("SELECT COUNT(*) FROM #__jdownloads_templates WHERE template_name LIKE " . $db->quote('%v4.1%') . " AND `locked` = 1 AND `uses_bootstrap` = 1");
        $exists = $db->loadResult();

        if ($exists == 0)
        {
            // We must add the new bootstrap layouts for version 4.1
     
            require_once (JPATH_ADMINISTRATOR.'/components/com_jdownloads/src/Helper/JDownloadsHelper.php');
            require_once (JPATH_ADMINISTRATOR.'/components/com_jdownloads/src/Helper/StandardLayouts.php');
            
            $sum_layouts = 0;
            $name_extension = ' v4.1';

            // Categories Standard Layout  
            $cats_layout_before = stripslashes($JLIST_TEMPLATES_BOOT_CATS_DEFAULT_BEFORE);
            $cats_layout        = stripslashes($JLIST_TEMPLATES_BOOT_CATS_DEFAULT);
            $cats_layout_after  = stripslashes($JLIST_TEMPLATES_BOOT_CATS_DEFAULT_AFTER);
            $cats_header        = stripslashes($cats_header_boot);
            $cats_subheader     = stripslashes($cats_subheader_boot);
            $cats_footer        = stripslashes($cats_footer_boot);
            $cats_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_CATS_DEFAULT_NAME_V41_NOTE'); 
            $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_CATS_DEFAULT_NAME_V41')).$name_extension."', 1, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '".$cats_layout_before."', '".$cats_layout_after."', '".$cats_notes."', 1, 1, 0, 1, '*', 0)");
            $db->execute();
            $sum_layouts++;

            // Sub Categories Standard Layout  
            $cats_layout_before = stripslashes($JLIST_TEMPLATES_SUBCATS_BOOT_PAGINATION_BEFORE);
            $cats_layout        = stripslashes($JLIST_TEMPLATES_SUBCATS_BOOT_PAGINATION_DEFAULT);
            $cats_layout_after  = stripslashes($JLIST_TEMPLATES_SUBCATS_BOOT_PAGINATION_AFTER);
            $cats_header        = stripslashes('');
            $cats_subheader     = stripslashes('');
            $cats_footer        = stripslashes('');
            $cats_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_SUBCATS_DEFAULT_NAME_V41_NOTE'); 
            $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_SUBCATS_DEFAULT_NAME_V41')).$name_extension."', 8, '".$cats_layout."', '".$cats_header."', '".$cats_subheader."', '".$cats_footer."', '".$cats_layout_before."', '".$cats_layout_after."', '".$cats_notes."', 1, 1, 0, 1, '*', 0)");
            $db->execute();
            $sum_layouts++;

            // Category Standard Layout  
            $cat_layout_before = stripslashes($JLIST_TEMPLATES_CAT_BOOT_BEFORE);
            $cat_layout        = stripslashes($JLIST_TEMPLATES_CAT_BOOT_DEFAULT);
            $cat_layout_after  = stripslashes($JLIST_TEMPLATES_CAT_BOOT_AFTER);
            $cat_header        = stripslashes($cat_boot_header);
            $cat_subheader     = stripslashes($cat_boot_subheader);
            $cat_footer        = stripslashes($cat_boot_footer);
            $cat_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_CAT_DEFAULT_NAME_V41_NOTE'); 
            $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_CAT_DEFAULT_NAME_V41')).$name_extension."', 4, '".$cat_layout."', '".$cat_header."', '".$cat_subheader."', '".$cat_footer."', '".$cat_layout_before."', '".$cat_layout_after."', '".$cat_notes."', 1, 1, 0, 1, '*', 0)");
            $db->execute();
            $sum_layouts++;

            // Files/Downloads Standard Layout
            $files_layout_before = stripslashes($JLIST_TEMPLATES_FILES_BOOT_BEFORE);
            $files_layout        = stripslashes($JLIST_TEMPLATES_FILES_BOOT_DEFAULT);
            $files_layout_after  = stripslashes('');
            $files_header        = stripslashes($file_boot_header);
            $files_subheader     = stripslashes($file_boot_subheader);
            $files_footer        = stripslashes($file_boot_footer);
            $files_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_V41_NOTE'); 
            $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, checkbox_off, cols, uses_bootstrap, symbol_off, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_V41')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '".$files_layout_before."', '".$files_layout_after."', '".$files_notes."', 1, 1, 1, 1, 0, 1, '*', 0)");
            $db->execute();
            $sum_layouts++;

            // Files/Downloads Standard Layout with checkboxes 
            $files_layout_before = stripslashes($JLIST_TEMPLATES_FILES_BOOT_BEFORE_2);
            $files_layout        = stripslashes($JLIST_TEMPLATES_FILES_BOOT_DEFAULT_2);
            $files_layout_after  = stripslashes('');
            $files_header        = stripslashes($file_boot_header_2);
            $files_subheader     = stripslashes($file_boot_subheader_2);
            $files_footer        = stripslashes($file_boot_footer_2);
            $files_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_CHECKBOX_V41_NOTE'); 
            $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, checkbox_off, cols, uses_bootstrap, symbol_off, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_FILES_DEFAULT_NAME_CHECKBOX_V41')).$name_extension."', 2, '".$files_layout."', '".$files_header."', '".$files_subheader."', '".$files_footer."', '".$files_layout_before."', '".$files_layout_after."', '".$files_notes."', 0, 1, 1, 1, 0, 1, '*', 0)");
            $db->execute();
            $sum_layouts++;

            // Downloads Details Standard Layout  
            $file_layout_before = stripslashes('');
            $file_layout        = stripslashes($JLIST_TEMPLATES_DETAILS_BOOTSTRAP_GRID);
            $file_layout_after  = stripslashes('');
            $file_header        = stripslashes($det_boot_header);
            $file_subheader     = stripslashes($det_boot_subheader);
            $file_footer        = stripslashes($det_boot_footer);
            $file_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_DETAILS_DEFAULT_NAME_V41_NOTE'); 
            $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_DETAILS_DEFAULT_NAME_V41')).$name_extension."', 5, '".$file_layout."', '".$file_header."', '".$file_subheader."', '".$file_footer."', '".$file_layout_before."', '".$file_layout_after."', '".$file_notes."', 1, 1, 0, 1, '*', 0)");
            $db->execute();
            $sum_layouts++;
            
            // Summary Standard Layout 
            $sum_layout_before = stripslashes($JLIST_TEMPLATES_SUM_BOOT_BEFORE);
            $sum_layout        = stripslashes($JLIST_TEMPLATES_SUM_BOOT_DEFAULT);
            $sum_layout_after  = stripslashes($JLIST_TEMPLATES_SUM_BOOT_AFTER);
            $sum_header        = stripslashes($sum_boot_header);
            $sum_subheader     = stripslashes($sum_boot_subheader);
            $sum_footer        = stripslashes($sum_boot_footer);
            $sum_notes         = Text::_('COM_JDOWNLOADS_TEMPLATES_SUM_DEFAULT_NAME_V41_NOTE'); 
            $db->setQuery("INSERT INTO #__jdownloads_templates (template_name, template_typ, template_text, template_header_text, template_subheader_text, template_footer_text, template_before_text, template_after_text, note, cols, uses_bootstrap, template_active, locked, language, preview_id)  VALUES ('".$db->escape(Text::_('COM_JDOWNLOADS_TEMPLATES_SUM_DEFAULT_NAME_V41')).$name_extension."', 3, '".$sum_layout."', '".$sum_header."', '".$sum_subheader."', '".$sum_footer."', '".$sum_layout_before."', '".$sum_layout_after."', '".$sum_notes."', 1, 1, 0, 1, '*', 0)");
            $db->execute();
            $sum_layouts++; 
            
            self::addLog('New layouts from jDownloads 4.1 successfully added to the database.', 'Log::INFO');
        
        }
        
    }
 
	/**
	 * Method to run before an install/update/
     * 
	 * @return void
	 */
	public function preflight($type, $parent) 
	{
        $parent   = $parent->getParent();
        $source   = $parent->getPath("source");
        $manifest = $parent->get("manifest");
        $db       = Factory::getContainer()->get(DatabaseInterface::class);
        $session  = Factory::getApplication()->getSession();        
        
        $pos = strpos($manifest->version, ' ');
        if ($pos){
            $this->new_version_short     = substr($manifest->version, 0, $pos);
        } else {
            $this->new_version_short     = $manifest->version;
        }    
        $this->new_version              = (string)$manifest->version;
        $this->target_joomla_version    = (string)$manifest->targetjoomla;
        $this->requiredForUpgrade       = (string)$manifest->required_for_upgrade;
        $this->minimum_databases        = (string)$manifest->minimum_databases;
        
        // Add a log entry - with basic system information at first
        self::addLog('', 'Log::INFO', true);                
        
        if ( $type == 'install'){     
            self::addLog('------------------------------------------------------ Installation Started', '');                
        }
        if ( $type == 'update'){     
            self::addLog('------------------------------------------------------ Update Started', '');                
        }
        
        $prefix = self::getCorrectDBPrefix();
        $tablelist = $db->getTableList();
        
        if ( $type == 'install' || $type == 'update' ) {
            // This component does only work with Joomla release 5.0 or higher - otherwise abort
            $jversion     = new Version();
            $jversion_value = $jversion->getShortVersion();
        
            if (!$jversion->isCompatible($this->target_joomla_version)) {
                // Is not the required joomla target version - Abort!
                Factory::getApplication()->enqueueMessage( Text::_('COM_JDOWNLOADS_INSTALL_WRONG_JOOMLA_RELEASE'), 'warning');
                return false;
            }
         
            if ( $type == 'update' ) {
                $component_header = Text::_('COM_JDOWNLOADS_DESCRIPTION');
                $typetext = Text::_('COM_JDOWNLOADS_INSTALL_TYPE_UPDATE');
                $db->setQuery('SELECT * FROM #__extensions WHERE `element` = "com_jdownloads" AND `type` = "component"');
                $item = $db->loadObject();
                $old_manifest = json_decode($item->manifest_cache); 
                $pos = strpos($old_manifest->version, ' ');
                if ($pos){
                    $this->old_version_short = substr($old_manifest->version, 0, $pos);    
                } else {
                    $this->old_version_short = $old_manifest->version;    
                } 
                
                // Build the versions text information for the finaly update message.
                $rel = $this->old_version_short . ' to ' . $this->new_version;

                if ( !version_compare($this->new_version_short, $this->old_version_short, '>=' ) ) {
                    self::addLog(Text::_('COM_JDOWNLOADS_UPDATE_ERROR_INCORRECT_VERSION').' '.$rel, 'Log::WARNING');                
                    // Abort if the release being installed is not newer (or equal) than the currently installed jDownloads version
                    Factory::getApplication()->enqueueMessage(Text::_('COM_JDOWNLOADS_UPDATE_ERROR_INCORRECT_VERSION').' '.$rel, 'warning');
                    return false;
                }
                
                // Enforce minimum required version for update to 4.1.
                if ($this->requiredForUpgrade !== '' && version_compare($this->old_version_short, $this->requiredForUpgrade, '<')) {
                    $msg = Text::_('COM_JDOWNLOADS_UPDATE_ERROR_INCORRECT_VERSION') . ' ' . $rel . '. ' .
                        'Required for update: ' . $this->requiredForUpgrade . ' or newer.';
                    self::addLog($msg, 'Log::WARNING');
                    Factory::getApplication()->enqueueMessage($msg, 'warning');
                    return false;
                }

            } else {
                
                // Only if $type == 'install'
                // Build the text information for the finaly installation message (no update!).
                $component_header = Text::_('COM_JDOWNLOADS_DESCRIPTION');
                $typetext =  Text::_('COM_JDOWNLOADS_INSTALL_TYPE_INSTALL');
                $rel = $this->new_version; 
            }

            $install_msg = '<p><b>'.$component_header.'</b></p>
                            <p>'.$typetext.' '.Text::_('COM_JDOWNLOADS_INSTALL_VERSION').' '.$rel.'</p>';

            $this->install_msg = $install_msg."\n";
            
            ?>
            <table class="adminlist" style="width:100%;">
                <thead>
                    <tr>
                        <th class="title" style="text-align:center;"><img src="<?php echo URI::base(); ?>components/com_jdownloads/assets/images/jdownloads.jpg" style="border:0;" alt="jDownloads Logo" /><br />
                        <?php echo $this->install_msg; ?>
                        </th>
                    </tr>
                </thead>
           </table>
        <form>
            <div style="text-align:center; margin:25px,0px,25px,0px;"><input class="btn btn-primary" style="align:center;" type="button" value="<?php echo Text::_('COM_JDOWNLOADS_INSTALL_16').'&nbsp; '; ?>" onclick="window.location.href='index.php?option=com_jdownloads'" /></div>
        </form>
        
        <?php  // end install/update
        
        } else {
            
            if ($type == 'uninstall'){
                       
            }
           
        }
        
        // ***********************************************************************************************************
        // Only here the component files are copied from the Joomla installation function to the target directories... 
        // ***********************************************************************************************************
	}
 
	/**
	 * Method to run after an install/update/discover_install method
	 *
	 * @return void
	 */
	public function postflight($type, $parent) 
	{
		// $parent is the class calling this method
		// $type is the type of change (install, update or discover_install)
        
        $app    = Factory::getApplication(); 
        $db     = Factory::getContainer()->get(DatabaseInterface::class);        
        $language = $app->getLanguage();
        
        if ($type == 'install' || $type == 'update'){
            // Load admin strings early because update notices below are shown before later setup steps.
            $language->load('com_jdownloads', JPATH_ADMINISTRATOR);

            $this->backfillCategoryExtensionValues();

            if ($type == 'update') {
                $acl_asset_maintenance = $this->runUpgradeAclAssetMaintenance();

                if ($acl_asset_maintenance['issues_found']) {
                    if ($acl_asset_maintenance['total_changes'] > 0) {
                        $app->enqueueMessage(
                            Text::sprintf(
                                'COM_JDOWNLOADS_UPDATE_ACL_ASSET_REPAIR_NOTICE',
                                (int) $acl_asset_maintenance['category_changes'],
                                (int) $acl_asset_maintenance['download_changes'],
                                (int) $acl_asset_maintenance['asset_changes']
                            ),
                            'message'
                        );
                    }

                    $app->enqueueMessage(Text::_('COM_JDOWNLOADS_UPDATE_ACL_ASSET_REPAIR_WARNING'), 'warning');
                }
            }

            
            require_once (JPATH_ADMINISTRATOR.'/components/com_jdownloads/src/Helper/JDownloadsHelper.php');
            require_once (JPATH_ADMINISTRATOR.'/components/com_jdownloads/src/Helper/StandardLayouts.php');
            
            /* Write default permission settings in the assets table when not exist already
            /  
            / Temporarily removed as we did not want to use automatic download permission for all levels as default in the future. 
            / This would make it easier to create a category-level authorisation structure without having to make major adjustments beforehand.
            / But activated again in first beta to be full compatible with old 3.9 series.
            */
            $query = $db->getQuery(true);
            $query->select('rules');
            $query->from('#__assets');
            $query->where('name = '.$db->Quote('com_jdownloads'));
            $db->setQuery($query);
            $jd_component_rule = $db->loadResult();              
              
            if ($jd_component_rule == '' || $jd_component_rule == '{}'){
                $query = $db->getQuery(true);
                $query->update($db->quoteName('#__assets'));
                $query->set('rules = '.$db->Quote('{"download":{"1":1}}'));
                $query->where('name = '.$db->Quote('com_jdownloads'));
                $db->setQuery($query);
				$this->executeQuery($db);
            }
            
            // Replace titles from the jD backend admin modules with the right content from language file
            $query = $db->getQuery(true);
            $query->select('title');
            $query->from('#__assets');
            $query->where('title = '.$db->Quote('jDownloads Stats for Administrators'));
            $db->setQuery($query);
            $result = $db->LoadResult();
            if ($result){
                $new_name = Text::_('COM_JDOWNLOADS_STATS_MODULE_TITLE');
                $old_name = Text::_('jDownloads Stats for Administrators');
                $query = $db->getQuery(true);
                $query->update($db->quoteName('#__assets'));
                $query->set('title = '.$db->Quote($new_name));
                $query->where('title = '.$db->Quote($old_name));
                $db->setQuery($query);
				$this->executeQuery($db);
                $new_name = Text::_('COM_JDOWNLOADS_MONITORING_MODULE_TITLE');
                $old_name = Text::_('jDownloads Administrator Monitoring');
                $query = $db->getQuery(true);
                $query->update($db->quoteName('#__assets'));
                $query->set('title = '.$db->Quote($new_name));
                $query->where('title = '.$db->Quote($old_name));
                $db->setQuery($query);
				$this->executeQuery($db);
            }
            
            // Get the currently stored jDownloads params
            $query = $db->getQuery(true);
            $db->setQuery('SELECT `params` FROM #__extensions WHERE `type` = "component" AND `element` = "com_jdownloads"');
            $old_params = $db->loadResult();
            
            if ($old_params == '{}' || !$old_params){
            
                // Create the default param values
                $json = file_get_contents(JPATH_ADMINISTRATOR.'/components/com_jdownloads/default_params.txt');
                $def_params = json_decode($json);
                

                // Add the root path
                $files_uploaddir = $db->escape(JPATH_ROOT.'/jdownloads'); 
                $files_uploaddir = rtrim($files_uploaddir, "/");
                $files_uploaddir = rtrim($files_uploaddir, "\\");
                $files_uploaddir = str_replace('\\', '/', $files_uploaddir);
                
                $def_params->files_uploaddir = $files_uploaddir;
                $def_params->root_dir        = $files_uploaddir;
                
                // Some fields must have values from the current active jD language files
                $def_params->global_datetime                = $db->escape(Text::_('COM_JDOWNLOADS_INSTALL_DEFAULT_DATE_FORMAT'));
                $def_params->global_datetime_short          = $db->escape(Text::_('COM_JDOWNLOADS_INSTALL_DEFAULT_DATE_FORMAT'));
                $def_params->offline_text                   = $db->escape(Text::_('COM_JDOWNLOADS_BACKEND_OFFLINE_MESSAGE_DEFAULT'));
                $def_params->system_list                    = $db->escape(Text::_('COM_JDOWNLOADS_BACKEND_FILESEDIT_SYSTEM_DEFAULT_LIST'));
                $def_params->language_list                  = $db->escape(Text::_('COM_JDOWNLOADS_BACKEND_FILESEDIT_LANGUAGE_DEFAULT_LIST'));
                $def_params->send_mailto_betreff            = $db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_INSTALL_3'));
                $def_params->send_mailto_template_download  = $db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_MAIL_DEFAULT'));
                $def_params->send_mailto_betreff_upload     = $db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_INSTALL_6'));
                $def_params->send_mailto_template_upload    = $db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_GLOBAL_MAIL_UPLOAD_TEMPLATE'));
                $def_params->report_mail_subject            = $db->escape(Text::_('COM_JDOWNLOADS_CONFIG_REPORT_FILE_MAIL_SUBJECT_DEFAULT'));
                $def_params->report_mail_layout             = $db->escape(Text::_('COM_JDOWNLOADS_CONFIG_REPORT_FILE_MAIL_LAYOUT_DEFAULT'));
                $def_params->customers_mail_subject         = $db->escape(Text::_('COM_JDOWNLOADS_CONFIG_CUSTOMERS_MAIL_SUBJECT_DEFAULT'));
                $def_params->customers_mail_layout          = $db->escape(Text::_('COM_JDOWNLOADS_CONFIG_CUSTOMERS_MAIL_LAYOUT_DEFAULT'));
                $def_params->user_message_when_zero_points  = $db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SET_AUP_FE_MESSAGE_NO_DOWNLOAD'));
                $def_params->fileplugin_defaultlayout       = $db->escape(Text::_('COM_JDOWNLOADS_BACKEND_SETTINGS_TEMPLATES_FILES_DEFAULT_NAME'));
                $def_params->fileplugin_offline_title       = $db->escape(Text::_('COM_JDOWNLOADS_FRONTEND_SETTINGS_FILEPLUGIN_OFFLINE_FILETITLE'));
                $def_params->fileplugin_offline_descr       = $db->escape(Text::_('COM_JDOWNLOADS_FRONTEND_SETTINGS_FILEPLUGIN_DESCRIPTION'));
                $def_params->checkbox_top_text              = $db->escape(Text::_('COM_JDOWNLOADS_SETTINGS_INSTALL_1'));
                
                // Create a new scan secret key - added in 4.0.48
                $def_params->scan_secret_key                = bin2hex(random_bytes(16));
                
                //$def_params->sortorder_fields               = '["0","1","2","3","4"]';
            
                $json = json_encode($def_params, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
	            $query = $db->getQuery(true);
	            $db->setQuery("UPDATE #__extensions SET params = " . $db->quote($json) . " WHERE `type` = 'component' AND `element` = 'com_jdownloads'");
                if ($db->execute()){
                    self::addLog(Text::_('COM_JDOWNLOADS_INSTALL_HINT_1'), 'Log::INFO');                
                }
        	}
        }
        
        if ( $type == 'update' ){
            // Update the length of logs_ip field to 50
            $query = $db->getQuery(true);
            $db->setQuery("ALTER TABLE #__jdownloads_logs CHANGE log_ip log_ip varchar(50) NOT NULL DEFAULT ''");
            try {
                $db->execute();
            } catch(RuntimeException $e) {
                self::addLog(Text::_($e->getMessage()), 'Log::ERROR');
                Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
            }
            
            // If the jDownloads component or other parts have been deactivated (due to earlier incompatibility),
            // they must now be reactivated to avoid an error message the first time they are called.
            $query = $db->getQuery(true);
            $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `name` = 'com_jDownloads'");
            $db->execute();
            $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `name` = 'plg_system_jdownloads'");
            $db->execute();
            $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `name` = 'plg_content_jdownloads_tags_fix'");
            $db->execute();
            $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `element` = 'mod_jdownloads_admin_stats'");
            $db->execute();
            $db->setQuery("UPDATE #__extensions SET enabled = '1' WHERE `element` = 'mod_jdownloads_admin_monitoring'");
            $db->execute();
            
            // If an upgrade from 3.9 was performed at an earlier time, the 'publish_down' field in #__jdownloads_files might still contain wrong values (0000-00-00 00:00:00).
            // Here we try to check this and correct it to 'NULL'.
            $query = $db->getQuery(true);
            $db->setQuery("SELECT COUNT(*) FROM #__jdownloads_files WHERE `publish_down` = '0000-00-00 00:00:00'");
            $result = $db->loadResult();
            if ($result > 0){
                $db->setQuery("SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION'");
                $db->execute();
                $db->setQuery("UPDATE #__jdownloads_files SET `publish_down` = null WHERE `publish_down` = '0000-00-00 00:00:00'");
                if ($db->execute()){
                    self::addLog(Text::_('Wrong values successfully corrected in jdownloads_files `publish_down` field.'), 'Log::INFO');                
                } else {
                    self::addLog(Text::_('Attention! Wrong values could not be corrected in jdownloads_files `publish_down` field.'), 'Log::ALERT');                
                }
            }
            
            // Add an additional table index if in jdownloads_files it does not already exist. For better performance. Added since 4.0.46.
            $query = $db->getQuery(true);
            $db->setQuery("SHOW INDEXES FROM `#__jdownloads_files` WHERE Key_name = 'idx_catid_extra'");
            $result = $db->loadObject();
            if (!$result){
                // Create the missing index
                $db->setQuery('ALTER TABLE `#__jdownloads_files` ADD INDEX `idx_catid_extra` (`catid`, `published`, `access`, `user_access`, `publish_up`, `publish_down`) USING BTREE');
                    try {
                        $result = $db->execute();
                    } catch(RuntimeException $e) {
                        self::addLog(Text::_($e->getMessage()), 'Log::ERROR');
                        Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
                    }
                    if ($result){
                        self::addLog('Additional index `idx_catid_extra` in jdownloads_files table successful created.', 'Log::INFO');
                    }
            } else {
                self::addLog('Additional index `idx_catid_extra` exists already in jdownloads_files table.', 'Log::INFO');
            }
        }    
        
        // $type is install, update or discover_install
        
        // Write for the Tags feature the jDownloads data in the #__content_types table
        $query = $db->getQuery(true);
        $query->select('*');
        $query->from('#__content_types');
        $query->where('type_alias = '.$db->Quote('com_jdownloads.download'));
        $db->setQuery($query);
        $type_download = $db->loadResult();              
        
        if (!$type_download){              
            $query = $db->getQuery(true);
            $query->insert($db->quoteName('#__content_types'))
                    ->columns(array($db->quoteName('type_title'), $db->quoteName('type_alias'), $db->quoteName('table'), $db->quoteName('rules'), $db->quoteName('field_mappings'), $db->quoteName('router')))
                    ->values($db->quote('jDownloads Download'). ', ' .$db->quote('com_jdownloads.download'). ',' .$db->quote('{"special":{"dbtable":"#__jdownloads_files","key":"id","type":"DownloadTable","prefix":"JDownloads\\Component\\JDownloads\\Administrator\\Table\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Download","prefix":"Joomla\\CMS\\Table\\","config":"array()"}}', false).', '.$db->quote('').', '.$db->quote('{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"views","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"null", "core_language":"language", "core_images":"images", "core_urls":"null", "core_version":"null", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "core_xreference":"null", "asset_id":"asset_id"}, "special":{"description_long":"description_long"}}', false).', ' .$db->quote('RouteHelper::getDownloadRoute'));
            $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                    
			$this->executeQuery($db);
            
            $query = $db->getQuery(true);
            $query->insert($db->quoteName('#__content_types'))
                    ->columns(array($db->quoteName('type_title'), $db->quoteName('type_alias'), $db->quoteName('table'), $db->quoteName('rules'), $db->quoteName('field_mappings'), $db->quoteName('router')))
                    ->values($db->quote('jDownloads Category'). ', ' .$db->quote('com_jdownloads.category'). ',' .$db->quote('{"special":{"dbtable":"#__jdownloads_categories","key":"id","type":"JDCategoryTable","prefix":"JDownloads\\Component\\JDownloads\\Administrator\\Table\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Category","prefix":"Joomla\\CMS\\Table\\","config":"array()"}}', false).', '.$db->quote('').', '.$db->quote('{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"views","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "core_xreference":"null", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"null","extension":"null","note":"null"}}', false).', ' .$db->quote('RouteHelper::getCategoryRoute'));
            $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                               
			$this->executeQuery($db);
        } 
        
        // Write for the Joomla user 'action log' feature the required jDownloads data in the #__action_log_config
        $query = $db->getQuery(true);
        $query->select('*');
        $query->from('#__action_log_config');
        $query->where('type_alias = '.$db->Quote('com_jdownloads.download'));
        $db->setQuery($query);
        $type_download = $db->loadResult();              
        
        if (!$type_download){              
            $query = $db->getQuery(true);
            $query->insert($db->quoteName('#__action_log_config'))
                    ->columns(array($db->quoteName('type_title'), $db->quoteName('type_alias'), $db->quoteName('id_holder'), $db->quoteName('title_holder'), $db->quoteName('table_name'), $db->quoteName('text_prefix')))
                    ->values($db->quote('download'). ', ' .$db->quote('com_jdownloads.download'). ', ' .$db->quote('id'). ',' .$db->quote('title'). ', ' .$db->quote('#__jdownloads_files'). ', ' .$db->quote('COM_JDOWNLOADS_ACTIONLOG'));
            $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                    
			$this->executeQuery($db);
            $query = $db->getQuery(true);
            $query->insert($db->quoteName('#__action_log_config'))
                    ->columns(array($db->quoteName('type_title'), $db->quoteName('type_alias'), $db->quoteName('id_holder'), $db->quoteName('title_holder'), $db->quoteName('table_name'), $db->quoteName('text_prefix')))
                    ->values($db->quote('category'). ', ' .$db->quote('com_jdownloads.category'). ', ' .$db->quote('id'). ', ' .$db->quote('title'). ', ' .$db->quote('#__jdownloads_categories'). ', ' .$db->quote('COM_JDOWNLOADS_ACTIONLOG'));
            $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                    
			$this->executeQuery($db);
            $query = $db->getQuery(true);
            $query->insert($db->quoteName('#__action_log_config'))
                    ->columns(array($db->quoteName('type_title'), $db->quoteName('type_alias'), $db->quoteName('id_holder'), $db->quoteName('title_holder'), $db->quoteName('table_name'), $db->quoteName('text_prefix')))
                    ->values($db->quote('license'). ', ' .$db->quote('com_jdownloads.license'). ', ' .$db->quote('id'). ', ' .$db->quote('title'). ', ' .$db->quote('#__jdownloads_licenses'). ', ' .$db->quote('COM_JDOWNLOADS_ACTIONLOG'));
            $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                    
			$this->executeQuery($db);
            $query = $db->getQuery(true);
            $query->insert($db->quoteName('#__action_log_config'))
                    ->columns(array($db->quoteName('type_title'), $db->quoteName('type_alias'), $db->quoteName('id_holder'), $db->quoteName('title_holder'), $db->quoteName('table_name'), $db->quoteName('text_prefix')))
                    ->values($db->quote('layout'). ', ' .$db->quote('com_jdownloads.template'). ', ' .$db->quote('id'). ', ' .$db->quote('template_name'). ', ' .$db->quote('#__jdownloads_templates'). ', ' .$db->quote('COM_JDOWNLOADS_ACTIONLOG'));
            $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                    
			$this->executeQuery($db);
            $query = $db->getQuery(true);
            $query->insert($db->quoteName('#__action_log_config'))
                    ->columns(array($db->quoteName('type_title'), $db->quoteName('type_alias'), $db->quoteName('id_holder'), $db->quoteName('title_holder'), $db->quoteName('table_name'), $db->quoteName('text_prefix')))
                    ->values($db->quote('group'). ', ' .$db->quote('com_jdownloads.group'). ', ' .$db->quote('id'). ', ' .$db->quote('group_id'). ', ' .$db->quote('#__jdownloads_usergroups_limits'). ', ' .$db->quote('COM_JDOWNLOADS_ACTIONLOG'));
            $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                    
			$this->executeQuery($db);
            
            // We need also a new dataset in the #__action_logs_extensions table
            $query = $db->getQuery(true);
            $query->select('*');
            $query->from('#__action_logs_extensions');
            $query->where('extension = '.$db->Quote('com_jdownloads'));
            $db->setQuery($query);
            $result = $db->loadResult();              
            
            if (!$result){              
                $query = $db->getQuery(true);
                $query->insert($db->quoteName('#__action_logs_extensions'))
                        ->columns(array($db->quoteName('extension')))
                        ->values($db->quote('com_jdownloads'));
                $db->setQuery($query);                                                                                                                                                                                                                                                                                                                                                    
				$this->executeQuery($db);
            }
        }                   

        
        if ( $type == 'install'){     
            self::addLog('------------------------------------------------------ Installation Finished', 'Log::INFO');                
        }
        if ( $type == 'update'){     
            self::addLog('------------------------------------------------------ Update Finished', 'Log::INFO');                
        }
                            
        ?>
        <form>
            <div style="text-align:center; margin:25px,0px,25px,0px;"><input class="btn btn-primary" style="align:center;" type="button" value="<?php echo Text::_('COM_JDOWNLOADS_INSTALL_16').'&nbsp; '; ?>" onclick="window.location.href='index.php?option=com_jdownloads'" /></div>
        </form>
        <?php
	}

    /**
     * Backfills the category extension column after older update paths added the field
     * without fully populating existing or newly created rows.
     *
     * @return void
     */
    private function backfillCategoryExtensionValues(): void
    {
        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $table_fields = $db->getTableColumns('#__jdownloads_categories');

        if (!isset($table_fields['extension'])) {
            return;
        }

        $query = $db->getQuery(true)
            ->update($db->quoteName('#__jdownloads_categories'))
            ->set($db->quoteName('extension') . ' = ' . $db->quote('com_jdownloads'))
            ->where('(' . $db->quoteName('extension') . ' IS NULL'
                . ' OR ' . $db->quoteName('extension') . ' = ' . $db->quote('')
                . ' OR ' . $db->quoteName('extension') . ' <> ' . $db->quote('com_jdownloads') . ')');
        $db->setQuery($query);

        try {
            $db->execute();

            if ((int) $db->getAffectedRows() > 0) {
                self::addLog('Backfilled jDownloads category extension values.', 'Log::INFO');
            }
        } catch (\RuntimeException $e) {
            self::addLog($e->getMessage(), 'Log::ERROR');
            Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
        }
    }

    /**
     * Runs non-destructive ACL/asset maintenance for older upgraded installations.
     *
     * @return array<string, int|bool>
     */
    private function runUpgradeAclAssetMaintenance(): array
    {
        $summary = [
            'issues_found' => false,
            'category_changes' => 0,
            'download_changes' => 0,
            'asset_changes' => 0,
            'total_changes' => 0,
        ];

        try {
            $cleanup_result = $this->cleanupBrokenCategoryZeroAsset();
            $category_result = $this->repairCategoryAssetLinks();
            $download_result = $this->repairDownloadAssetLinks();

            $summary['issues_found'] = !empty($cleanup_result['issues_found'])
                || !empty($category_result['issues_found'])
                || !empty($download_result['issues_found']);
            $summary['category_changes'] = (int) ($category_result['table_changes'] ?? 0);
            $summary['download_changes'] = (int) ($download_result['table_changes'] ?? 0);
            $summary['asset_changes'] = (int) ($cleanup_result['asset_changes'] ?? 0)
                + (int) ($category_result['asset_changes'] ?? 0)
                + (int) ($download_result['asset_changes'] ?? 0);
            $summary['total_changes'] = (int) $summary['category_changes']
                + (int) $summary['download_changes']
                + (int) $summary['asset_changes'];

            if (!empty($cleanup_result['rebuild_required'])
                || !empty($category_result['rebuild_required'])
                || !empty($download_result['rebuild_required'])) {
                $this->rebuildAssetTree();
            }
        } catch (\RuntimeException $e) {
            self::addLog('ACL/asset maintenance during update failed: ' . $e->getMessage(), 'Log::WARNING');
            Factory::getApplication()->enqueueMessage($e->getMessage(), 'warning');
        }

        return $summary;
    }

    /**
     * Removes the orphan asset left behind by failed 4.0.50 category inserts.
     *
     * @return array<string, int|bool>
     */
    private function cleanupBrokenCategoryZeroAsset(): array
    {
        $db = Factory::getContainer()->get(DatabaseInterface::class);

        $query = $db->getQuery(true)
            ->select($db->quoteName('id'))
            ->from($db->quoteName('#__assets'))
            ->where($db->quoteName('name') . ' = ' . $db->quote('com_jdownloads.category.0'));
        $db->setQuery($query);

        $asset_id = (int) $db->loadResult();

        if ($asset_id <= 0) {
            return ['issues_found' => false, 'asset_changes' => 0, 'rebuild_required' => false];
        }

        $query = $db->getQuery(true)
            ->delete($db->quoteName('#__assets'))
            ->where($db->quoteName('id') . ' = ' . $asset_id);
        $db->setQuery($query);

        try {
            $db->execute();
            self::addLog('Removed orphan asset com_jdownloads.category.0 and rebuilt the asset tree.', 'Log::INFO');

            return ['issues_found' => true, 'asset_changes' => 1, 'rebuild_required' => true];
        } catch (\RuntimeException $e) {
            self::addLog($e->getMessage(), 'Log::ERROR');
            Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');

            return ['issues_found' => true, 'asset_changes' => 0, 'rebuild_required' => false];
        }
    }

    /**
     * Repairs category asset rows, parent relations and asset_id links without altering explicit ACL rules.
     *
     * @return array<string, int|bool>
     */
    private function repairCategoryAssetLinks(): array
    {
        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $query = $db->getQuery(true)
            ->select($db->quoteName(['id', 'parent_id', 'title', 'asset_id']))
            ->from($db->quoteName('#__jdownloads_categories'))
            ->order($db->quoteName('lft') . ' ASC')
            ->order($db->quoteName('id') . ' ASC');
        $db->setQuery($query);
        $category_rows = $db->loadAssocList() ?: [];

        $table_changes = 0;
        $asset_changes = 0;
        $issues_found = false;
        $rebuild_required = false;

        foreach ($category_rows as $category_row) {
            $category_id = (int) ($category_row['id'] ?? 0);

            if ($category_id <= 0) {
                continue;
            }

            $parent_asset_id = $this->getComponentAssetId();
            $parent_category_id = (int) ($category_row['parent_id'] ?? 0);

            if ($parent_category_id > 1) {
                $parent_asset = $this->loadAssetByName('com_jdownloads.category.' . $parent_category_id);

                if ($parent_asset !== null) {
                    $parent_asset_id = (int) ($parent_asset['id'] ?? 0);
                }
            }

            $asset_sync = $this->ensureAssetRecord(
                'com_jdownloads.category.' . $category_id,
                $parent_asset_id,
                (string) ($category_row['title'] ?? '')
            );

            if (!empty($asset_sync['issues_found'])) {
                $issues_found = true;
            }

            $asset_changes += (int) ($asset_sync['asset_changes'] ?? 0);
            $rebuild_required = $rebuild_required || !empty($asset_sync['rebuild_required']);
            $asset_id = (int) ($asset_sync['asset_id'] ?? 0);

            if ($asset_id > 0 && (int) ($category_row['asset_id'] ?? 0) !== $asset_id) {
                $query = $db->getQuery(true)
                    ->update($db->quoteName('#__jdownloads_categories'))
                    ->set($db->quoteName('asset_id') . ' = ' . $asset_id)
                    ->where($db->quoteName('id') . ' = ' . $category_id);
                $db->setQuery($query);
                $db->execute();
                $table_changes++;
                $issues_found = true;
            }
        }

        return [
            'issues_found' => $issues_found,
            'table_changes' => $table_changes,
            'asset_changes' => $asset_changes,
            'rebuild_required' => $rebuild_required,
        ];
    }

    /**
     * Repairs download asset rows, parent relations and asset_id links without altering explicit ACL rules.
     *
     * @return array<string, int|bool>
     */
    private function repairDownloadAssetLinks(): array
    {
        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $query = $db->getQuery(true)
            ->select($db->quoteName(['id', 'catid', 'title', 'asset_id']))
            ->from($db->quoteName('#__jdownloads_files'))
            ->order($db->quoteName('id') . ' ASC');
        $db->setQuery($query);
        $download_rows = $db->loadAssocList() ?: [];

        $table_changes = 0;
        $asset_changes = 0;
        $issues_found = false;
        $rebuild_required = false;

        foreach ($download_rows as $download_row) {
            $download_id = (int) ($download_row['id'] ?? 0);

            if ($download_id <= 0) {
                continue;
            }

            $parent_asset_id = $this->getComponentAssetId();
            $category_id = (int) ($download_row['catid'] ?? 0);

            if ($category_id > 1) {
                $category_asset = $this->loadAssetByName('com_jdownloads.category.' . $category_id);

                if ($category_asset !== null) {
                    $parent_asset_id = (int) ($category_asset['id'] ?? 0);
                }
            }

            $asset_sync = $this->ensureAssetRecord(
                'com_jdownloads.download.' . $download_id,
                $parent_asset_id,
                (string) ($download_row['title'] ?? '')
            );

            if (!empty($asset_sync['issues_found'])) {
                $issues_found = true;
            }

            $asset_changes += (int) ($asset_sync['asset_changes'] ?? 0);
            $rebuild_required = $rebuild_required || !empty($asset_sync['rebuild_required']);
            $asset_id = (int) ($asset_sync['asset_id'] ?? 0);

            if ($asset_id > 0 && (int) ($download_row['asset_id'] ?? 0) !== $asset_id) {
                $query = $db->getQuery(true)
                    ->update($db->quoteName('#__jdownloads_files'))
                    ->set($db->quoteName('asset_id') . ' = ' . $asset_id)
                    ->where($db->quoteName('id') . ' = ' . $download_id);
                $db->setQuery($query);
                $db->execute();
                $table_changes++;
                $issues_found = true;
            }
        }

        return [
            'issues_found' => $issues_found,
            'table_changes' => $table_changes,
            'asset_changes' => $asset_changes,
            'rebuild_required' => $rebuild_required,
        ];
    }

    /**
     * Ensures a Joomla asset record exists with the expected parent and title.
     *
     * @param string $asset_name
     * @param int    $parent_asset_id
     * @param string $asset_title
     *
     * @return array<string, int|bool>
     */
    private function ensureAssetRecord(string $asset_name, int $parent_asset_id, string $asset_title): array
    {
        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $asset_title = $this->normalizeAssetTitle($asset_title);
        $asset_row = $this->loadAssetByName($asset_name);

        if ($asset_row !== null) {
            $field_updates = [];

            if ($parent_asset_id > 0 && (int) ($asset_row['parent_id'] ?? 0) !== $parent_asset_id) {
                $field_updates[] = $db->quoteName('parent_id') . ' = ' . $parent_asset_id;
            }

            if ((string) ($asset_row['title'] ?? '') !== $asset_title) {
                $field_updates[] = $db->quoteName('title') . ' = ' . $db->quote($asset_title);
            }

            if ($field_updates === []) {
                return [
                    'issues_found' => false,
                    'asset_id' => (int) $asset_row['id'],
                    'asset_changes' => 0,
                    'rebuild_required' => false,
                ];
            }

            $query = $db->getQuery(true)
                ->update($db->quoteName('#__assets'))
                ->set($field_updates)
                ->where($db->quoteName('id') . ' = ' . (int) $asset_row['id']);
            $db->setQuery($query);
            $db->execute();

            return [
                'issues_found' => true,
                'asset_id' => (int) $asset_row['id'],
                'asset_changes' => 1,
                'rebuild_required' => $parent_asset_id > 0 && (int) ($asset_row['parent_id'] ?? 0) !== $parent_asset_id,
            ];
        }

        $query = $db->getQuery(true)
            ->insert($db->quoteName('#__assets'))
            ->columns([
                $db->quoteName('parent_id'),
                $db->quoteName('lft'),
                $db->quoteName('rgt'),
                $db->quoteName('level'),
                $db->quoteName('name'),
                $db->quoteName('title'),
                $db->quoteName('rules'),
            ])
            ->values(
                implode(', ', [
                    (string) ($parent_asset_id > 0 ? $parent_asset_id : $this->getRootAssetId()),
                    '0',
                    '0',
                    '0',
                    $db->quote($asset_name),
                    $db->quote($asset_title),
                    $db->quote('{}'),
                ])
            );
        $db->setQuery($query);
        $db->execute();

        return [
            'issues_found' => true,
            'asset_id' => (int) $db->insertid(),
            'asset_changes' => 1,
            'rebuild_required' => true,
        ];
    }

    /**
     * Normalizes asset titles to the actual #__assets.title column length.
     *
     * @param string $asset_title
     *
     * @return string
     */
    private function normalizeAssetTitle(string $asset_title): string
    {
        $asset_title = trim($asset_title);

        if ($asset_title === '') {
            return $asset_title;
        }

        $max_length = $this->getAssetsTitleMaxLength();

        if ($max_length <= 0 || StringHelper::strlen($asset_title) <= $max_length) {
            return $asset_title;
        }

        return StringHelper::substr($asset_title, 0, $max_length);
    }

    /**
     * Resolves the configured varchar length of #__assets.title.
     *
     * @return int
     */
    private function getAssetsTitleMaxLength(): int
    {
        if ($this->asset_title_max_length !== null) {
            return (int) $this->asset_title_max_length;
        }

        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $db->setQuery('SHOW FIELDS FROM ' . $db->quoteName('#__assets') . ' WHERE Field = ' . $db->quote('title'));

        try {
            $field = $db->loadAssoc();
        } catch (\RuntimeException $e) {
            $this->asset_title_max_length = 100;

            return (int) $this->asset_title_max_length;
        }

        $type = strtolower((string) ($field['Type'] ?? ''));

        if (preg_match('/varchar\((\d+)\)/', $type, $matches)) {
            $this->asset_title_max_length = (int) $matches[1];
        } else {
            $this->asset_title_max_length = 100;
        }

        return (int) $this->asset_title_max_length;
    }

    /**
     * Loads one asset row by name.
     *
     * @param string $asset_name
     *
     * @return array<string, mixed>|null
     */
    private function loadAssetByName(string $asset_name): ?array
    {
        if ($asset_name === '') {
            return null;
        }

        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $query = $db->getQuery(true)
            ->select('*')
            ->from($db->quoteName('#__assets'))
            ->where($db->quoteName('name') . ' = ' . $db->quote($asset_name));
        $db->setQuery($query);
        $asset_row = $db->loadAssoc();

        return is_array($asset_row) ? $asset_row : null;
    }

    /**
     * Returns the component asset id with a root fallback.
     *
     * @return int
     */
    private function getComponentAssetId(): int
    {
        $component_asset = $this->loadAssetByName('com_jdownloads');

        if ($component_asset !== null) {
            return (int) ($component_asset['id'] ?? 0);
        }

        return $this->getRootAssetId();
    }

    /**
     * Returns the Joomla root asset id.
     *
     * @return int
     */
    private function getRootAssetId(): int
    {
        $db = Factory::getContainer()->get(DatabaseInterface::class);
        $query = $db->getQuery(true)
            ->select($db->quoteName('id'))
            ->from($db->quoteName('#__assets'))
            ->where($db->quoteName('parent_id') . ' = 0')
            ->order($db->quoteName('id') . ' ASC');
        $db->setQuery($query, 0, 1);

        return (int) $db->loadResult();
    }

    /**
     * Rebuilds the Joomla asset tree after asset maintenance.
     *
     * @return void
     */
    private function rebuildAssetTree(): void
    {
        $asset_table = Table::getInstance('Asset');

        if (!$asset_table->rebuild()) {
            throw new \RuntimeException((string) $asset_table->getError());
        }

        self::addLog('Rebuilt the Joomla asset tree after jDownloads ACL/asset maintenance.', 'Log::INFO');
    }

    /**
     * Method to get the correct db prefix (problem with getTablelist() which always/sometimes has lowercase prefix names in array)
     *
     * @return string
     */
    private function getCorrectDBPrefix() 
    {
        $db = Factory::getContainer()->get(DatabaseInterface::class);

        // Get DB prefix string and table list
        $prefix     = $db->getPrefix();
        $prefix_low = strtolower($prefix);
        $tablelist  = $db->getTableList();

        if (!in_array ( $prefix.'assets', $tablelist)) {
            if (in_array ( $prefix_low.'assets', $tablelist)) {
                return $prefix_low;
            } else {
                // Assets table not found? 
                return '';
            } 
        } else {
            return $prefix;
        }        
    }
    
    
    /**
     * Method to get only a part from the string in a selected language
     *
     * @return string
     */
    private function getOnlyLanguageSubstring($msg, $lang_key = '')
    {
        // Get the current locale language tag
        if (!$lang_key){
            $lang       = Factory::getApplication()->getLanguage();
            $lang_key   = $lang->getTag();        
        }
        
        // Remove the language tag from the text
        $startpos = StringHelper::strpos($msg, '{'.$lang_key.'}') +  strlen( $lang_key) + 2 ;
        $endpos   = StringHelper::strpos($msg, '{/'.$lang_key.'}') ;
        
        if ($startpos !== false && $endpos !== false){
            return StringHelper::substr($msg, $startpos, ($endpos - $startpos ));
        } else {    
            return $msg;
        }    
    }
    
    /**
     * Method to add a log item 
     *
     * @return
     */
    private function addLog($msg, $priority, $basic_informations = false)
    {
        if ($basic_informations){
            // Add a few important system information when param is set

            $db = Factory::getContainer()->get(DatabaseInterface::class);
            $messages_array = array();

            $logoptions['text_entry_format'] = '{DATE} {TIME}    {PRIORITY}     {MESSAGE}';
            $logoptions['text_file'] = 'com_jdownloads_install_logs.php';
            
            Log::addLogger($logoptions, Log::ALL, 'jD');

            $version = new Version();
            
            $messages_array[] = '------------------------------------------------------ System Information';                
            $messages_array[] = 'OS                 : '.substr(php_uname(), 0, 7);
            $messages_array[] = 'PHP                : '.phpversion();
            $messages_array[] = 'MySQL              : '.$db->getVersion();
            $messages_array[] = 'Joomla!            : '.$version->getShortVersion();
            
            $messages_array[] = 'Debug              : '.Factory::getApplication()->get('debug');
            $messages_array[] = 'Debug Language     : '.Factory::getApplication()->get('debug_lang');
            
            $messages_array[] = 'Error Reporting    : '.Factory::getApplication()->get('error_reporting');
            
            $messages_array[] = 'SEF                : '.Factory::getApplication()->get('sef');
            $messages_array[] = 'Unicode Aliases    : '.Factory::getApplication()->get('unicodeslugs');
            $messages_array[] = 'System Cache       : '.Factory::getApplication()->get('caching');
            $messages_array[] = 'Captcha            : '.Factory::getApplication()->get('captcha');
            
            foreach ($messages_array as $message){
                        
                try
                {
                    Log::add(Text::_($message), LOG::INFO, 'jD');
                }            
                catch (RuntimeException $exception)
                {
                    // Informational log only
                }
            }
            return;
        }
        
        // Add here the normal log item
        
        $logoptions['text_entry_format'] = '{DATE} {TIME}    {PRIORITY}     {MESSAGE}';
        $logoptions['text_file'] = 'com_jdownloads_install_logs.php';
        
        Log::addLogger($logoptions, Log::ALL, 'jD');

        try
        {
            Log::add(Text::_($msg), $priority, 'jD');
        }            
        catch (RuntimeException $exception)
        {
            // Informational log only
        }
        return;
    }
    
}