| Current Path : /var/www/html/administrator/components/com_flexicontact/ |
| Current File : /var/www/html/administrator/components/com_flexicontact/install.php |
<?php
/********************************************************************
Product : Flexicontact
Date : 15 August 2024
Copyright : Les Arbres Design 2009-2024
Contact : https://www.lesarbresdesign.info
Licence : GNU General Public License
*********************************************************************/
defined('_JEXEC') or die('Restricted Access');
use Joomla\CMS\Factory;
use Joomla\CMS\Installer\Installer;
use Joomla\CMS\HTML\HTMLHelper;
class com_flexicontactInstallerScript
{
var $app;
var $db;
var $previous_component_version;
public function preflight($type, $parent)
{
if ($type == 'uninstall')
return;
if (defined('JVERSION'))
$joomla_version = JVERSION; // get the Joomla version (JVERSION did not exist before Joomla 2.5)
else
$joomla_version = '1.x';
$this->app = Factory::getApplication();
if (version_compare($joomla_version,"4.0","<"))
{
$this->app->enqueueMessage("This extension requires at least Joomla 4.0. This is $joomla_version ", 'error');
return false;
}
$dbtype = $this->app->get('dbtype');
if (!strstr($dbtype,'mysql'))
{
$this->app->enqueueMessage("Flexicontact currently only supports MYSQL databases. It cannot run with $dbtype", 'error');
return false;
}
$this->db = Factory::getDBO();
$db_version = $this->ladb_loadResult('select version()');
if (version_compare($db_version,"5.5.3","<"))
{
$this->app->enqueueMessage("Flexicontact requires at least MySql 5.5.3. Your version is $db_version", 'error');
return false;
}
if (version_compare(PHP_VERSION,"7.0.0","<"))
{
$app->enqueueMessage("Flexicontact requires at least PHP 7.0.0. Your version is ".PHP_VERSION, 'error');
return false;
}
if (!function_exists('mb_substr'))
{
$this->app->enqueueMessage("Flexicontact cannot run on this server because it does not support the PHP Multibyte String Functions", 'error');
return false;
}
// get the previously installed version, if any
if (file_exists(JPATH_ADMINISTRATOR.'/components/com_flexicontact/flexicontact.xml'))
{
$xml_array = Installer::parseXMLInstallFile(JPATH_ADMINISTRATOR.'/components/com_flexicontact/flexicontact.xml');
$this->previous_component_version = $xml_array['version'];
}
// empty the admin assets directory, the current files will be re-installed
foreach (glob(JPATH_SITE.'/administrator/components/com_flexicontact/assets/*.*') as $filename)
@unlink($filename);
return true;
}
public function uninstall($parent)
{
$text = "You uninstalled the Flexicontact component. If you want to remove the Flexicontact data, execute this query in phpMyAdmin:
<br><br>DROP TABLE #__flexicontact_log;
<br><br>If you DO NOT execute the query, you can install Flexicontact again without losing your data.
<br>Please note that you don't have to uninstall Flexicontact to install a new version. Simply install the new version without uninstalling the current version.";
$this->app = Factory::getApplication();
$dbprefix = $this->app->get('dbprefix');
$text = str_replace('#__', $dbprefix, $text);
$this->app->enqueueMessage($text, 'notice');
return true;
}
//-------------------------------------------------------------------------------
// The main install function
//
public function postflight($type, $parent)
{
if ($type == 'uninstall')
return;
// check the Joomla version
if (substr(JVERSION,0,1) > "5")
$this->app->enqueueMessage("This version of Flexicontact has not been tested on this version of Joomla.", 'notice');
// get the component version from the component manifest xml file
$component_version = $parent->getManifest()->version;
// delete redundant files from older versions
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/assets/com_flexicontact_j3.css');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/admin.flexicontact.php');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/toolbar.flexicontact.html.php');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/toolbar.flexicontact.php');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/admin.flexicontact.html.php');
@unlink(JPATH_SITE.'/components/com_flexicontact/flexicontact.html.php');
@unlink(JPATH_SITE.'/components/com_flexicontact/RL_flexicontact.html.php');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/joomla15.xml');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/joomla16.xml');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/install.flexicontact.php');
@unlink(JPATH_SITE.'/components/com_flexicontact/views/responsive/view.html.php'); // leave the rest of the view so that old menu items still work
@unlink(JPATH_SITE.'/components/com_flexicontact/error_log.txt');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/helpers/db_helper.php');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/forms/image.php');
@unlink(JPATH_SITE.'/components/com_flexicontact/views/contact/metadata.xml');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/latest_version.xml'); // re-created by the about view
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/fields/tracebuttons.php');
@unlink(JPATH_SITE.'/administrator/components/com_flexicontact/fields/j3linkpreview.php');
self::recurse_delete(JPATH_SITE."/administrator/components/com_flexicontact/forms");
self::recurse_delete(JPATH_SITE."/components/com_flexicontact/assets");
self::recurse_delete(JPATH_SITE."/components/com_flexicontact/old_assets");
self::deleteAdminViews(array('help','log_list','log_detail','config_list','config_general','config_fields','config_text','config_template',
'config_captcha','config_confirm','config_images','config_css'));
self::recurse_delete(JPATH_SITE.'/administrator/components/com_flexicontact/forms_j3');
// we no longer install the view named 'responsive', but if it is present, copy the default.xml from 'contact' to 'responsive'
if (file_exists(JPATH_SITE.'/components/com_flexicontact/views/responsive/tmpl/default.xml'))
copy(JPATH_SITE.'/components/com_flexicontact/views/contact/tmpl/default.xml', JPATH_SITE.'/components/com_flexicontact/views/responsive/tmpl/default.xml');
// remove redundant http update sites, if present
$this->db = Factory::getDBO();
$this->ladb_execute_ignore("DELETE FROM `#__update_sites` WHERE `name`= 'Flexicontact' AND SUBSTRING(`location`,1,5) = 'http:'");
// we now install language files in the component directories, so must remove them from the system-wide directories, since those would take precedence
$dirs = glob(JPATH_ADMINISTRATOR.'/language/*',GLOB_ONLYDIR);
foreach ($dirs as $dir)
{
$sub_dir = basename($dir);
@unlink($dir.'/'.$sub_dir.'.com_flexicontact.ini');
@unlink($dir.'/'.$sub_dir.'.com_flexicontact.sys.ini');
}
$dirs = glob(JPATH_SITE.'/language/*',GLOB_ONLYDIR);
foreach ($dirs as $dir)
{
$sub_dir = basename($dir);
@unlink($dir.'/'.$sub_dir.'.com_flexicontact.ini');
}
// remove the original 20 GIF images
$image_path = JPATH_SITE.'/media/com_flexicontact/images/';
for ($i=1; $i<=20; $i++)
@unlink($image_path.sprintf('%03u.gif',$i));
// create or upgrade the log table
$this->create_log_table();
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
$this->add_column('#__flexicontact_log', 'admin_email', "VARCHAR(60) NOT NULL DEFAULT '' AFTER `email`");
$this->add_column('#__flexicontact_log', 'list_choice', "VARCHAR(60) DEFAULT NULL AFTER `browser_string`");
$this->add_column('#__flexicontact_log', 'admin_from_email', "VARCHAR(60) DEFAULT NULL AFTER `admin_email`"); // 8.08
$this->add_column('#__flexicontact_log', 'user_from_email', "VARCHAR(60) NOT NULL DEFAULT '' AFTER `admin_from_email`"); // 8.08
$this->add_column('#__flexicontact_log', 'admin_reply_to_email', "VARCHAR(60) NOT NULL DEFAULT '' AFTER `user_from_email`"); // 8.08
$this->add_column('#__flexicontact_log', 'config_show_copy', "TINYINT(4) NOT NULL DEFAULT 0 AFTER `message`"); // 8.08
$this->add_column('#__flexicontact_log', 'show_copy', "TINYINT(4) NOT NULL DEFAULT 0 AFTER `config_show_copy`"); // 8.08
$this->add_column('#__flexicontact_log', 'agreement_check', "TINYINT(4) NOT NULL DEFAULT 0 AFTER `field5`"); // 12.01
$this->add_column('#__flexicontact_log', 'admin_email_subject', "varchar(255) NOT NULL DEFAULT ''"); // 12.13
$this->add_column('#__flexicontact_log', 'user_email_subject', "varchar(255) NOT NULL DEFAULT ''"); // 12.13
$this->add_column('#__flexicontact_log', 'admin_email_body', "text NOT NULL"); // 13.03
$this->add_column('#__flexicontact_log', 'user_email_body', "text NOT NULL"); // 13.03
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `list_choice` `list_choice` VARCHAR(255) NOT NULL DEFAULT '' "); // 12.13
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `field1` `field1` VARCHAR(255) NOT NULL DEFAULT '' "); // 12.13
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `field2` `field2` VARCHAR(255) NOT NULL DEFAULT '' "); // 12.13
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `field3` `field3` VARCHAR(255) NOT NULL DEFAULT '' "); // 12.13
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `field4` `field4` VARCHAR(255) NOT NULL DEFAULT '' "); // 12.13
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `field5` `field5` VARCHAR(255) NOT NULL DEFAULT '' "); // 12.13
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `ip` `ip` VARCHAR(45) NOT NULL DEFAULT '' "); // 12.15
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `config_show_copy` `config_show_copy` TINYINT(4) NOT NULL DEFAULT 0"); // 13.03
$this->ladb_execute_ignore("ALTER TABLE `#__flexicontact_log` CHANGE `show_copy` `show_copy` TINYINT(4) NOT NULL DEFAULT 0"); // 13.03
// upgrade the component configuration as necessary
$this->upgrade_config();
// check the language files for errors - some older files contain errors
$this->check_language_files('com_flexicontact',true,false);
// if upgrading from a version older than 12.00, show an extra message
if (isset($this->previous_component_version) && (version_compare($this->previous_component_version,"12.00", "<")) )
$this->app->enqueueMessage("If you use the image captcha system, please install one of the (free) image packs. The original 20 images are no longer available.", 'message');
// if com_flexicontact.css exists and matches any released CSS, the user has not customised it so update it to the latest release
// if com_flexicontact.css doesn't exist, this is a new installation, so copy the current default.css to be the live CSS
$live_css_file = JPATH_ROOT.'/media/com_flexicontact/css/com_flexicontact.css';
if (file_exists($live_css_file))
{
$live_css_md5 = md5(file_get_contents($live_css_file));
if (in_array($live_css_md5, array('58c4fe340997c6956f416cb4790235ff','c1e853bab6726257ccca85033d32cd2f','365c5912b758310843b4cb2c05ed7ca1',
'ca4daadec51e46be03fdc295b229e74a','4161cd0efc494f3d07deb7ea9a6d8cec','c3162ae6f32aaabc7d9c37b0d6fcdb40','49b64d42b9a3d17e60946b894a4cf89e')))
copy(JPATH_ROOT.'/media/com_flexicontact/css/default.css', $live_css_file);
}
else
copy(JPATH_ROOT.'/media/com_flexicontact/css/default.css', $live_css_file);
// we are done, show the update or install message
if (isset($this->previous_component_version) && version_compare($this->previous_component_version,$component_version,"<"))
{
$url = 'https://www.lesarbresdesign.info/version-history/flexicontact';
$link = HTMLHelper::link($url, $url, 'target="_blank"');
$this->app->enqueueMessage("Flexicontact updated to version $component_version. Here's what changed: $link", 'message');
}
else
$this->app->enqueueMessage("Flexicontact version $component_version installed.", 'message');
return true;
}
//---------------------------------------------------------------
// Create the log table if it doesn't exist
//
function create_log_table()
{
$query = "CREATE TABLE IF NOT EXISTS `#__flexicontact_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`name` varchar(60) NOT NULL DEFAULT '',
`email` varchar(60) NOT NULL DEFAULT '',
`admin_email` varchar(60) NOT NULL DEFAULT '',
`admin_from_email` varchar(60) NOT NULL DEFAULT '',
`user_from_email` varchar(60) NOT NULL DEFAULT '',
`admin_reply_to_email` varchar(60) NOT NULL DEFAULT '',
`subject` varchar(100) NOT NULL DEFAULT '',
`message` text NOT NULL,
`config_show_copy` TINYINT(4) NOT NULL DEFAULT 0,
`show_copy` TINYINT(4) NOT NULL DEFAULT 0,
`status_main` varchar(255) NOT NULL DEFAULT '',
`status_copy` varchar(255) NOT NULL DEFAULT '',
`ip` varchar(45) NOT NULL DEFAULT '',
`browser_id` tinyint(4) NOT NULL DEFAULT 0,
`browser_string` varchar(20) NOT NULL DEFAULT '',
`list_choice` varchar(255) NOT NULL DEFAULT '',
`field1` varchar(255) NOT NULL DEFAULT '',
`field2` varchar(255) NOT NULL DEFAULT '',
`field3` varchar(255) NOT NULL DEFAULT '',
`field4` varchar(255) NOT NULL DEFAULT '',
`field5` varchar(255) NOT NULL DEFAULT '',
`agreement_check` TINYINT(4) NOT NULL DEFAULT 0,
`admin_email_subject` varchar(255) NOT NULL DEFAULT '',
`user_email_subject` varchar(255) NOT NULL DEFAULT '',
`admin_email_body` text NOT NULL,
`user_email_body` text NOT NULL,
PRIMARY KEY (`id`),
KEY `DATETIME` (`datetime`)
) DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;";
return $this->ladb_execute($query);
}
//-------------------------------------------------------------------------------
// Various upgrades to the component configuration parameters
//
function upgrade_config()
{
$query = "SELECT `params` from `#__extensions` WHERE `type` = 'component' AND `element` = 'com_flexicontact'";
$params = $this->ladb_loadResult($query);
if (($params === false) || (empty($params)) || ($params == '{}'))
return; // there are no component parameters yet
$config_data = json_decode($params);
if (!empty($config_data->agreement_name)) // 12.08 - removed the agreement_name parameter and moved it to the agreement_prompt
{
if (empty($config_data->agreement_prompt))
$config_data->agreement_prompt = '';
$config_data->agreement_prompt .= ' %'.$config_data->agreement_name.'%';
unset($config_data->agreement_name);
}
if (empty($config_data->copyme_prompt)) // 12.14 - added copyme_prompt
$config_data->copyme_prompt = '';
if (empty($config_data->error_class)) // 12.14 - added error_class
$config_data->error_class = '';
// save the config data
$query = "UPDATE `#__extensions` SET `params` = ".$this->db->quote(json_encode($config_data))." WHERE `type` = 'component' AND `element` = 'com_flexicontact'";
$this->ladb_execute($query);
}
//-------------------------------------------------------------------------------
// Check whether a column exists in a table. Returns TRUE if exists, FALSE if it doesn't
//
function column_exists($table, $column)
{
$fields = $this->db->getTableColumns($table);
if ($fields === null)
return false;
if (array_key_exists($column,$fields))
return true;
else
return false;
}
//-------------------------------------------------------------------------------
// Add a column if it doesn't exist (the table must exist)
//
function add_column($table, $column, $details)
{
if ($this->column_exists($table, $column))
return;
$query = 'ALTER TABLE `'.$table.'` ADD `'.$column.'` '.$details;;
return $this->ladb_execute($query);
}
//-------------------------------------------------------------------------------
// Execute a SQL query and return true if it worked, false if it failed
//
function ladb_execute($query)
{
try
{
$this->db->setQuery($query);
$this->db->execute();
}
catch (RuntimeException $e)
{
$message = $e->getMessage();
$this->app->enqueueMessage($message, 'error');
return false;
}
return true;
}
//-------------------------------------------------------------------------------
// Execute a SQL query ignoring any errors
//
function ladb_execute_ignore($query)
{
try
{
$this->db->setQuery($query);
$this->db->execute();
}
catch (RuntimeException $e)
{
return;
}
return;
}
//-------------------------------------------------------------------------------
// Get a single value from the database as an object and return it, or false if it failed
//
function ladb_loadResult($query)
{
try
{
$this->db->setQuery($query);
$result = $this->db->loadResult();
}
catch (RuntimeException $e)
{
$message = $e->getMessage();
$this->app->enqueueMessage($message, 'error');
return false;
}
return $result;
}
//-------------------------------------------------------------------------------
// Delete one or more back end views
//
static function deleteAdminViews($views)
{
foreach ($views as $view)
self::recurse_delete(JPATH_SITE."/administrator/components/com_flexicontact/views/$view");
}
//-------------------------------------------------------------------------------
// Recursively delete a folder and all its contents
//
static function recurse_delete($dir)
{
if (!file_exists($dir))
return;
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file)
if (is_dir($dir.'/'.$file))
self::recurse_delete($dir.'/'.$file);
else
unlink($dir.'/'.$file);
rmdir($dir);
}
// -------------------------------------------------------------------------------
// Check all the language file for errors
//
function check_language_files($component,$admin,$site)
{
$errors = array();
$admin_dirs = array();
$site_dirs = array();
if ($admin)
$admin_dirs = glob(JPATH_ADMINISTRATOR.'/components/'.$component.'/language/*',GLOB_ONLYDIR);
if ($site)
$site_dirs = glob(JPATH_SITE.'/components/'.$component.'/language/*',GLOB_ONLYDIR);
$all_dirs = array_merge($admin_dirs, $site_dirs);
foreach ($all_dirs as $dir)
{
$sub_dir = basename($dir);
$files = glob($dir.'/*.ini');
foreach ($files as $file_name)
if (!self::parseIniFile($file_name))
$errors[] = 'Language file has formatting errors: '.str_replace(JPATH_SITE, '', $file_name);;
}
if (!empty($errors))
$this->app->enqueueMessage(implode('<br>',$errors), 'notice');
}
// -------------------------------------------------------------------------------
// Check a language file for correct syntax
//
static function parseIniFile($filename)
{
if (!is_file($filename))
return false;
$contents = file_get_contents($filename);
$contents = str_replace('_QQ_', '"\""', $contents);
$strings = @parse_ini_string($contents);
if ($strings === false)
return false;
return true;
}
}