From cb20414522b8592319a4a991bc5adbeffb7d194d Mon Sep 17 00:00:00 2001 From: Abu-Huraira Date: Sun, 23 Mar 2025 14:53:36 +0600 Subject: [PATCH 1/3] added core files to repo --- TODO | 0 access.xml | 6 + config.xml | 6 + iquix.php | 71 ++ iquix.xml | 37 + languages/admin/en-GB.com_iquix.ini | 25 + languages/admin/en-GB.com_iquix.sys.ini | 9 + languages/site/en-GB.com_iquix.ini | 9 + script.php | 103 +++ setup.html | 219 +++++ setup/assets/images/quix-logo.png | Bin 0 -> 2330 bytes setup/assets/scripts/script.js | 405 +++++++++ setup/assets/styles/style.css | 59 ++ setup/bootstrap.php | 147 ++++ setup/config/installation.json | 26 + setup/controllers/controller.php | 342 ++++++++ setup/controllers/installation.php | 914 +++++++++++++++++++++ setup/controllers/license.php | 201 +++++ setup/controllers/maintenance.php | 90 ++ setup/controllers/update.php | 103 +++ setup/packages/index.html | 0 setup/views/default.footer.php | 117 +++ setup/views/default.php | 79 ++ setup/views/default.steps.php | 31 + setup/views/steps/complete.php | 27 + setup/views/steps/installing.directory.php | 65 ++ setup/views/steps/installing.network.php | 70 ++ setup/views/steps/installing.php | 18 + setup/views/steps/installing.steps.php | 58 ++ setup/views/steps/maintenance.php | 57 ++ setup/views/steps/requirements.php | 475 +++++++++++ setup/views/steps/source.php | 184 +++++ 32 files changed, 3953 insertions(+) create mode 100644 TODO create mode 100644 access.xml create mode 100644 config.xml create mode 100644 iquix.php create mode 100644 iquix.xml create mode 100644 languages/admin/en-GB.com_iquix.ini create mode 100644 languages/admin/en-GB.com_iquix.sys.ini create mode 100755 languages/site/en-GB.com_iquix.ini create mode 100644 script.php create mode 100644 setup.html create mode 100644 setup/assets/images/quix-logo.png create mode 100644 setup/assets/scripts/script.js create mode 100644 setup/assets/styles/style.css create mode 100644 setup/bootstrap.php create mode 100644 setup/config/installation.json create mode 100644 setup/controllers/controller.php create mode 100644 setup/controllers/installation.php create mode 100644 setup/controllers/license.php create mode 100644 setup/controllers/maintenance.php create mode 100644 setup/controllers/update.php create mode 100644 setup/packages/index.html create mode 100644 setup/views/default.footer.php create mode 100644 setup/views/default.php create mode 100644 setup/views/default.steps.php create mode 100644 setup/views/steps/complete.php create mode 100644 setup/views/steps/installing.directory.php create mode 100644 setup/views/steps/installing.network.php create mode 100644 setup/views/steps/installing.php create mode 100644 setup/views/steps/installing.steps.php create mode 100644 setup/views/steps/maintenance.php create mode 100644 setup/views/steps/requirements.php create mode 100644 setup/views/steps/source.php diff --git a/TODO b/TODO new file mode 100644 index 0000000..e69de29 diff --git a/access.xml b/access.xml new file mode 100644 index 0000000..2506145 --- /dev/null +++ b/access.xml @@ -0,0 +1,6 @@ + + +
+ +
+
diff --git a/config.xml b/config.xml new file mode 100644 index 0000000..065d56e --- /dev/null +++ b/config.xml @@ -0,0 +1,6 @@ + + +
+ +
+
\ No newline at end of file diff --git a/iquix.php b/iquix.php new file mode 100644 index 0000000..0c87fea --- /dev/null +++ b/iquix.php @@ -0,0 +1,71 @@ + 'iquix.log.php'), \JLog::ALL, array('iquix')); +} + + +jimport('joomla.filesystem.folder'); +jimport('joomla.filesystem.file'); + +$app = JFactory::getApplication(); +$input = $app->input; +$exitInstallation = $input->get('exitInstallation', false, 'bool'); + +// Check if there's a file initiated for installation +$file = JPATH_ROOT . '/tmp/quix.installation'; +if ($exitInstallation) { + if (JFile::exists($file)) { + JFile::delete($file); + return $app->redirect('index.php?option=com_quix'); + } +} + +// check if we need to proceed with installation +$launchInstaller = $input->get('launchInstaller', false, 'bool'); +if ($launchInstaller) { + // Determines if the installation is a new installation or old installation. + $obj = new stdClass(); + $obj->new = false; + $obj->step = 1; + $obj->status = 'installing'; + + $contents = json_encode($obj); + + if (!JFile::exists($file)) { + JFile::write($file, $contents); + } +} + +// finally check for setup view or not +// $active = $input->get('active', 0, 'int'); +// if (JFile::exists($file) || $active) { + require_once(dirname(__FILE__) . '/setup/bootstrap.php'); + JExit(); +// } + +// Regular operation starts +// Access check. +// if ( !JFactory::getUser()->authorise( 'core.manage', 'com_iquix' ) ) { +// return JError::raiseWarning( 404, JText::_( 'JERROR_ALERTNOAUTHOR' ) ); +// } + +// Include dependancies +// jimport( 'quix.app.bootstrap' ); +// jimport( 'quix.app.init' ); + +// $controller = JControllerLegacy::getInstance( 'iQuix' ); +// $controller->execute( JFactory::getApplication()->input->get( 'task' ) ); +// $controller->redirect(); diff --git a/iquix.xml b/iquix.xml new file mode 100644 index 0000000..e28fef8 --- /dev/null +++ b/iquix.xml @@ -0,0 +1,37 @@ + + + com_iquix + 11th April 2018 + Copyright (C) 2015. All rights reserved. + GNU General Public License version 2 or later; see LICENSE.txt + ThemeXpert + info@themexpert.com + http://www.themexpert.com + 1.7.0 + Page builder for Joomla + script.php + + + en-GB.com_iquix.ini + + + + + setup + iquix.php + script.php + setup.html + config.xml + iquix.xml + access.xml + + + en-GB.com_iquix.ini + en-GB.com_iquix.sys.ini + + + + + + + diff --git a/languages/admin/en-GB.com_iquix.ini b/languages/admin/en-GB.com_iquix.ini new file mode 100644 index 0000000..688ac7b --- /dev/null +++ b/languages/admin/en-GB.com_iquix.ini @@ -0,0 +1,25 @@ +; @package Quix +; @copyright Copyright (C) 2009 - 2017 Stack Ideas Private Limited. All rights reserved. +; @license GNU/GPL, see LICENSE.php +; Quix is free software. This version may have been modified pursuant to the +; GNU General Public License, and as distributed it includes or is derivative of +; works licensed under the GNU General Public License or other free or open source +; software licenses. See COPYRIGHT.php for copyright notices and details. + +COM_IQUIX="Quix installer" +COM_IQUIX_INSTALLATION_COMPLETE = "Complete" +COM_IQUIX_INSTALLATION_CACHECLEAN_SUCCESS = "Cache cleaned successfully!" + +COM_QUIX_INSTALLATION_FIX_THIS = "Fix this" +COM_QUIX_INSTALLATION_PHP_VERSION_TIPS = "Quix recommand PHP7, but minimum requirement is: 5.6.0" +COM_QUIX_INSTALLATION_PHP_GD_TIPS = "GB library required!" +COM_QUIX_INSTALLATION_PHP_CURL_TIPS = "CURL support required" +COM_QUIX_INSTALLATION_PHP_MAGICQUOTES_TIPS = "PHP Magic quote should be disabled!" +COM_QUIX_INSTALLATION_PHP_MEMORYLIMIT_TIPS = "memory limit must be atleast 64MB" +COM_QUIX_INSTALLATION_MYSQL_VERSION_TIPS = "Minimum required version 5.0.4" +COM_QUIX_INSTALLATION_PHP_ZIP_TIPS = "ZIP extension is required for archive operation." +COM_QUIX_INSTALLATION_PHP_CTYPE_TIPS = "ctype function support is required!" +COM_QUIX_INSTALLATION_PHP_POST_MAX_SIZE_TIPS = "post_max_size php settings min 5MB" +COM_QUIX_INSTALLATION_PHP_MAX_EXECUTION_TIPS = "max_execution_time time config should be minimum 60" +COM_QUIX_INSTALLATION_ALLOW_URL_FOPEN_TIPS="allow_url_fopen is required to Install the package from Online Server." +COM_QUIX_INSTALLATION_FILEINFO_TIPS = "Reading fileinfo is required for installation process." \ No newline at end of file diff --git a/languages/admin/en-GB.com_iquix.sys.ini b/languages/admin/en-GB.com_iquix.sys.ini new file mode 100644 index 0000000..0f8b496 --- /dev/null +++ b/languages/admin/en-GB.com_iquix.sys.ini @@ -0,0 +1,9 @@ +; @package Quix +; @copyright Copyright (C) 2009 - 2017 Stack Ideas Private Limited. All rights reserved. +; @license GNU/GPL, see LICENSE.php +; Quix is free software. This version may have been modified pursuant to the +; GNU General Public License, and as distributed it includes or is derivative of +; works licensed under the GNU General Public License or other free or open source +; software licenses. See COPYRIGHT.php for copyright notices and details. + +COM_IQUIX="Quix Installer" \ No newline at end of file diff --git a/languages/site/en-GB.com_iquix.ini b/languages/site/en-GB.com_iquix.ini new file mode 100755 index 0000000..0f8b496 --- /dev/null +++ b/languages/site/en-GB.com_iquix.ini @@ -0,0 +1,9 @@ +; @package Quix +; @copyright Copyright (C) 2009 - 2017 Stack Ideas Private Limited. All rights reserved. +; @license GNU/GPL, see LICENSE.php +; Quix is free software. This version may have been modified pursuant to the +; GNU General Public License, and as distributed it includes or is derivative of +; works licensed under the GNU General Public License or other free or open source +; software licenses. See COPYRIGHT.php for copyright notices and details. + +COM_IQUIX="Quix Installer" \ No newline at end of file diff --git a/script.php b/script.php new file mode 100644 index 0000000..ac3adba --- /dev/null +++ b/script.php @@ -0,0 +1,103 @@ +new = false; + $obj->step = 1; + $obj->status = 'installing'; + + $contents = json_encode($obj); + + if (!JFile::exists($file)) { + JFile::write($file, $contents); + } + } + + /** + * Responsible to perform the installation + * + * @since 1.0 + * @access public + */ + public function install() + { + $this->createTableConfig(); + } + + /** + * Responsible to perform the uninstallation + * + * @since 1.0 + * @access public + */ + public function uninstall() + { + // @TODO: Disable modules + // @TODO: Disable plugins + } + + /** + * Responsible to perform component updates + * + * @since 1.0 + * @access public + */ + public function update() + { + $this->createTableConfig(); + } + + function createTableConfig() + { + $db = JFactory::getDbo(); + $sql = " + CREATE TABLE IF NOT EXISTS `#__quix_configs` ( + `name` varchar(255) NOT NULL, + `params` text NOT NULL + ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COMMENT='Store any configuration in key => params maps'; + "; + $db->setQuery($sql); + return $db->execute(); + } +} diff --git a/setup.html b/setup.html new file mode 100644 index 0000000..ffbaabd --- /dev/null +++ b/setup.html @@ -0,0 +1,219 @@ + + + +
+
+ + +
+

Thank you for purchasing Quix - Page Builder

+

+ The Most Advanced Responsive First Website Builder For Joomla! In The World. Build anything, simple to complex with drag & drop layout builder. No coding required. +

+ + +
+
+
+
\ No newline at end of file diff --git a/setup/assets/images/quix-logo.png b/setup/assets/images/quix-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7c32704307dfcc6121997e9f5a92b597d2ac17d2 GIT binary patch literal 2330 zcmaJ@X;f2Z8V-tD5Qn0&$RaT*N`NFJAwa?=WMK`mL(2L zf}kx>0kNn>L>7x-X+=HYf>03&Rkn_Rq97tnV#UsnaqhYIe&6?==Xu`so^vw;{5>~m z8*76=piSOh#30oQS3TBWtyjJOBxt0omTe*uO%%+F6p85q0OZc%F#xbPhaLq40d!Vk z+^>K$2(;FUO{Ixw6hAzZ$3f857=(nwSFu4LXEzC-&Wr&>U9TJ6uqcC{YZD$Mq zbU{?!1guDW5Rv@Jm+IsKi57|YcqCFR79+$M1Wyp9;^J^fTQm}lhN}>8VIo&Vm%zC~ z=&Aw{5Hba9zKG4^g4K$21}|RZ0#QZ!R|*{dXIZZBQ<+o+LrUm;Bnn}xPH7cLq5OX+ zhw~XN6a@i)$NN8ph15hofD8hJym$dq)woEg+7%y95CC)$PeA4IVpppe5X}?ugwZ@c zm_Sfh4U52nEh%&+o2xd%KJq9Oyf;@UqH~#mH_-*6QbMrVEW88G0gZJe<1hpq4uv8) z;>Z|V4|jsQy*tj)gNSup|=~PuiU?^I1d=Hp`IbEkdykw zrYE-92x{4R0i$2tF8H3P=qrjNNr`(wWCr4N;Ti0oYQctXuDm(y({`QkH-~(v7=VWRpM` zFql2I;E@b|s$W)BEh;Q3xU0X9=uodg+M{<(mUcel-leVgnc>sAdDk`^_FpQ<>ht$I zUMR~yzdOqiqtNa>xn?Y)MZRF;6I(@=c@lFQ*BoQ@^sQUCa6RbkI6NUEB+w>xY}$g| zG?}ins<$!oHHRk{-eF`oZXb^Q`k*XEksNqC-qkmF0@}e~>|j^?`$~F8k}|g8vj3A# zg55LYx6}R3;n3F7I@+_R@Rz%#M+3ABrld(* zBZg9y)T5O(k^?0$gP*M9SWqY2o;kgAa;^FC5&L)V=miq}`Jb|E{{i$=4`=o&`MvTZ z&0%?&ydWKXP4<|)2KwmvxqF9?b}db9YXBQs59XG3>b`=RuFM%~h5u2Y^Ydnd2YdBm ztcIMFUk5aFR5ZG;V==WhN>jq8qU26niu3W+vDrn|AxUfNjaE`9I?pr=`WF1ki*(9I z>PsJ&bT`vZrl!wL?kXtNzO&yI}i#=&=T%Z1#F5}dQ-ej%Bru+_$vsYC2)DA@SKy4YpsqqM?dxx&B#l@ixr8)Z~ zp72QaP-8d@J`v-ZlIEDT+@2g+>!@h`hIb};I89?bKS352cym7GGW)2HCHQR~^1G+s zhHu=rxzw6I8Y&K6gcjYRGAv#@msPC{XN;a6klq*1DOb1ym}B!-4~&*)VCfg9BD)^e z7WS>T?~_Y@|MiKEW$Z60rzFM8gJQ1!`}A;T%joHl2F!AQaCM81c}Zov!HjrjCC#YH zF(Uh=Ie*iAVd)L5ncpMJ`H49A!;)-i`!0EUvfw2op?}|-rVU{OX!)r3+Uri55K*cT(j>wTqLAhi2SsD3dx!U+mxxHhh0rVUj;9d+~lnz z+hdY{D7av;t=Ra=%31QkQc_uP=hB4zB*d+vU(jIi&9U$bm%6LpVRv?Q&)cWDQA`GJ zCXQT7jw12)XHVZ%lHJj$yRht2Pkeg^jqB@7-}O@acF z5w5K}7(-tEn%e9KJ^{{iHkYIWwtkgY@>6oD$tZnsyrRkD(aCb@RZrMZ58Wp(3)omi zqN1h;ej7isbzI-1>EK9@#oIvM#j4-slRZyGX7Y=>IL~cA=s=c8g9b^lo%pVK@OB#6cenL8EI7gLIQQ)bU=*vL*Kzgh2neo5J5 z*n==-c$^>Px;Q5!E;JzaMJ~IU;qu{1X4|R4!r(rK%9^YDq!AbBb_*?AR$A+aez|jc r0un0Ny>+bf!^CnW`rLF*o2C&6P4h1aX!}`D{kP&x@+a1LL>&DO+M4Hv literal 0 HcmV?d00001 diff --git a/setup/assets/scripts/script.js b/setup/assets/scripts/script.js new file mode 100644 index 0000000..b510e95 --- /dev/null +++ b/setup/assets/scripts/script.js @@ -0,0 +1,405 @@ + +var qx = { + ajaxUrl: "index.php?option=com_iquix&ajax=1", + installation: { + path: null, + ajaxCall: function(task, properties, callback) { + + var prop = $.extend({ + "path": qx.installation.path + }, properties); + + $.ajax({ + type: "POST", + url: qx.ajaxUrl + "&controller=installation&task=" + task , + data: prop + }).done(function(result) { + callback.apply(this, [result]); + }); + }, + + showRetry: function(step) { + $('[data-installation-retry]').data('retry-step', step).show(); + $('[data-installation-loading]').hide(); + }, + + download: function() { + qx.installation.ajaxCall('download', {}, function(result){ + // Set the progress + qx.installation.update( 'data-progress-download' , result , '30%'); + + if (!result.state) { + qx.installation.showRetry('download'); + return false; + } + + // Set the installation path + qx.installation.path = result.path; + qx.installation.cleanCache(); + }); + }, + + cleanCache: function() { + // Install the SQL stuffs + qx.installation.setActive( 'data-progress-cleancache' ); + qx.installation.ajaxCall('cleanCache', {}, function(result) { + + qx.installation.update('data-progress-cleancache', result, '35%'); + if (!result.state) { + qx.installation.showRetry('cleanCache'); + return false; + } + + qx.installation.backupDatabase(); + }); + }, + + backupDatabase: function() { + qx.installation.setActive('data-progress-backup'); + + qx.installation.ajaxCall('backupDatabase' , {} , function(result) { + // Set the progress + qx.installation.update( 'data-progress-backup' , result , '40%'); + + if (!result.state) { + qx.installation.showRetry('backupDatabase'); + return false; + } + + qx.installation.installComponent(); + }); + }, + + installComponent : function() { + // Install the admin stuffs + qx.installation.setActive( 'data-progress-component' ); + + qx.installation.ajaxCall( 'installComponent' , {} , function( result ) + { + // Set the progress + qx.installation.update( 'data-progress-component' , result , '50%'); + + if( !result.state ) + { + qx.installation.showRetry( 'installComponent' ); + return false; + } + + qx.installation.installLibrary(); + }); + }, + + installLibrary : function() { + // Install the admin stuffs + qx.installation.setActive( 'data-progress-library' ); + + qx.installation.ajaxCall( 'installLibrary' , {} , function( result ) + { + // Set the progress + qx.installation.update( 'data-progress-library' , result , '60%'); + + if( !result.state ) + { + qx.installation.showRetry( 'installLibrary' ); + return false; + } + + qx.installation.installModules(); + }); + }, + + + installModules: function() { + // Install the admin stuffs + qx.installation.setActive('data-progress-modules'); + + qx.installation.ajaxCall('installModules', {}, function(result) { + // Set the progress + qx.installation.update('data-progress-modules', result , '70%'); + + if (!result.state) { + qx.installation.showRetry('installModules'); + return false; + } + + qx.installation.installTemplates(); + }); + }, + + installTemplates: function() + { + // Install the admin stuffs + qx.installation.setActive( 'data-progress-plugins' ); + + qx.installation.ajaxCall( 'installTemplates' , {} , function( result ) + { + // Set the progress + qx.installation.update( 'data-progress-templates' , result , '80%'); + + if( !result.state ) + { + qx.installation.showRetry( 'installTemplates' ); + return false; + } + + qx.installation.installPlugins(); + }); + }, + installPlugins: function() + { + // Install the admin stuffs + qx.installation.setActive( 'data-progress-templates' ); + + qx.installation.ajaxCall( 'installPlugins' , {} , function( result ) + { + // Set the progress + qx.installation.update( 'data-progress-plugins' , result , '90%'); + + if( !result.state ) + { + qx.installation.showRetry( 'installPlugins' ); + return false; + } + + qx.installation.syncdb(); + }); + }, + syncdb: function() + { + // Install the admin stuffs + qx.installation.setActive( 'data-progress-syncdb' ); + + qx.installation.ajaxCall( 'syncDb' , {} , function( result ) + { + // Set the progress + qx.installation.update( 'data-progress-syncdb' , result , '95%'); + + if( !result.state ) + { + qx.installation.showRetry( 'syncDb' ); + return false; + } + + qx.installation.postInstall(); + }); + }, + postInstall : function() { + // Install the admin stuffs + qx.installation.setActive( 'data-progress-postinstall' ); + + qx.installation.ajaxCall( 'installPost' , {} , function( result ) + { + // Set the progress + qx.installation.update( 'data-progress-postinstall' , result , '100%'); + + if( !result.state ) + { + qx.installation.showRetry( 'postInstall' ); + return false; + } + + $( '[data-installation-completed]' ).show(); + + $( '[data-installation-loading]' ).hide(); + $( '[data-installation-submit]' ).show(); + + $( '[data-installation-submit]' ).bind( 'click' , function(){ + $( '[data-installation-form]' ).submit(); + }); + + }); + }, + + update : function( element , obj , progress ) + { + var className = obj.state ? ' text-success' : ' text-error', + stateMessage = obj.state ? 'Success' : 'Failed'; + + // Update the state + $( '[' + element + ']' ) + .find( '.progress-state' ) + .html( stateMessage ) + .removeClass( 'text-info' ) + .addClass( className ); + + // Update the message + $( '[' + element + ']' ) + .find( '.notes' ) + .html( obj.message ) + .removeClass( 'text-info' ) + .addClass( className ); + + // Update the progress + qx.installation.updateProgress( progress ); + }, + + updateProgress : function( percentage ) + { + $( '[data-progress-bar]' ).css( 'width' , percentage ); + $( '[data-progress-bar-result]' ).html( percentage ); + }, + + setActive : function( item ) + { + $( '[data-progress-active-message]' ).html( $( '[' + item + ']' ).find( '.split__title' ).html() + ' ...' ); + $( '[' + item + ']' ).removeClass( 'pending' ).addClass( 'active' ); + } + }, + maintenance : + { + init: function() + { + // Initializes the installation process. + qx.maintenance.finalizeMaintenance(); + }, + + finalizeMaintenance: function() + { + var frame = $('[data-progress-finalizing]'); + frame.addClass('active').removeClass('pending'); + + $.ajax({ + type: 'POST', + url: qx.ajaxUrl + '&controller=maintenance&task=cleanInstallation&active=1' + }) + .done(function(result){ + var stateMessage = result.state ? 'Success' : 'Failed'; + + var item = $('
  • '); + item.addClass('text-success').html(result.message); + $('[data-progress-finalizing] .notes ul').append(item); + $('[data-progress-finalizing] .progress-state').html( stateMessage ); + + + qx.maintenance.remoeUpdateRecord(); + }); + }, + + remoeUpdateRecord: function() + { + var frame = $('[data-progress-updaterecord]'); + + frame.addClass('active').removeClass('pending'); + + $.ajax({ + type: 'POST', + url: qx.ajaxUrl + '&controller=maintenance&task=removeUpdateRecord&active=1' + }) + .done(function(result){ + var stateMessage = result.state ? 'Success' : 'Failed'; + var item = $('
  • '); + item.addClass('text-success').html(result.message); + + $('[data-progress-updaterecord] .notes ul').append(item); + $('[data-progress-updaterecord] .progress-state').html( stateMessage ); + + + qx.maintenance.updateAssets(); + }); + }, + + updateAssets: function() + { + var frame = $('[data-progress-updateassets]'); + + frame.addClass('active').removeClass('pending'); + + $.ajax({ + type: 'POST', + url: qx.ajaxUrl + '&controller=maintenance&task=updateAssets&active=1' + }) + .done(function(result){ + var stateMessage = result.state ? 'Success' : 'Failed'; + var item = $('
  • '); + item.addClass('text-success').html(result.message); + + $('[data-progress-updateassets] .notes ul').append(item); + $('[data-progress-updateassets] .progress-state').html( stateMessage ); + + + qx.maintenance.complete(); + }); + }, + + complete: function() { + $('[data-installation-loading]').hide(); + $('[data-installation-submit]').show(); + + $('[data-installation-submit]').on('click', function() { + $('[data-installation-form]').submit(); + }); + } + }, + verification: { + getInfo: function() { + $('[data-licenses]').addClass('hide'); + $('[data-checking]').removeClass('hide'); + qx.installation.ajaxCall('getAuthInfo', {}, function(result){ + // console.log(result.length); + for (var i = 0; i < result.length; i++) { + // console.log(result[i].name); + if(result[i].name == 'username') + { + $('#usernameInput').val(result[i].params); + } + else if(result[i].name == 'key') + { + $('#keyInput').val(result[i].params); + } + } + + $('[data-checking]').addClass('hide'); + $('[data-licenses]').removeClass('hide'); + + }); + }, + }, + core: { + checkUpdate: function() { + jQuery('[data-update-checking]').removeClass('hide'); + jQuery('[data-installation-form]').addClass('hide'); + qx.core.ajaxCall('updateScript', {}, function(result){ + + if(result.state && result.stateMessage == 302) + { + // already uptodate for this session + $('[data-update-checking]').html(result.message); + + location.reload(); + // reload this page + return; + } + else if(result.state) + { + // already uptodate for this session + $('[data-update-checking]').html(result.message); + } + else if(!result.state) + { + console.warn(result.state); + // already uptodate for this session + $('[data-update-checking]').html('
    ' + result.message + '<.div>'); + return; + } + + $('[data-update-checking]').addClass('hide'); + $('[data-installation-form]').removeClass('hide'); + + }); + }, + ajaxCall: function(task, properties, callback) { + + var prop = $.extend({ + "path": qx.installation.path + }, properties); + + $.ajax({ + type: "POST", + url: qx.ajaxUrl + "&controller=update&task=" + task , + data: prop + }).done(function(result) { + callback.apply(this, [result]); + }); + }, + } +} diff --git a/setup/assets/styles/style.css b/setup/assets/styles/style.css new file mode 100644 index 0000000..625f665 --- /dev/null +++ b/setup/assets/styles/style.css @@ -0,0 +1,59 @@ +body{ + background-color: #f8f9fa; + font-family: 'Poppins', sans-serif; + font-size: 14px; + font-weight: 300; + padding-top: 40px; + padding-bottom: 40px; +} +/* Steps */ +.steps{ margin-top: 2rem; margin-left: -3rem; } +.steps .badge{ + width: 40px; height: 40px; + background-color: #343a40; + color: #fff; + padding: 0 !important; + font-size: 16px; + line-height: 40px; +} +.steps > .current > .badge{ background-color: #007bff; } +.steps > .current.done > .badge{ background-color: #20c997; } + +.content{ + position: relative; + min-height: 550px; + padding-bottom: 6rem !important; +} + +/* Footer */ +.footer{ + position: absolute; + left: 0; bottom: 0; + width: 100%; + padding-top: 20px; + padding: 1rem; + background: #fff; + box-shadow: 0px -3px 4px 0px #eee; +} + +.text-error{ color : #ec5f16; } +.list-group-item .text-error{ color : #f3ea66; } +.list-group-item .text-success{ color: #85fba0!important} + +span.label.label-info { + -webkit-font-smoothing: antialiased; + background: #a5b2bd; + border-radius: 2px; + color: #fff; + display: inline-block; + font-size: 11px; + font-style: normal; + font-weight: 700; + line-height: 10px; + padding: 4px 5px; + text-transform: uppercase; + vertical-align: text-top; + -webkit-transition: background-color .25s ease-in-out; + -o-transition: background-color .25s ease-in-out; + transition: background-color .25s ease-in-out; +} \ No newline at end of file diff --git a/setup/bootstrap.php b/setup/bootstrap.php new file mode 100644 index 0000000..bdba0c1 --- /dev/null +++ b/setup/bootstrap.php @@ -0,0 +1,147 @@ +input; + +// Ensure that the Joomla sections don't appear. +$input->set('tmpl', 'component'); + +// Determines if we are now in developer mode. +$developer = $input->get('developer', false, 'bool'); + +if ($developer) { + $session = JFactory::getSession(); + $session->set('quix.developer', true); +} + +############################################################ +#### Constants +############################################################ +$path = __DIR__; +define('QX_PACKAGES', $path . '/packages'); +define('QX_CONFIG', $path . '/config'); +define('QX_THEMES', $path . '/views'); +define('QX_LIB', $path . '/libraries'); +define('QX_CONTROLLERS', $path . '/controllers'); +define('QX_TMP', $path . '/tmp'); + +define('QX_SETUP_URL', rtrim(JURI::root(), '/') . '/administrator/components/com_iquix/setup'); +define('QX_INSTALLER', 'launcher'); +define('QX_PACKAGE', ''); +define('QX_BETA', ''); + +// add constant for product id +define('QX_PRO_ID', '116'); +define('QX_FREE_ID', '117'); +define('QX_EXT_ID', '118'); +define('QX_AGENCY_ID', '127'); +define('QX_BUS_ID', '202'); +define('QX_PRO_LT_ID', '220'); +// Category +define('QX_CATID', '38'); + +// quix api url to check for response +define('QX_SERVER', 'https://www.themexpert.com/index.php?option=com_digicom&task=responses'); + +// download the file api +// &pid=116&username=AAA&key=AAA +define('QX_API_DOWNLOAD', QX_SERVER . '&source=release&format=xml&provider=joomla'); + +// update or release api +// &pid=116 +define('QX_API_UPDATE', QX_SERVER . '&source=release&format=xml&provider=joomla'); + +// license verification api +// &pid=116&username=AAA&key=AAA || catid=QX_CATID +define('QX_API_LICENSE', QX_SERVER . '&source=authapi'); + + +############################################################ +#### Process ajax calls +############################################################ +if ($input->get('ajax', false, 'bool')) { + + $controller = $input->get('controller', '', 'cmd'); + $task = $input->get('task', '', 'cmd'); + + $controllerFile = QX_CONTROLLERS . '/' . strtolower( $controller ) . '.php'; + + require_once($controllerFile); + + $controllerName = 'iQuixController' . ucfirst( $controller ); + $controller = new $controllerName(); + + return $controller->$task(); +} + +############################################################ +#### Process controller +############################################################ +$controller = $input->get('controller', '', 'cmd'); + +if (!empty($controller)) { + $controllerFile = QX_CONTROLLERS . '/' . strtolower($controller) . '.php'; + + require_once($controllerFile); + + $controllerName = 'iQuixController' . ucfirst( $controller ); + $controller = new $controllerName(); + return $controller->execute(); +} + +############################################################ +#### Initialization +############################################################ +$contents = file_get_contents(QX_CONFIG . '/installation.json'); +$steps = json_decode($contents); + +############################################################ +#### Workflow +############################################################ +$active = $input->get('active', 0, 'int'); + +if ($active == 0) { + $active = 1; + $stepIndex = 0; +} else { + $active += 1; + $stepIndex = $active - 1; +} + +if ($active > count($steps)) { + $active = 'complete'; + $activeStep = new stdClass(); + + $activeStep->title = JText::_('Installation Completed'); + $activeStep->template = 'complete'; + + // Assign class names to the step items. + if ($steps) { + foreach ($steps as $step) { + $step->className = ' current done'; + } + } +} else { + // Get the active step object. + $activeStep = $steps[$stepIndex]; + + // Assign class names to the step items. + foreach ($steps as $step) { + $step->className = $step->index == $active || $step->index < $active ? ' current' : ''; + $step->className .= $step->index < $active ? ' done' : ''; + } +} + +require(QX_THEMES . '/default.php'); diff --git a/setup/config/installation.json b/setup/config/installation.json new file mode 100644 index 0000000..657a8ac --- /dev/null +++ b/setup/config/installation.json @@ -0,0 +1,26 @@ +[ + { + "index": 1, + "title": "Requirements", + "desc" : "Server must satisfy Quix requirements", + "template": "requirements" + }, + { + "index": 2, + "title": "Validation", + "desc" : "Authenticate yourself", + "template": "source" + }, + { + "index": 3, + "title": "Installation", + "desc" : "Ignite the thruster", + "template": "installing" + }, + { + "index": 4, + "title": "Maintenance", + "desc" : "Cleaning up the system", + "template": "maintenance" + } +] diff --git a/setup/controllers/controller.php b/setup/controllers/controller.php new file mode 100644 index 0000000..421f0e1 --- /dev/null +++ b/setup/controllers/controller.php @@ -0,0 +1,342 @@ +app = JFactory::getApplication(); + $this->input = $this->app->input; + } + + protected function data($key, $value) + { + $obj = new stdClass(); + $obj->$key = $value; + + $this->result[] = $obj; + } + + /** + * Renders a response with proper headers + * + * @since 2.1.0 + * @access public + */ + public function output($data = array()) + { + header('Content-Type: application/json; UTF-8'); + + if (empty($data)) { + $data = $this->result; + } + + echo json_encode($data); + exit; + } + + /** + * Generates a result object that can be json encoded + * + * @since 2.1.0 + * @access public + */ + public function getResultObj($message, $state, $stateMessage = '') + { + $obj = new stdClass(); + $obj->state = $state; + $obj->stateMessage = $stateMessage; + $obj->message = JText::_($message); + + return $obj; + } + + /** + * Get's the version of this launcher so we know which to install + * + * @since 1.0 + * @access public + */ + public function getVersion() + { + static $version = null; + + // Get the version from the manifest file + if (is_null($version)) { + $contents = file_get_contents(JPATH_ROOT.'/administrator/components/com_iquix/iquix.xml'); + $parser = simplexml_load_string($contents); + $version = $parser->xpath('version'); + $version = (string) $version[0]; + } + + if (JDEBUG) { + \JLog::add("iQuix - version : $version", JLog::DEBUG, 'iquix'); + } + + return $version; + } + + /** + * Retrieve the Joomla Version + * + * @since 2.0 + * @access public + */ + public function getJoomlaVersion() + { + $jVerArr = explode('.', JVERSION); + $jVersion = $jVerArr[0].'.'.$jVerArr[1]; + + if (JDEBUG) { + \JLog::add("iQuix - jVersion : $jVersion", JLog::DEBUG, 'iquix'); + } + + return $jVersion; + } + + /** + * Retrieves the current site's domain information + * + * @since 2.0.9 + * @access public + */ + public function getDomain() + { + static $domain = null; + + if (is_null($domain)) { + $domain = JURI::root(); + $domain = str_ireplace(array('http://', 'https://'), '', $domain); + $domain = rtrim($domain, '/'); + } + + if (JDEBUG) { + \JLog::add("iQuix - Domain : $domain", JLog::DEBUG, 'iquix'); + } + + return $domain; + } + + /** + * Retrieves the information about the latest version + * + * @since 2.0.9 + * @access public + */ + public function getInfo() + { + // Get the md5 hash from the server. + $session = JFactory::getSession(); + $username = $session->get('quix.username', ''); + $key = $session->get('quix.key', ''); + $id = $session->get('quix.id', ''); + + $url = QX_API_LICENSE.'&pid='.$id.'&username='.$username.'&key='.$key; + // &pid=116&username=AAA&key=AAA + + if (JDEBUG) { + \JLog::add("iQuix - Retrieves the information from : $url", JLog::DEBUG, 'iquix'); + } + + $resource = curl_init(); + + $version = $this->getVersion(); + + // We need to pass the api keys to the server + curl_setopt($resource, CURLOPT_URL, $url); + curl_setopt($resource, CURLOPT_POST, false); + // curl_setopt($resource, CURLOPT_POSTFIELDS, 'apikey=' . ES_KEY . '&from=' . $version); + curl_setopt($resource, CURLOPT_TIMEOUT, 120); + curl_setopt($resource, CURLOPT_RETURNTRANSFER, true); + curl_setopt($resource, CURLOPT_SSL_VERIFYPEER, false); + + $result = curl_exec($resource); + + curl_close($resource); + + if (JDEBUG) { + \JLog::add("iQuix - curl server response: ".$result, JLog::DEBUG, 'iquix'); + } + + if ( ! $result) { + return false; + } + + $obj = json_decode($result); + + return $obj; + } + + public function getAuthInfo() + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select('*')->from('#__quix_configs'); + $db->setQuery($query); + $result = $db->loadObjectList(); + + if (JDEBUG) { + \JLog::add("iQuix - userInfo: ".json_encode($result), JLog::DEBUG, 'iquix'); + } + + return $this->output($result); + } + + /** + * Loads the previous version that was installed + * + * @since 1.0 + * @access public + */ + public function getInstalledVersion() + { + $xml = new SimpleXMLElement(file_get_contents(JPATH_ADMINISTRATOR.'/components/com_quix/quix.xml')); + + $version = (string) $xml->version; + + if (JDEBUG) { + \JLog::add("iQuix - NEW COM_QUIX version:".$version, JLog::INFO, 'iquix'); + } + + return $version; + } + + /** + * get a configuration item + * + * @since 1.0 + * @access public + */ + public function getPreviousVersion() + { + $xml = new SimpleXMLElement(file_get_contents(JPATH_ADMINISTRATOR.'/components/com_quix/quix.xml')); + $version = (string) $xml->version; + + if (JDEBUG) { + \JLog::add("iQuix - OLD COM_QUIX version:".$version, JLog::INFO, 'iquix'); + } + + return $version; + + } + + /** + * Determines if we are in development mode + * + * @since 1.2 + * @access public + */ + public function isDevelopment() + { + $session = JFactory::getSession(); + $developer = $session->get('quix.developer'); + + return $developer; + } + + /** + * Verifies the api key + * + * @since 2.1.0 + * @access public + */ + public function verifyApiKey($username, $key) + { + $url = QX_API_LICENSE.'&catid='.QX_CATID.'&username='.$username.'&key='.$key; + // $post = array('username' => $username, 'key' => $key); + if (JDEBUG) { + \JLog::add("iQuix - authAPI Url : ".$url, JLog::DEBUG, 'iquix'); + } + + $httpOption = new JRegistry; + $http = JHttpFactory::getHttp($httpOption); + $str = $http->get($url); + if ($str->code != 200 && $str->code != 310) { + return false; + } + + if (JDEBUG) { + \JLog::add("iQuix - Verifying authAPI:".$str->body, JLog::DEBUG, 'iquix'); + } + + $result = json_decode($str->body); + + return $result; + } + + /** + * Retrieves the extension id + * + * @since 2.0.10 + * @access public + */ + public function getExtensionId($ext = 'pkg_quix') + { + //SELECT * FROM `fl6j4_extensions` WHERE `element` LIKE 'pkg_quix' + $db = JFactory::getDBO(); + $sql = "SELECT * FROM ".$db->quoteName('#__extensions')." WHERE ".$db->quoteName('element')." = ".$db->quote('pkg_quix'); + $db->setQuery($sql); + + // Get the extension id + $extensionId = $db->loadResult(); + + if (JDEBUG) { + \JLog::add("iQuix - pkg_quix Info:".json_encode($extensionId), JLog::DEBUG, 'iquix'); + } + + return $extensionId; + } + + /** + * Retrieves the information about the latest version + * url: com_iquix&task=getReleaseInfo&controller=license&ajax=1 + * + * @since 2.0.9 + * @access public + */ + public function getReleaseInfo() + { + $session = JFactory::getSession(); + $username = $session->get('quix.username', ''); + $key = $session->get('quix.key', ''); + $id = $session->get('quix.id', ''); + + if ( ! $id) { + return false; + } + $update = new JUpdate; + $update->loadFromXml(QX_API_UPDATE.'&pid='.$id, JUpdater::STABILITY_STABLE); + + if (JDEBUG) { + \JLog::add("iQuix - release xml", JLog::DEBUG, 'iquix'); + \JLog::add("iQuix - release xml :".json_encode($update), JLog::DEBUG, 'iquix'); + } + + $downloadUrl = $update->get('downloadurl')->_data ?? null; + if ( ! $downloadUrl) { + return false; + } + + $downloadUrl = $downloadUrl.'&username='.$username.'&key='.$key; + + return $downloadUrl; + } +} diff --git a/setup/controllers/installation.php b/setup/controllers/installation.php new file mode 100644 index 0000000..3a55bb1 --- /dev/null +++ b/setup/controllers/installation.php @@ -0,0 +1,914 @@ +cachecleaner('com_quix'); + $this->cachecleaner('mod_quix'); + $this->cachecleaner('libquix', 1); + $this->cachecleaner('lib_quix', 1); + $this->cachecleaner('lib_quix'); + $this->cachecleaner('quix', 1); + $this->cachecleaner('quix'); + + if (JDEBUG) { + \JLog::add("iQuix - Cleared cache", JLog::INFO, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('COM_IQUIX_INSTALLATION_CACHECLEAN_SUCCESS'), true)); + + } + + public function cachecleaner($group = 'com_quix', $client_id = 0) + { + $conf = \JFactory::getConfig(); + + $options = array( + 'defaultgroup' => $group, + 'cachebase' => $client_id ? JPATH_ADMINISTRATOR.'/cache' : $conf->get('cache_path', JPATH_SITE.'/cache'), + 'result' => true, + ); + + try { + /** @var \JCacheControllerCallback $cache */ + $cache = \JCache::getInstance('callback', $options); + $cache->clean(); + } catch (\JCacheException $exception) { + $options['result'] = false; + } + + // Trigger the onContentCleanCache event. + // \JEventDispatcher::getInstance()->trigger('onContentCleanCache', $options); + JFactory::getApplication()->triggerEvent('onContentCleanCache', $options); + } + + public function checkPackageExtension() + { + $db = JFactory::getDBO(); + // Update installed version + $query = "SELECT * FROM `#__extensions` WHERE `name` = 'pkg_quix' and `type` = 'package'"; + $db->setQuery($query); + $result = $db->loadObject(); + + if ($result->extension_id) { + if (JDEBUG) { + \JLog::add("iQuix - Only Updates, No need to update PKG information", JLog::INFO, 'iquix'); + } + + return true; + } else { + $newVersion = $this->getInstallableVersion(); + + $manifest = '{"name":"pkg_quix","type":"package","creationDate":"2017-07-16","author":"ThemeXpert","copyright":"(C) 2010 - 2016 ThemeXpert. All rights reserved.","authorEmail":"info@themexpert.com","authorUrl":"www.themexpert.com","version":"'.$newVersion.'","description":"PKG_QUIX_XML_DESCRIPTION","group":"","filename":"pkg_quix"}'; + + // new installation, add pkg_quix + $obj = new stdClass(); + $obj->extension_id = ''; + $obj->package_id = 0; + $obj->name = 'pkg_quix'; + $obj->type = 'package'; + $obj->element = 'pkg_quix'; + $obj->enabled = 1; + $obj->access = 1; + $obj->manifest_cache = $manifest; + $obj->params = '{}'; + + // Insert the object into the user profile table. + $result = JFactory::getDbo()->insertObject('#__extensions', $obj); + + if (JDEBUG) { + \JLog::add("iQuix - updated pkg_quix information with status:".$result, JLog::DEBUG, 'iquix'); + } + + if ($result) { + return true; + } else { + return false; + } + } + + } + + public function backupDatabase() + { + $getPackage = $this->checkPackageExtension(); + if ( ! $getPackage) { + + if (JDEBUG) { + \JLog::add("iQuix - backupDatabase failed! ".JText::_('Parent package failed to detect!'), JLog::ERROR, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Parent package failed to detect!'), false)); + } + + $getComponent = \JComponentHelper::getComponent('com_quix'); + if (empty($getComponent->id) or ! $getComponent->id) { + + if (JDEBUG) { + \JLog::add("iQuix - New Installation, No need backup", JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('New installation'), true)); + } + + $version = $this->getPreviousVersion(); + $versionText = str_replace(".", "", $version); + + $app = JFactory::getApplication(); + $prefix = $app->get('dbprefix'); + + $db = JFactory::getDbo(); + $tables = JFactory::getDbo()->getTableList(); + + if ( ! in_array($prefix.'quix', $tables)) { + + if (JDEBUG) { + \JLog::add("iQuix - Database empty, No need backup", JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('No record to backup!'), true)); + } + + try { + $tables = JFactory::getDbo()->getTableList(); + $quixTable = $prefix.'quix'.$versionText; + if ( ! in_array($quixTable, $tables)) { + + $query = "CREATE TABLE IF NOT EXISTS `#__quix$versionText` LIKE `#__quix`;"; + $db->setQuery($query); + $result = $db->execute(); + + $query = "INSERT `#__quix$versionText` SELECT * FROM `#__quix`;"; + $db->setQuery($query); + $db->execute(); + + $query = "CREATE TABLE IF NOT EXISTS `#__quix_collections$versionText` LIKE `#__quix_collections`;"; + $db->setQuery($query); + $db->execute(); + $query = "INSERT `#__quix_collections$versionText` SELECT * FROM `#__quix_collections`;"; + $db->setQuery($query); + $db->execute(); + + $query = "CREATE TABLE IF NOT EXISTS `#__quix_collection_map$versionText` LIKE `#__quix_collection_map`;"; + $db->setQuery($query); + $db->execute(); + $query = "INSERT `#__quix_collection_map$versionText` SELECT * FROM `#__quix_collection_map`;"; + $db->setQuery($query); + $db->execute(); + + $query = "CREATE TABLE IF NOT EXISTS `#__quix_elements$versionText` LIKE `#__quix_elements`;"; + $db->setQuery($query); + $db->execute(); + $query = "INSERT `#__quix_elements$versionText` SELECT * FROM `#__quix_elements`;"; + $db->setQuery($query); + $db->execute(); + + if (JDEBUG) { + \JLog::add("iQuix - Database backup complete, name: ".$prefix.'quix'.$versionText, JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Database backup complete'), true)); + } else { + if (JDEBUG) { + \JLog::add("iQuix - No need backup, already has it. name: ".$prefix.'quix'.$versionText, JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::sprintf('Version %s already has a backup', $version), true)); + } + + } catch (Exception $e) { + if (JDEBUG) { + \JLog::add("iQuix - Database update failed, due to: ".$e->getMessage(), JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + } + } + + /** + * Downloads the file from the server + * + * @since 2.0.9 + * @access public + */ + public function download() + { + $getLatestRelease = $this->getReleaseInfo(); + + if ( ! $getLatestRelease) { + $info = $this->getInfo(); + + if ( ! $info->success) { + $result = new stdClass(); + $result->state = false; + $result->message = $info->message; + + $this->output($result); + exit; + } + if (JDEBUG) { + \JLog::add("iQuix - server FIle Info : ".json_encode($info), JLog::DEBUG, 'iquix'); + } + + // Download the component installer. + $data = $info->data; + + } else { + $data = new stdClass; + $data->download_url = $getLatestRelease; + + if (JDEBUG) { + \JLog::add("iQuix - download url from release : ".json_encode($data), JLog::DEBUG, 'iquix'); + } + } + + if (JDEBUG) { + \JLog::add("iQuix - Lets download : ".json_encode($data), JLog::DEBUG, 'iquix'); + } + + $storage = $this->getDownloadFile($data); + + // This only happens when there is no result returned from the server + if ($storage === false) { + $result = new stdClass(); + $result->state = false; + $result->message = 'There was some errors when downloading the file from the server.'; + + if (JDEBUG) { + \JLog::add("iQuix - downloading failed : ".$result->message, JLog::ERROR, 'iquix'); + } + + $this->output($result); + } + + if (JDEBUG) { + \JLog::add("iQuix - Downloads completed!", JLog::DEBUG, 'iquix'); + } + + // Extract files here. + $tmp = QX_TMP.'/pkg_quix'; + + if (JFolder::exists($tmp)) { + JFolder::delete($tmp); + } + + try { + // Try to extract the files + // $state = JArchive::extract($storage, $tmp); + + // The archive instance + $archive = new Archive(array('tmp_path' => JFactory::getConfig()->get('tmp_path'))); + // Extract the archive + $state = $archive->extract($storage, $tmp); + + } catch (Exception $e) { + $result = new stdClass(); + $result->state = false; + $result->message = 'File extracting error: '.$e->getMessage(); + + $this->output($result); + } + + // If there is an error extracting the zip file, then there is a possibility that the server returned a json string + if ( ! $state) { + + $contents = file_get_contents($storage); + $result = json_decode($contents); + + if (is_object($result)) { + $result->state = false; + + if (JDEBUG) { + \JLog::add("iQuix - File extraction error : ".json_encode($result), JLog::ERROR, 'iquix'); + } + + $this->output($result); + exit; + } + + $result = new stdClass(); + $result->state = false; + $result->message = 'There was some errors when extracting the archive from the server. If the problem still persists, please contact our support team.

    Contact Support'; + + if (JDEBUG) { + \JLog::add("iQuix - File extraction error : ".$result->message, JLog::ERROR, 'iquix'); + } + + $this->output($result); + exit; + } + + + // Get the md5 hash of the stored file + $hash = md5_file($storage); + + // @TODO: update server license plugin to generate md5hash for the file + // Check if the md5 check sum matches the one provided from the server. + // if (!in_array($hash, $info->md5)) { + // $result = new stdClass(); + // $result->state = false; + // $result->message = 'The MD5 hash of the downloaded file does not match. Please contact our support team to look into this.

    Contact Support'; + + // $this->output($result); + // exit; + // } + + // After installation is completed, cleanup all zip files from the site + $this->cleanupZipFiles(dirname($storage)); + if (JDEBUG) { + \JLog::add("iQuix - Installation file downloaded successfully", JLog::DEBUG, 'iquix'); + } + + $result = new stdClass(); + $result->message = 'Installation file downloaded successfully'; + $result->state = $state; + $result->path = $tmp; + + $this->output($result); + } + + /** + * Downloads the installation files from our installation API + * + * @since 2.0.9 + * @access public + */ + public function getDownloadFile($info) + { + // Set the storage page + $storage = QX_PACKAGES.'/pkg_quix.zip'; + + // Delete zip archive if it already exists. + if (JFile::exists($storage)) { + JFile::delete($storage); + } + + $download_url = preg_replace("/^http:/i", "https:", $info->download_url); + + if (JDEBUG) { + \JLog::add("iQuix - downloading ".$download_url, JLog::DEBUG, 'iquix'); + \JLog::add("iQuix - downloading to location ".$storage, JLog::DEBUG, 'iquix'); + } + + set_time_limit(0); + + //This is the file where we save the information + $fp = fopen($storage, 'w+'); + + //Here is the file we are downloading, replace spaces with %20 + $ch = curl_init($download_url); + curl_setopt($ch, CURLOPT_TIMEOUT, 35000); + // write curl response to file + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + // get curl response + $result = curl_exec($ch); + curl_close($ch); + + fclose($fp); + + return $result ? $storage : false; + + } + + + /** + * For users who uploaded the installer and needs a manual extraction + * + * @since 2.0.9 + * @access public + */ + public function extract() + { + // Check the api key from the request + $apiKey = JRequest::getVar('apikey', ''); + + // Construct the storage path + $storage = QX_PACKAGES.'/'.QX_PACKAGE; + $exists = JFile::exists($storage); + + // Test if package really exists + if ( ! $exists) { + $result = new stdClass(); + $result->state = false; + $result->message = 'The component package does not exist on the site.
    Please contact our support team to look into this.'; + + if (JDEBUG) { + \JLog::add("iQuix - $result->message", JLog::ERROR, 'iquix'); + } + $this->output($result); + exit; + } + + // Get the folder name + $folderName = basename($storage); + $folderName = str_ireplace('.zip', '', $folderName); + + // Extract files here. + $tmp = QX_TMP.'/'.$folderName; + + // Ensure that there is no such folders exists on the site + if (JFolder::exists($tmp)) { + JFolder::delete($tmp); + } + + // Try to extract the files + //$state = JArchive::extract($storage, $tmp); + // The archive instance + $archive = new Archive(array('tmp_path' => JFactory::getConfig()->get('tmp_path'))); + // Extract the archive + $state = $archive->extract($storage, $tmp); + + // Regardless of the extraction state, delete the zip file otherwise anyone can download the zip file. + @JFile::delete($storage); + + if ( ! $state) { + $result = new stdClass(); + $result->state = false; + $result->message = 'There was some errors when extracting the zip file'; + + if (JDEBUG) { + \JLog::add("iQuix - $result->message", JLog::ERROR, 'iquix'); + } + + $this->output($result); + exit; + } + + $result = new stdClass(); + + $result->message = 'Installation archive extracted successfully'; + $result->state = $state; + $result->path = $tmp; + + if (JDEBUG) { + \JLog::add("iQuix - $result->message", JLog::DEBUG, 'iquix'); + } + + $this->output($result); + } + + + public function getInstallableVersion() + { + try { + $path = QX_TMP.'/pkg_quix/'.'pkg_quix.xml'; + // echo $path;die; + if (JFile::exists($path)) { + $content = file_get_contents($path); + $xml = simplexml_load_string($content); + + return (string) $xml->version; + } else { + return '2.0.0'; + } + } catch (Exception $e) { + return '2.0.0'; + } + } + + + public function installComponent() + { + // Try to extract the files + $storage = QX_TMP.'/pkg_quix/com_quix.zip'; + $tmp = QX_TMP.'/pkg_quix/com_quix'; + // $state = JArchive::extract($storage, $tmp); + + // The archive instance + $archive = new Archive(array('tmp_path' => JFactory::getConfig()->get('tmp_path'))); + // Extract the archive + $state = $archive->extract($storage, $tmp); + + if (JDEBUG) { + \JLog::add("iQuix - Installing component", JLog::DEBUG, 'iquix'); + } + + if ( ! $state) { + + if (JDEBUG) { + $fileExist = JFile::exists($storage); + \JLog::add("iQuix - Installing component failed! fileurl: $storage, isFileExist: $fileExist", JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('COM_QUIX_INSTALLATION_ERROR_EXTRACT_COMPONENT'), false)); + } + + try { + $app = JFactory::getApplication(); + $app->input->set('installtype', 'folder'); + $app->input->set('install_directory', $tmp); + JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_installer/models'); + $installerModel = JModelLegacy::getInstance('Install', 'InstallerModel'); + $result = $installerModel->install(); + + if ($result) { + if (JDEBUG) { + \JLog::add("iQuix - Component Installed", JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Component installation success!'), true)); + } else { + if (JDEBUG) { + \JLog::add("iQuix - Component Installation failed. Error: ".end($app->getMessageQueue()), JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Installation failed! Error: '.end($app->getMessageQueue())), false)); + } + + if (JDEBUG) { + $fileExist = JFile::exists($storage); + \JLog::add("iQuix - Installing component failed! fileurl: $storage, isFileExist: $fileExist", JLog::DEBUG, 'iquix'); + } + + } catch (Exception $e) { + if (JDEBUG) { + \JLog::add("iQuix - Component Installation failed. Error: ".end($app->getMessageQueue()), JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + } + } + + public function installLibrary() + { + // Try to extract the files + $storage = QX_TMP.'/pkg_quix/lib_quix.zip'; + if ( ! JFile::exists($storage)) { + $storage = QX_TMP.'/pkg_quix/lib_quixnxt.zip'; + + if ( ! JFile::exists($storage)) { + + if (JDEBUG) { + \JLog::add("iQuix - lib_quix does not exist: ".$storage, JLog::DEBUG, 'iquix'); + } + + return $this->output(JText::_('Installation failed! lib_quix does not exist')); + } + + } + + $tmp = QX_TMP.'/pkg_quix/lib_quix'; + //$state = JArchive::extract($storage, $tmp); + // The archive instance + $archive = new Archive(array('tmp_path' => JFactory::getConfig()->get('tmp_path'))); + // Extract the archive + $state = $archive->extract($storage, $tmp); + + if ( ! $state) { + if ( ! JFile::exists($storage)) { + if (JDEBUG) { + \JLog::add("iQuix - FIle does not exist: ".$storage, JLog::DEBUG, 'iquix'); + } + } + + return $this->output($this->getResultObj(JText::_('COM_QUIX_INSTALLATION_ERROR_EXTRACT_LIBRARY'), false)); + } + + try { + $app = JFactory::getApplication(); + $app->input->set('installtype', 'folder'); + $app->input->set('install_directory', $tmp); + JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_installer/models'); + $installerModel = JModelLegacy::getInstance('Install', 'InstallerModel'); + $result = $installerModel->install(); + + if (JDEBUG) { + \JLog::add("iQuix - Library installation status: ".$result, JLog::DEBUG, 'iquix'); + } + + if ($result) { + return $this->output($this->getResultObj(JText::_('Library installation success!'), true)); + } else { + return $this->output($this->getResultObj(JText::_('Installation failed! Error: '.end($app->getMessageQueue())), false)); + } + + } catch (Exception $e) { + if (JDEBUG) { + \JLog::add("iQuix - Library installation error: ".$e->getMessage(), JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + } + } + + public function installModules() + { + $app = JFactory::getApplication(); + $modules = ['mod_quix_menu', 'mod_quix', 'mod_quix_info']; + foreach ($modules as $key => $module) { + // Try to extract the files + $storage = QX_TMP.'/pkg_quix/'.$module.'.zip'; + $tmp = QX_TMP.'/pkg_quix/'.$module; + //$state = JArchive::extract($storage, $tmp); + // The archive instance + $archive = new Archive(array('tmp_path' => JFactory::getConfig()->get('tmp_path'))); + // Extract the archive + $state = $archive->extract($storage, $tmp); + + if ( ! $state) { + return $this->output($this->getResultObj(JText::_('COM_QUIX_INSTALLATION_ERROR_EXTRACT_'.strtoupper($module)), false)); + } + + try { + + $app->input->set('installtype', 'folder'); + $app->input->set('install_directory', $tmp); + JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_installer/models'); + $installerModel = JModelLegacy::getInstance('Install', 'InstallerModel'); + $result = $installerModel->install(); + + if ( ! $result) { + return $this->output($this->getResultObj(JText::_(strtoupper($module).' installation failed! Error: '.end($app->getMessageQueue())), + false)); + } + + } catch (Exception $e) { + return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + } + + } + + return $this->output($this->getResultObj(JText::sprintf('%s Modules installation success!', count($modules)), true)); + } + + + public function installPlugins() + { + $app = JFactory::getApplication(); + $plugins = [ + 'plg_content_quix', + 'plg_editors_xtd_quix', + 'plg_finder_quix', + 'plg_quickicon_quix', + 'plg_quix_content', + 'plg_system_quix', + 'plg_system_seositeattributes' + ]; + foreach ($plugins as $key => $plugin) { + // Try to extract the files + $storage = QX_TMP.'/pkg_quix/'.$plugin.'.zip'; + if ( ! JFile::exists($storage)) { + continue; + } + + $tmp = QX_TMP.'/pkg_quix/'.$plugin; + //$state = JArchive::extract($storage, $tmp); + // The archive instance + $archive = new Archive(array('tmp_path' => JFactory::getConfig()->get('tmp_path'))); + // Extract the archive + $state = $archive->extract($storage, $tmp); + + if ( ! $state) { + return $this->output($this->getResultObj(JText::_('COM_QUIX_INSTALLATION_ERROR_EXTRACT_'.strtoupper($plugin)), false)); + } + + try { + + $app->input->set('installtype', 'folder'); + $app->input->set('install_directory', $tmp); + JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_installer/models'); + $installerModel = JModelLegacy::getInstance('Install', 'InstallerModel'); + $result = $installerModel->install(); + + if ( ! $result) { + return $this->output($this->getResultObj(JText::_(strtoupper($plugin).' installation failed! Error: '.end($app->getMessageQueue())), + false)); + } + + } catch (Exception $e) { + return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + } + + } + + return $this->output($this->getResultObj(JText::sprintf('%s Plugins installation success!', count($plugins)), true)); + } + + public function installTemplates() + { + $app = JFactory::getApplication(); + $templates = [ + 'tpl_atom' + ]; + foreach ($templates as $key => $template) { + // Try to extract the files + $storage = QX_TMP.'/pkg_quix/'.$template.'.zip'; + if ( ! JFile::exists($storage)) { + continue; + } + + $tmp = QX_TMP.'/pkg_quix/'.$template; + //$state = JArchive::extract($storage, $tmp); + + // The archive instance + $archive = new Archive(array('tmp_path' => JFactory::getConfig()->get('tmp_path'))); + // Extract the archive + $state = $archive->extract($storage, $tmp); + + if ( ! $state) { + return $this->output($this->getResultObj(JText::_('COM_QUIX_INSTALLATION_ERROR_EXTRACT_'.strtoupper($template)), false)); + } + + try { + + $app->input->set('installtype', 'folder'); + $app->input->set('install_directory', $tmp); + JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_installer/models'); + $installerModel = JModelLegacy::getInstance('Install', 'InstallerModel'); + $result = $installerModel->install(); + + if ( ! $result) { + return $this->output($this->getResultObj(JText::_(strtoupper($template).' installation failed! Error: '.end($app->getMessageQueue())), + false)); + } + + } catch (Exception $e) { + return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + } + + } + + return $this->output($this->getResultObj(JText::sprintf('%s Templates installation success!', count($templates)), true)); + } + + /** + * Post installation process + * + * @since 1.0 + * @access public + */ + public function syncDb() + { + include QX_TMP."/pkg_quix/pkg.script.php"; + + try { + $script = new pkg_QuixInstallerScript(); + ob_start(); + $script->postflight(array()); + $data = ob_get_contents(); + ob_end_clean(); + + return $this->output($this->getResultObj(JText::_('Updating Database complete!'), true)); + + } catch (Exception $e) { + if (JDEBUG) { + \JLog::add("iQuix - syncDb failed cause: : ".JText::_('Error: '.$e->getMessage()), JLog::DEBUG, 'iquix'); + } + + return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + } + } + + /** + * Post installation process + * + * @since 1.0 + * @access public + */ + public function installPost() + { + $results = array(); + + // Update the api key on the server with the one from the bootstrap + // $this->updateConfig(); + + // update package version + $this->updateJoomlaUpdater(); + + try { + // Cleanup temporary files from the tmp folder + $tmp = dirname(dirname(__FILE__)).'/tmp'; + $folders = JFolder::folders($tmp, '.', false, true); + + if ($folders) { + foreach ($folders as $folder) { + @JFolder::delete($folder); + } + } + + // Update installation package to 'launcher' + $this->updatePackage(); + + $result = new stdClass(); + $result->state = true; + $result->message = "Post operation completed!"; + + + } catch (Exception $e) { + $result = new stdClass(); + $result->state = false; + $result->message = "Post operation failed! but you proceed..."; + + } + + + return $this->output($result); + } + + /** + * Update installation package to launcher package to update issue via update button + * + * @since 2.1.3 + * @access public + */ + public function updatePackage() + { + // now we need to update the QX_INSTALLER to launcher to that the update button will + // work correctly. #1558 + $path = JPATH_ADMINISTRATOR.'/components/com_iquix/setup/bootstrap.php'; + + // Read the contents + $contents = file_get_contents($path); + + $contents = str_ireplace("define('QX_INSTALLER', 'full');", "define('QX_INSTALLER', 'launcher');", $contents); + $contents = preg_replace('/define\(\'QX_PACKAGE\', \'.*\'\);/i', "define('QX_PACKAGE', '');", $contents); + + JFile::write($path, $contents); + } + + /** + * Allows cleanup of installation files + * + * @since 1.3 + * @access public + */ + private function cleanupZipFiles($path) + { + return true; + + $zipFiles = JFolder::files($path, '.zip', false, true); + + if ($zipFiles) { + foreach ($zipFiles as $file) { + @JFile::delete($file); + } + } + + return true; + } + + + public function updateJoomlaUpdater() + { + $version = $this->getInstallableVersion(); + + $db = JFactory::getDBO(); + // Update installed version + $query = "SELECT * FROM `#__extensions` WHERE `name` = 'pkg_quix' and `type` = 'package'"; + $db->setQuery($query); + $result = $db->loadObject(); + + $manifest = json_decode($result->manifest_cache); + $manifest->version = $version; + + $result->manifest_cache = json_encode($manifest); + + return JFactory::getDbo()->updateObject('#__extensions', $result, 'extension_id'); + } + +} diff --git a/setup/controllers/license.php b/setup/controllers/license.php new file mode 100644 index 0000000..aa2ca38 --- /dev/null +++ b/setup/controllers/license.php @@ -0,0 +1,201 @@ +input; + $session = JFactory::getSession(); + $username = $input->get('username', '', 'string'); + $key = $input->get('key', '', 'string'); + + if(JDEBUG){ + \JLog::add("iQuix - Verifing credentials, Username: `$username` and Auth Key: `$key`", JLog::DEBUG, 'iquix'); + } + + // keep the credentials + $session->set('quix.username', $username); + $session->set('quix.key', $key); + + // Verify the key + $result = new stdClass(); + $response = $this->verifyApiKey($username, $key); + + if ($response === false or !$response->success) { + $result->state = 400; + $result->message = JText::_('Unable to verify your license or your hosting provider has blocked outgoing connections. Details: ' . $response->message); + + if(JDEBUG){ + \JLog::add("iQuix - Verification faild. Message: $response->message", JLog::ERROR, 'iquix'); + } + + return $this->output($result); + } + + // store config + $this->updateConfig($username, $key); + if(JDEBUG){ + \JLog::add("iQuix - Config updated to #__quix_configs", JLog::INFO, 'iquix'); + } + + $validLicense = $this->getValidLicense($response); + if(JDEBUG){ + \JLog::add(json_encode($validLicense), JLog::DEBUG, 'iquix'); + } + // json_encode(['hasPro' => true, 'hasFree' => false, 'hasLicense' => true, 'name' => $proProduct, 'id' => $proID]); + + if (!$validLicense['hasLicense']) { + $result->state = 403; + $result->message = JText::_('No valid Quix license found! Chances are, you\'ve entered wrong credentials or you did not purchase Quix yet.'); + \JLog::add("iQuix - $result->message", JLog::WARNING, 'iquix'); + return $this->output($result); + } + + if ($validLicense['hasLicense'] && $validLicense['hasPro']) { + $result->state = 200; + $response->html = ''; + $result->message = JText::_('Great! ' . $validLicense['name'] . ' license found. Please click next to continue installation.'); + \JLog::add("iQuix - $result->message", JLog::INFO, 'iquix'); + return $this->output($result); + } + + if ($validLicense['hasLicense'] && $validLicense['hasFree']) { + $result->state = 200; + $response->html = ''; + $result->message = JText::_('Quix free license found. Please click next to continue installation.'); + \JLog::add("iQuix - $result->message", JLog::INFO, 'iquix'); + return $this->output($result); + } + } + + /** + * Saves a configuration item + * + * @since 1.0 + * @access public + */ + public function updateConfig($username, $authkey) + { + // dont allow empty request + if(empty($username) or empty($authkey)) + { + return; + } + + $db = JFactory::getDbo(); + $query = $db->getQuery(true); + $query->select('*') + ->from('#__quix_configs'); + $db->setQuery($query); + $result = $db->loadObjectList(); + if(!count($result)){ + // set all, incert + $obj = new stdClass(); + $obj->name = 'username'; + $obj->params = $username; + // Insert the object into the user obj table. + $result = JFactory::getDbo()->insertObject('#__quix_configs', $obj); + + $obj = new stdClass(); + $obj->name = 'key'; + $obj->params= $authkey; + + // Insert the object into the user obj table. + $result = JFactory::getDbo()->insertObject('#__quix_configs', $obj); + } + else + { + foreach ($result as $key => $item) { + if($item->name == 'username'){ + // Create an object for the record we are going to update. + $obj = new stdClass(); + $obj->name = 'username'; + $obj->params = $username; + + // Update their details in the users table using id as the primary key. + $result = JFactory::getDbo()->updateObject('#__quix_configs', $obj, 'name'); + } + if($item->name == 'key'){ + // Create an object for the record we are going to update. + $obj = new stdClass(); + $obj->name = 'key'; + $obj->params = $authkey; + + // Update their details in the users table using id as the primary key. + $result = JFactory::getDbo()->updateObject('#__quix_configs', $obj, 'name'); + } + + } + } + + return true; + + } + + public function getValidLicense($data) + { + $session = JFactory::getSession(); + $products = $data->data; + $quixPro = [QX_AGENCY_ID, QX_PRO_ID, QX_EXT_ID, QX_BUS_ID, QX_PRO_LT_ID]; + $hasPro = false; + $hasFree = false; + $proProduct = ''; + $proID = 0; + + foreach ($products as $key => $product) + { + if(in_array($product->id, $quixPro, true) && ($product->has_access === true)) + { + $hasPro = true; + $proProduct = $product->name; + $proID = $product->id; + + break; + } + + if($product->id == QX_FREE_ID && $product->has_access === true) + { + $hasFree = true; + $session->set('quix.hasFree', true); + } + } + + // now return result + if($hasPro) + { + $session->set('quix.id', $proID); + $session->set('quix.hasLicense', true); + return array('hasPro' => true, 'hasFree' => $hasFree, 'hasLicense' => true, 'name' => $proProduct, 'id' => $proID); + } + elseif($hasFree) + { + $session->set('quix.id', QX_FREE_ID); + $session->set('quix.hasLicense', true); + return array('hasPro' => false, 'hasFree' => true, 'hasLicense' => true); + } + else + { + $session->set('quix.hasLicense', false); + return array('hasPro' => false, 'hasFree' => false, 'hasLicense' => false); + } + } +} \ No newline at end of file diff --git a/setup/controllers/maintenance.php b/setup/controllers/maintenance.php new file mode 100644 index 0000000..9eb3a38 --- /dev/null +++ b/setup/controllers/maintenance.php @@ -0,0 +1,90 @@ +getResultObj('Updated maintenance version.', 1, 'success'); + + return $this->output($result); + } + + public function removeUpdateRecord() + { + $db = JFactory::getDBO(); + $query = 'DELETE FROM ' . $db->quoteName('#__updates') . ' WHERE ' . $db->quoteName('extension_id') . '=' . $db->Quote($this->getExtensionId()); + $db->setQuery($query); + $result = $db->execute(); + if($result) + { + $msg = $this->getResultObj('Update record cleaned!', true, 'success'); + } + else + { + $msg = $this->getResultObj('Unable to clean update record!', false, 'fail'); + } + + return $this->output($msg); + } + + public function updateAssets() + { + // cache assets + $token = JSession::getFormToken() . '=' . 1; + $ajax_url = 'index.php?option=com_quix&task=updateAjax&' . $token; + + try { + $http = new JHttp(); + $str = $http->get($ajax_url); + + if ($str->code != 200 && $str->code != 310) + { + $result = false; + } + else + { + $result = true; + } + } catch (Exception $e) { + // nothing to show now, lets ignore + $result = true; + } + + if($result) + { + $msg = $this->getResultObj('Updating assets completed!!', true, 'success'); + } + else + { + $msg = $this->getResultObj('Unable to update assets!', false, 'fail'); + } + + + if(JDEBUG){ + \JLog::add("iQuix - updateAssets status: " . $result, JLog::DEBUG, 'iquix'); + } + + return $this->output($msg); + } +} \ No newline at end of file diff --git a/setup/controllers/update.php b/setup/controllers/update.php new file mode 100644 index 0000000..7997e48 --- /dev/null +++ b/setup/controllers/update.php @@ -0,0 +1,103 @@ +set('quix.scriptupdate', false); + $scriptupdate = $session->get('quix.scriptupdate', false); + if($scriptupdate) + { + $this->output($this->getResultObj( 'Already checked!' , true )); + } + + // 1. get current version + $localVersion = $this->getVersion(); + // 2. get latest version info from server + $xml = $this->getLatestVersion(); + + $update = $xml->update[0]; // first one is the latest one + if(isset($update->version)) + { + $onlineVersion = (string) $update->version; + } + else + { + $onlineVersion = '1.0.0'; + } + + $session->set('quix.scriptupdate', true); + + // 3. match versions + if(version_compare($onlineVersion, $localVersion) == '1') + { + $result = $this->installScriptComponent($update); + if($result) + { + $this->output($this->getResultObj( 'Updated successfully!' , true , 302)); + } + else + { + $this->output($this->getResultObj( 'Something wrong to update the script! please manually install the Installer.' , false )); + } + } + else + { + // need to update the script + // either we have updated or same + $this->output($this->getResultObj( 'You have the latest version' , true )); + } + } + + public function getLatestVersion() + { + $ch = curl_init('https://raw.githubusercontent.com/themexpert/iquix/master/mainfest.xml'); + + curl_setopt($ch, CURLOPT_POST, false); + // curl_setopt($ch, CURLOPT_POSTFIELDS, 'key=' . QX_KEY . '&version=' . $info->version); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 35000); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + $contents = curl_exec($ch); + curl_close($ch); + + $xml = simplexml_load_string( $contents ); + + return $xml; + } + + public function installScriptComponent($update) + { + try { + $app = JFactory::getApplication(); + $app->input->set('installtype', 'url'); + $app->input->set('install_url', $update->downloads->downloadurl); //install_directory + JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_installer/models'); + $installerModel = JModelLegacy::getInstance('Install', 'InstallerModel'); + return $installerModel->install(); + } catch (Exception $e) { + return $this->output($this->getResultObj( JText::_( 'Error: ' . $e->getMessage() ) , false )); + } + } +} \ No newline at end of file diff --git a/setup/packages/index.html b/setup/packages/index.html new file mode 100644 index 0000000..e69de29 diff --git a/setup/views/default.footer.php b/setup/views/default.footer.php new file mode 100644 index 0000000..2584532 --- /dev/null +++ b/setup/views/default.footer.php @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + diff --git a/setup/views/default.php b/setup/views/default.php new file mode 100644 index 0000000..4b8227a --- /dev/null +++ b/setup/views/default.php @@ -0,0 +1,79 @@ + + + + + + + + Installing Quix Visual Builder + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    + + + + + + + + +
    +
    +
    + +
    +
    +
    +
    + template . '.php'); ?> + + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    + + diff --git a/setup/views/default.steps.php b/setup/views/default.steps.php new file mode 100644 index 0000000..386f473 --- /dev/null +++ b/setup/views/default.steps.php @@ -0,0 +1,31 @@ + + + +
    + index);?> +
    +

    title);?>

    +

    desc);?>

    +
    +
    + + +
    + +
    +

    +

    You are ready to go

    +
    +
    \ No newline at end of file diff --git a/setup/views/steps/complete.php b/setup/views/steps/complete.php new file mode 100644 index 0000000..daf2fdc --- /dev/null +++ b/setup/views/steps/complete.php @@ -0,0 +1,27 @@ + +
    +

    🎊

    + +

    Installation Completed

    +
    + +

    Congratulations! Quix has been successfully installed on your site and you may start using it.

    + +
    + + + + +
    \ No newline at end of file diff --git a/setup/views/steps/installing.directory.php b/setup/views/steps/installing.directory.php new file mode 100644 index 0000000..fcadc9a --- /dev/null +++ b/setup/views/steps/installing.directory.php @@ -0,0 +1,65 @@ + +
    +

    We are now performing the installation of Quix on the site. This process may take a little + while depending on the Internet connectivity of your server. While we are at it, you should get some coffee ... +

    + +
    +
    +
    Installation completed successfully. Please click on the Next Step button to proceed. +
    +
    + +
    + +
    +
    +
    +
    Extracting component files
    +
    +
    +
    20%
    +
    +
    + +
    +
    +
    +
    +
    + + +
      +
    1. + Extracting component files + Extracting +
      +
    2. + + +
    +
    + + + +
    + + \ No newline at end of file diff --git a/setup/views/steps/installing.network.php b/setup/views/steps/installing.network.php new file mode 100644 index 0000000..8725ca5 --- /dev/null +++ b/setup/views/steps/installing.network.php @@ -0,0 +1,70 @@ + +
    + +
    +

    Installing Quix

    +

    We are now performing the installation of Quix on the site. This process may take a little + while depending on the Internet connectivity of your server. While we are at it, you should get some coffee + ...

    +
    + + + +
    + +
    +
    +
    Installing Quix Pagebuilder
    +
    20%
    +
    +
    +
    +
    +
    + + +
      +
    • + Downloading Installation Files... + Downloading +
      +
    • + + +
    +
    + + + + + + +
    + + \ No newline at end of file diff --git a/setup/views/steps/installing.php b/setup/views/steps/installing.php new file mode 100644 index 0000000..6b1fb86 --- /dev/null +++ b/setup/views/steps/installing.php @@ -0,0 +1,18 @@ +get('method', '', 'default'); +$file = __DIR__ . '/installing.' . $method . '.php'; + +include_once(__DIR__ . '/installing.' . $method . '.php'); \ No newline at end of file diff --git a/setup/views/steps/installing.steps.php b/setup/views/steps/installing.steps.php new file mode 100644 index 0000000..5c8a147 --- /dev/null +++ b/setup/views/steps/installing.steps.php @@ -0,0 +1,58 @@ + +
  • + Cleaning cache + Waiting +
    +
  • +
  • + Backup Database + Waiting +
    +
  • +
  • + Initializing Component + Waiting +
    +
  • +
  • + Initializing Library + Waiting +
    +
  • +
  • + Initializing Modules + Waiting +
    +
  • +
  • + Initializing Plugins + Waiting +
    +
  • +
  • + Initializing Templates + Waiting +
    +
  • +
  • + Initializing Database Synchronization + Waiting +
    +
  • +
  • + Post Installation Cleanup + Waiting +
    +
  • diff --git a/setup/views/steps/maintenance.php b/setup/views/steps/maintenance.php new file mode 100644 index 0000000..b54d472 --- /dev/null +++ b/setup/views/steps/maintenance.php @@ -0,0 +1,57 @@ + +
    + +
    +

    Maintenance

    +

    We will need to update some scripts for installation.

    +
    + + +
    +
      +
    • + Finalizing installation + Executing +
      +
        +
        +
      • +
      • + Remove update record + Executing +
        +
          +
          +
        • +
        • + Update assets + Executing +
          +
            +
            +
          • +
          +
          + + + +
          + + \ No newline at end of file diff --git a/setup/views/steps/requirements.php b/setup/views/steps/requirements.php new file mode 100644 index 0000000..088f883 --- /dev/null +++ b/setup/views/steps/requirements.php @@ -0,0 +1,475 @@ +getVersion(); + +//########################################### +//# PHP info +//########################################### +$phpVersion = phpversion(); +$memoryLimit = ini_get('memory_limit'); +$postSize = (int) ini_get('post_max_size'); +$max_execution = ini_get('max_execution_time'); +$allow_url_fopen = ini_get('allow_url_fopen'); + +$hasErrors = false; + +if (stripos($memoryLimit, 'G') !== false) { + list($memoryLimit) = explode('G', $memoryLimit); + $memoryLimit = $memoryLimit * 1024; +} + +if (!$gd || !$curl || !$ctype || !$fileinfo || !$allow_url_fopen || $postSize < 5 || $max_execution < 30) { + $hasErrors = true; +} + +//######################################### +//# Paths +//######################################### +$files = []; + +$files['admin'] = new stdClass(); +$files['admin']->path = JPATH_ROOT . '/administrator/components'; + +$files['admin_modules'] = new stdClass(); +$files['admin_modules']->path = JPATH_ROOT . '/administrator/modules'; + +$files['site'] = new stdClass(); +$files['site']->path = JPATH_ROOT . '/components'; + +$files['tmp'] = new stdClass(); +$files['tmp']->path = JPATH_ROOT . '/tmp'; + +$files['media'] = new stdClass(); +$files['media']->path = JPATH_ROOT . '/media'; + +$files['libraries'] = new stdClass(); +$files['libraries']->path = JPATH_ROOT . '/libraries'; + +$files['system'] = new stdClass(); +$files['system']->path = JPATH_ROOT . '/plugins/system'; + +$files['content'] = new stdClass(); +$files['content']->path = JPATH_ROOT . '/plugins/content'; + +$files['finder'] = new stdClass(); +$files['finder']->path = JPATH_ROOT . '/plugins/finder'; + +$files['quickicon'] = new stdClass(); +$files['quickicon']->path = JPATH_ROOT . '/plugins/quickicon'; + +$files['editors_xtd'] = new stdClass(); +$files['editors_xtd']->path = JPATH_ROOT . '/plugins/editors_xtd'; + +$files['auth'] = new stdClass(); +$files['auth']->path = JPATH_ROOT . '/modules'; + +$files['cache'] = new stdClass(); +$files['cache']->path = JPATH_ROOT . '/cache'; + +//######################################### +//# Determine states +//######################################### +// $hasErrors = false; + +foreach ($files as $file) { + // The only proper way to test this is to not use is_writable + $contents = ''; + $state = JFile::write($file->path . '/tmp.html', $contents); + + // Initialize this to false by default + $file->writable = false; + + if ($state) { + JFile::delete($file->path . '/tmp.html'); + + $file->writable = true; + } + + if (!$file->writable) { + $hasErrors = true; + } +} +?> + + +
          +
          +   + Checking update script... +
          +
          + +
          +

          Requirements

          +
          + +
          + +

          👍 Awesome! The minimum requirements are met. You may proceed with the installation + process now.

          + + +

          + Some of the requirements below are not met. Please ensure that all of the requirements below are met. +

          + +

          + New License validation updated. +

          + +
          +
          + +
          +
          + +
          +
          + +

          + Need help about requirements? You might want check this link or our + Docs Home. +

          +

          + New License validation updated. +

          + + + + +
          + +get('quix.scriptupdate', false); +if (!$checkUpdate): ?> + +get('quix.hasLicense', false); +$hasFree = $session->get('quix.hasFree', false); +$hasLicense = $hasLicensepro; + +// we have to check for free license only for now, as this is the only version +// if($hasLicensepro && $hasFree){ +// $hasLicense = true; +// } +?> + +
          + + +
          +

          Unable to validate 🙇🏻

          +

          + Sorry, but the API key that you have provided does not have a valid subscription. Please try again, or if you still have technical difficulties, please contact our support team. +

          +
          + Try Again + Contact Support +
          + + +
          +

          🕺

          +

          Let's get started

          +

          + +

          +
          + + +
          +
          +

          Input your credentials

          +
          +
          + + + Input your ThemeXpert username here. +
          +
          + + + Don't have any Auth Key ? Generate it from ThemeXpert Dashboard. +
          + Validate + +
          + + +
          + +
          +
          +
          +
          +
          Checking for license...
          +
          + + + + + + +
          + + + +
          + From e1a4cb78604ad3f3d923c83ddf84877bf7c46ca7 Mon Sep 17 00:00:00 2001 From: Abu-Huraira Date: Sun, 23 Mar 2025 19:16:24 +0600 Subject: [PATCH 2/3] installation with debug improvement --- README.md | 21 +- iquix.php | 66 ++- iquix.xml | 2 +- mainfest.xml | 16 + setup/assets/scripts/script.js | 36 +- setup/bootstrap.php | 228 ++++++---- setup/controllers/controller.php | 506 ++++++++++++++++------- setup/controllers/installation.php | 315 ++++++-------- setup/controllers/license.php | 380 ++++++++++------- setup/controllers/maintenance.php | 164 +++++--- setup/controllers/update.php | 153 ++++++- setup/views/default.footer.php | 34 +- setup/views/steps/installing.network.php | 1 + setup/views/steps/installing.steps.php | 10 +- setup/views/steps/requirements.php | 79 ++-- setup/views/steps/source.php | 4 +- 16 files changed, 1310 insertions(+), 705 deletions(-) diff --git a/README.md b/README.md index 6ab730e..028d6ce 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,21 @@ #Quix Launcher -Quix Launcher to install and validate quix \ No newline at end of file +Quix Launcher to install and validate quix + + +### Release Instructions + +**Update `mainfest.xml`:** +1. Update the version number. +2. Update the download link. + +**Update `iquix.php`:** +1. Update the version number. + +**Create a ZIP Archive**: +1. Zip the entire directory, excluding `mainfest.xml`, `todo`, `.gitignore`, and `README.md`. + + +### **Upload ZIP Archive**: +```cmd +zip -r com_iquix_1.8.0.zip . -x "mainfest.xml" "todo" ".gitignore" "README.md" +``` diff --git a/iquix.php b/iquix.php index 0c87fea..37b525c 100644 --- a/iquix.php +++ b/iquix.php @@ -1,34 +1,35 @@ 'iquix.log.php'), \JLog::ALL, array('iquix')); -} - +use Joomla\CMS\Factory; +use Joomla\CMS\Filesystem\File; +use Joomla\CMS\Log\Log; +// define version +define('IQX_VERSION', '1.8.0'); -jimport('joomla.filesystem.folder'); -jimport('joomla.filesystem.file'); +if (defined('JDEBUG') && JDEBUG) { + Log::addLogger(array('text_file' => 'iquix.log.php'), Log::ALL, array('iquix')); +} -$app = JFactory::getApplication(); +$app = Factory::getApplication(); $input = $app->input; $exitInstallation = $input->get('exitInstallation', false, 'bool'); // Check if there's a file initiated for installation $file = JPATH_ROOT . '/tmp/quix.installation'; if ($exitInstallation) { - if (JFile::exists($file)) { - JFile::delete($file); + if (File::exists($file)) { + File::delete($file); return $app->redirect('index.php?option=com_quix'); } } @@ -44,28 +45,11 @@ $contents = json_encode($obj); - if (!JFile::exists($file)) { - JFile::write($file, $contents); - } + if (!File::exists($file)) { + File::write($file, $contents); + } } // finally check for setup view or not -// $active = $input->get('active', 0, 'int'); -// if (JFile::exists($file) || $active) { - require_once(dirname(__FILE__) . '/setup/bootstrap.php'); - JExit(); -// } - -// Regular operation starts -// Access check. -// if ( !JFactory::getUser()->authorise( 'core.manage', 'com_iquix' ) ) { -// return JError::raiseWarning( 404, JText::_( 'JERROR_ALERTNOAUTHOR' ) ); -// } - -// Include dependancies -// jimport( 'quix.app.bootstrap' ); -// jimport( 'quix.app.init' ); - -// $controller = JControllerLegacy::getInstance( 'iQuix' ); -// $controller->execute( JFactory::getApplication()->input->get( 'task' ) ); -// $controller->redirect(); +require_once(dirname(__FILE__) . '/setup/bootstrap.php'); +JExit(); \ No newline at end of file diff --git a/iquix.xml b/iquix.xml index e28fef8..17b4f11 100644 --- a/iquix.xml +++ b/iquix.xml @@ -7,7 +7,7 @@ ThemeXpert info@themexpert.com http://www.themexpert.com - 1.7.0 + 1.8.0 Page builder for Joomla script.php diff --git a/mainfest.xml b/mainfest.xml index 5c768d8..5c74aa1 100644 --- a/mainfest.xml +++ b/mainfest.xml @@ -1,5 +1,21 @@ + + Quix Launcher + iQuix is an installer extension + com_iquix + component + 1.8.0 + site + https://github.com/themexpert/iquix/releases/tag/v1.8.0 + + https://github.com/themexpert/iquix/releases/download/v1.8.0/com_iquix_1.8.0.zip + + + stable + + + Quix Launcher iQuix is an installer extension diff --git a/setup/assets/scripts/script.js b/setup/assets/scripts/script.js index b510e95..44f91fe 100644 --- a/setup/assets/scripts/script.js +++ b/setup/assets/scripts/script.js @@ -1,4 +1,3 @@ - var qx = { ajaxUrl: "index.php?option=com_iquix&ajax=1", installation: { @@ -50,7 +49,9 @@ var qx = { return false; } - qx.installation.backupDatabase(); + // qx.installation.backupDatabase(); + // Move to the next step + qx.installation.installComponent(); }); }, @@ -403,3 +404,34 @@ var qx = { }, } } + +/** + * Download debug log functionality + */ +qx.debug = { + /** + * Initialize debug log download functionality + * @returns {void} + */ + init: function() { + $(document).on('click', '#debug[data-installation-debug]', function(e) { + e.preventDefault(); + qx.debug.downloadLog(); + }); + }, + + /** + * Download the debug log file directly + * @returns {void} + */ + downloadLog: function() { + // Create a download link and navigate directly to file download URL + window.location.href = qx.ajaxUrl + "&controller=license&task=downloadDebugLog"; + } +} + +// Initialize debug functionality when document is ready +$(document).ready(function() { + // Initialize debug log download + qx.debug.init(); +}); diff --git a/setup/bootstrap.php b/setup/bootstrap.php index bdba0c1..fee3234 100644 --- a/setup/bootstrap.php +++ b/setup/bootstrap.php @@ -1,29 +1,59 @@ 'iquix.log.php'], Log::ALL, ['iquix']); + Log::add('iQuix - Bootstrap initialization started', Log::DEBUG, 'iquix'); +} -$app = JFactory::getApplication(); +// Get application and input objects +$app = Factory::getApplication(); $input = $app->input; -// Ensure that the Joomla sections don't appear. +// Ensure that the Joomla sections don't appear $input->set('tmpl', 'component'); -// Determines if we are now in developer mode. +// Get Joomla version +$jVersion = (new Version())->getShortVersion(); +$isJoomla4OrAbove = version_compare($jVersion, '4.0', '>='); +$isJoomla5OrAbove = version_compare($jVersion, '5.0', '>='); + +if (defined('JDEBUG') && JDEBUG) { + Log::add('iQuix - Joomla Version: ' . $jVersion, Log::DEBUG, 'iquix'); + Log::add('iQuix - Is Joomla 4+: ' . ($isJoomla4OrAbove ? 'Yes' : 'No'), Log::DEBUG, 'iquix'); + Log::add('iQuix - Is Joomla 5+: ' . ($isJoomla5OrAbove ? 'Yes' : 'No'), Log::DEBUG, 'iquix'); +} + +// Determines if we are now in developer mode $developer = $input->get('developer', false, 'bool'); if ($developer) { - $session = JFactory::getSession(); - $session->set('quix.developer', true); + $session = $isJoomla4OrAbove ? $app->getSession() : Factory::getSession(); + $session->set('quix.developer', true); + + if (defined('JDEBUG') && JDEBUG) { + Log::add('iQuix - Developer mode enabled', Log::DEBUG, 'iquix'); + } } ############################################################ @@ -37,12 +67,13 @@ define('QX_CONTROLLERS', $path . '/controllers'); define('QX_TMP', $path . '/tmp'); -define('QX_SETUP_URL', rtrim(JURI::root(), '/') . '/administrator/components/com_iquix/setup'); +// Use Uri class for Joomla 4/5 compatibility +define('QX_SETUP_URL', rtrim(Uri::root(), '/') . '/administrator/components/com_iquix/setup'); define('QX_INSTALLER', 'launcher'); define('QX_PACKAGE', ''); define('QX_BETA', ''); -// add constant for product id +// Add constant for product id define('QX_PRO_ID', '116'); define('QX_FREE_ID', '117'); define('QX_EXT_ID', '118'); @@ -52,38 +83,58 @@ // Category define('QX_CATID', '38'); -// quix api url to check for response +// Quix API URLs define('QX_SERVER', 'https://www.themexpert.com/index.php?option=com_digicom&task=responses'); - -// download the file api -// &pid=116&username=AAA&key=AAA define('QX_API_DOWNLOAD', QX_SERVER . '&source=release&format=xml&provider=joomla'); - -// update or release api -// &pid=116 define('QX_API_UPDATE', QX_SERVER . '&source=release&format=xml&provider=joomla'); - -// license verification api -// &pid=116&username=AAA&key=AAA || catid=QX_CATID define('QX_API_LICENSE', QX_SERVER . '&source=authapi'); - ############################################################ #### Process ajax calls ############################################################ if ($input->get('ajax', false, 'bool')) { - - $controller = $input->get('controller', '', 'cmd'); - $task = $input->get('task', '', 'cmd'); - - $controllerFile = QX_CONTROLLERS . '/' . strtolower( $controller ) . '.php'; - - require_once($controllerFile); - - $controllerName = 'iQuixController' . ucfirst( $controller ); - $controller = new $controllerName(); - - return $controller->$task(); + $controller = $input->get('controller', '', 'cmd'); + $task = $input->get('task', '', 'cmd'); + + $controllerFile = QX_CONTROLLERS . '/' . strtolower($controller) . '.php'; + + if (defined('JDEBUG') && JDEBUG) { + Log::add('iQuix - Processing AJAX request: ' . $controller . '/' . $task, Log::DEBUG, 'iquix'); + } + + try { + if (File::exists($controllerFile)) { + require_once($controllerFile); + + $controllerName = 'iQuixController' . ucfirst($controller); + + if (class_exists($controllerName)) { + $controllerInstance = new $controllerName(); + + if (method_exists($controllerInstance, $task)) { + return $controllerInstance->$task(); + } else { + throw new Exception('Task not found: ' . $task); + } + } else { + throw new Exception('Controller class not found: ' . $controllerName); + } + } else { + throw new Exception('Controller file not found: ' . $controllerFile); + } + } catch (Exception $e) { + if (defined('JDEBUG') && JDEBUG) { + Log::add('iQuix - AJAX Error: ' . $e->getMessage(), Log::ERROR, 'iquix'); + } + + // Send JSON error response + header('Content-Type: application/json; charset=utf-8'); + echo json_encode([ + 'status' => false, + 'message' => 'Error: ' . $e->getMessage() + ]); + $app->close(); + } } ############################################################ @@ -92,20 +143,54 @@ $controller = $input->get('controller', '', 'cmd'); if (!empty($controller)) { - $controllerFile = QX_CONTROLLERS . '/' . strtolower($controller) . '.php'; - - require_once($controllerFile); - - $controllerName = 'iQuixController' . ucfirst( $controller ); - $controller = new $controllerName(); - return $controller->execute(); + $controllerFile = QX_CONTROLLERS . '/' . strtolower($controller) . '.php'; + + if (defined('JDEBUG') && JDEBUG) { + Log::add('iQuix - Processing controller request: ' . $controller, Log::DEBUG, 'iquix'); + } + + try { + if (File::exists($controllerFile)) { + require_once($controllerFile); + + $controllerName = 'iQuixController' . ucfirst($controller); + + if (class_exists($controllerName)) { + $controllerInstance = new $controllerName(); + return $controllerInstance->execute(); + } else { + throw new Exception('Controller class not found: ' . $controllerName); + } + } else { + throw new Exception('Controller file not found: ' . $controllerFile); + } + } catch (Exception $e) { + if (defined('JDEBUG') && JDEBUG) { + Log::add('iQuix - Controller Error: ' . $e->getMessage(), Log::ERROR, 'iquix'); + } + + $app->enqueueMessage('Error: ' . $e->getMessage(), 'error'); + } } ############################################################ #### Initialization ############################################################ -$contents = file_get_contents(QX_CONFIG . '/installation.json'); -$steps = json_decode($contents); +try { + $contents = file_get_contents(QX_CONFIG . '/installation.json'); + $steps = json_decode($contents); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new Exception('Failed to parse installation steps: ' . json_last_error_msg()); + } +} catch (Exception $e) { + if (defined('JDEBUG') && JDEBUG) { + Log::add('iQuix - Initialization Error: ' . $e->getMessage(), Log::ERROR, 'iquix'); + } + + $app->enqueueMessage('Error loading installation configuration: ' . $e->getMessage(), 'error'); + $steps = []; +} ############################################################ #### Workflow @@ -113,35 +198,32 @@ $active = $input->get('active', 0, 'int'); if ($active == 0) { - $active = 1; - $stepIndex = 0; + $active = 1; + $stepIndex = 0; } else { - $active += 1; - $stepIndex = $active - 1; + $active += 1; + $stepIndex = $active - 1; } if ($active > count($steps)) { - $active = 'complete'; - $activeStep = new stdClass(); - - $activeStep->title = JText::_('Installation Completed'); - $activeStep->template = 'complete'; - - // Assign class names to the step items. - if ($steps) { - foreach ($steps as $step) { - $step->className = ' current done'; - } - } + $active = 'complete'; + $activeStep = new stdClass(); + + $activeStep->title = Text::_('Installation Completed'); + $activeStep->template = 'complete'; } else { - // Get the active step object. - $activeStep = $steps[$stepIndex]; - - // Assign class names to the step items. - foreach ($steps as $step) { - $step->className = $step->index == $active || $step->index < $active ? ' current' : ''; - $step->className .= $step->index < $active ? ' done' : ''; - } + $activeStep = $steps[$stepIndex]; } -require(QX_THEMES . '/default.php'); +// Register variables for main template +$template = $activeStep->template ?? 'default'; +$title = $activeStep->title ?? ''; +$description = $activeStep->description ?? ''; + +// Include the main template +$themeFile = QX_THEMES . '/default.php'; +if (File::exists($themeFile)) { + include($themeFile); +} else { + $app->enqueueMessage('Theme file not found: ' . $themeFile, 'error'); +} \ No newline at end of file diff --git a/setup/controllers/controller.php b/setup/controllers/controller.php index 421f0e1..78fffe1 100644 --- a/setup/controllers/controller.php +++ b/setup/controllers/controller.php @@ -1,7 +1,7 @@ app = JFactory::getApplication(); + $this->app = Factory::getApplication(); $this->input = $this->app->input; + + // Initialize debug logging + if ($this->isDebugEnabled()) { + $this->initDebugLogging(); + } + } + + /** + * Check if debug is enabled + * + * @return bool + */ + protected function isDebugEnabled() + { + return defined('JDEBUG') && JDEBUG; + } + + /** + * Initialize debug logging + */ + protected function initDebugLogging() + { + Log::addLogger(['text_file' => 'iquix.log.php'], Log::ALL, ['iquix']); + $this->debug('Initialized debug logging'); + } + + /** + * Add debug log entry + * + * @param string $message + * @param mixed $data Optional data to include in log + */ + protected function debug($message, $data = null) + { + if ($this->isDebugEnabled()) { + $logMessage = "iQuix - " . $message; + if ($data !== null) { + $logMessage .= ': ' . (is_string($data) ? $data : json_encode($data)); + } + Log::add($logMessage, Log::DEBUG, 'iquix'); + } } + /** + * Add data to the result + * + * @param string $key + * @param mixed $value + */ protected function data($key, $value) { - $obj = new stdClass(); + $obj = new \stdClass(); $obj->$key = $value; $this->result[] = $obj; @@ -38,16 +121,24 @@ protected function data($key, $value) /** * Renders a response with proper headers * - * @since 2.1.0 - * @access public + * @param array $data + * @return void + * @since 2.1.0 */ - public function output($data = array()) + public function output($data = []) { header('Content-Type: application/json; UTF-8'); if (empty($data)) { $data = $this->result; } + + // Add debug information for AJAX responses if debug is enabled + if ($this->isDebugEnabled() && is_array($data)) { + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); + $caller = isset($trace[1]['function']) ? $trace[1]['function'] : ''; + $this->debug("AJAX Response from {$caller}", $data); + } echo json_encode($data); exit; @@ -56,15 +147,24 @@ public function output($data = array()) /** * Generates a result object that can be json encoded * - * @since 2.1.0 - * @access public + * @param string $message + * @param bool $state + * @param string $stateMessage + * @return \stdClass + * @since 2.1.0 */ public function getResultObj($message, $state, $stateMessage = '') { - $obj = new stdClass(); + $obj = new \stdClass(); $obj->state = $state; $obj->stateMessage = $stateMessage; - $obj->message = JText::_($message); + + // Use namespaced Text for Joomla 4/5, fall back to JText for Joomla 3 + if (class_exists('\\Joomla\\CMS\\Language\\Text')) { + $obj->message = Text::_($message); + } else { + $obj->message = \JText::_($message); + } return $obj; } @@ -72,8 +172,8 @@ public function getResultObj($message, $state, $stateMessage = '') /** * Get's the version of this launcher so we know which to install * - * @since 1.0 - * @access public + * @return string + * @since 1.0 */ public function getVersion() { @@ -81,262 +181,352 @@ public function getVersion() // Get the version from the manifest file if (is_null($version)) { - $contents = file_get_contents(JPATH_ROOT.'/administrator/components/com_iquix/iquix.xml'); + $manifestPath = JPATH_ROOT . '/administrator/components/com_iquix/iquix.xml'; + + // Use File class for Joomla 4/5 compatibility + if (class_exists('\\Joomla\\CMS\\Filesystem\\File')) { + $contents = File::exists($manifestPath) ? file_get_contents($manifestPath) : ''; + } else { + $contents = \JFile::exists($manifestPath) ? file_get_contents($manifestPath) : ''; + } + + if (empty($contents)) { + $this->debug('Manifest file not found or empty: ' . $manifestPath); + return '0.0.0'; + } + $parser = simplexml_load_string($contents); $version = $parser->xpath('version'); $version = (string) $version[0]; } - if (JDEBUG) { - \JLog::add("iQuix - version : $version", JLog::DEBUG, 'iquix'); - } - + $this->debug("Version", $version); return $version; } /** * Retrieve the Joomla Version * - * @since 2.0 - * @access public + * @return string + * @since 2.0 */ public function getJoomlaVersion() { - $jVerArr = explode('.', JVERSION); - $jVersion = $jVerArr[0].'.'.$jVerArr[1]; - - if (JDEBUG) { - \JLog::add("iQuix - jVersion : $jVersion", JLog::DEBUG, 'iquix'); + // For Joomla 4 and 5, use Version class + if (class_exists('\\Joomla\\CMS\\Version')) { + $version = new Version(); + $jVersion = $version->getShortVersion(); + } else { + // Legacy method for Joomla 3 + $jVerArr = explode('.', JVERSION); + $jVersion = $jVerArr[0] . '.' . $jVerArr[1]; } + $this->debug("Joomla Version", $jVersion); return $jVersion; } + /** + * Check if current Joomla version is at least version 4 + * + * @return bool + */ + protected function isJoomla4OrHigher() + { + $version = $this->getJoomlaVersion(); + return version_compare($version, '4.0', '>='); + } + + /** + * Check if current Joomla version is at least version 5 + * + * @return bool + */ + protected function isJoomla5OrHigher() + { + $version = $this->getJoomlaVersion(); + return version_compare($version, '5.0', '>='); + } + /** * Retrieves the current site's domain information * - * @since 2.0.9 - * @access public + * @return string + * @since 2.0.9 */ public function getDomain() { static $domain = null; if (is_null($domain)) { - $domain = JURI::root(); - $domain = str_ireplace(array('http://', 'https://'), '', $domain); + // Use Uri class for Joomla 4/5 compatibility + if (class_exists('\\Joomla\\CMS\\Uri\\Uri')) { + $domain = Uri::root(); + } else { + $domain = \JURI::root(); + } + + $domain = str_ireplace(['http://', 'https://'], '', $domain); $domain = rtrim($domain, '/'); } - if (JDEBUG) { - \JLog::add("iQuix - Domain : $domain", JLog::DEBUG, 'iquix'); - } - + $this->debug("Domain", $domain); return $domain; } /** * Retrieves the information about the latest version * - * @since 2.0.9 - * @access public + * @return object|false + * @since 2.0.9 */ public function getInfo() { - // Get the md5 hash from the server. - $session = JFactory::getSession(); + $session = $this->isJoomla4OrHigher() ? Factory::getApplication()->getSession() : Factory::getSession(); $username = $session->get('quix.username', ''); $key = $session->get('quix.key', ''); $id = $session->get('quix.id', ''); - $url = QX_API_LICENSE.'&pid='.$id.'&username='.$username.'&key='.$key; - // &pid=116&username=AAA&key=AAA - - if (JDEBUG) { - \JLog::add("iQuix - Retrieves the information from : $url", JLog::DEBUG, 'iquix'); - } - - $resource = curl_init(); - - $version = $this->getVersion(); - - // We need to pass the api keys to the server - curl_setopt($resource, CURLOPT_URL, $url); - curl_setopt($resource, CURLOPT_POST, false); - // curl_setopt($resource, CURLOPT_POSTFIELDS, 'apikey=' . ES_KEY . '&from=' . $version); - curl_setopt($resource, CURLOPT_TIMEOUT, 120); - curl_setopt($resource, CURLOPT_RETURNTRANSFER, true); - curl_setopt($resource, CURLOPT_SSL_VERIFYPEER, false); - - $result = curl_exec($resource); - - curl_close($resource); - - if (JDEBUG) { - \JLog::add("iQuix - curl server response: ".$result, JLog::DEBUG, 'iquix'); - } - - if ( ! $result) { + $url = QX_API_LICENSE . '&pid=' . $id . '&username=' . $username . '&key=' . $key; + + $this->debug("Retrieving information from", $url); + + try { + // Use Http class for Joomla 4/5 compatibility + if ($this->isJoomla4OrHigher()) { + $httpOptions = new Registry(); + $http = HttpFactory::getHttp($httpOptions); + $response = $http->get($url); + $result = $response->body; + } else { + // Legacy method for Joomla 3 + $resource = curl_init(); + curl_setopt($resource, CURLOPT_URL, $url); + curl_setopt($resource, CURLOPT_POST, false); + curl_setopt($resource, CURLOPT_TIMEOUT, 120); + curl_setopt($resource, CURLOPT_RETURNTRANSFER, true); + curl_setopt($resource, CURLOPT_SSL_VERIFYPEER, false); + $result = curl_exec($resource); + curl_close($resource); + } + + $this->debug("Server response", $result); + + if (empty($result)) { + return false; + } + + $obj = json_decode($result); + if (json_last_error() !== JSON_ERROR_NONE) { + $this->debug("JSON decode error", json_last_error_msg()); + return false; + } + + return $obj; + } catch (\Exception $e) { + $this->debug("Error retrieving information", $e->getMessage()); return false; } - - $obj = json_decode($result); - - return $obj; } + /** + * Get authentication info from database + * + * @return void + */ public function getAuthInfo() { - $db = JFactory::getDbo(); + $db = Factory::getDbo(); $query = $db->getQuery(true); $query->select('*')->from('#__quix_configs'); $db->setQuery($query); - $result = $db->loadObjectList(); - - if (JDEBUG) { - \JLog::add("iQuix - userInfo: ".json_encode($result), JLog::DEBUG, 'iquix'); + + try { + $result = $db->loadObjectList(); + $this->debug("User info", $result); + return $this->output($result); + } catch (\Exception $e) { + $this->debug("Error getting auth info", $e->getMessage()); + return $this->output($this->getResultObj("Error retrieving authentication info: " . $e->getMessage(), false, 'error')); } - - return $this->output($result); } /** - * Loads the previous version that was installed + * Loads the installed version of Quix * - * @since 1.0 - * @access public + * @return string + * @since 1.0 */ public function getInstalledVersion() { - $xml = new SimpleXMLElement(file_get_contents(JPATH_ADMINISTRATOR.'/components/com_quix/quix.xml')); - - $version = (string) $xml->version; - - if (JDEBUG) { - \JLog::add("iQuix - NEW COM_QUIX version:".$version, JLog::INFO, 'iquix'); + $manifestPath = JPATH_ADMINISTRATOR . '/components/com_quix/quix.xml'; + + if (!file_exists($manifestPath)) { + $this->debug("Manifest file does not exist", $manifestPath); + return '0.0.0'; + } + + try { + $xml = new \SimpleXMLElement(file_get_contents($manifestPath)); + $version = (string) $xml->version; + $this->debug("COM_QUIX version", $version); + return $version; + } catch (\Exception $e) { + $this->debug("Error reading installed version", $e->getMessage()); + return '0.0.0'; } - - return $version; } /** - * get a configuration item + * Get previous installed version * - * @since 1.0 - * @access public + * @return string + * @since 1.0 */ public function getPreviousVersion() { - $xml = new SimpleXMLElement(file_get_contents(JPATH_ADMINISTRATOR.'/components/com_quix/quix.xml')); - $version = (string) $xml->version; - - if (JDEBUG) { - \JLog::add("iQuix - OLD COM_QUIX version:".$version, JLog::INFO, 'iquix'); - } - - return $version; - + return $this->getInstalledVersion(); } /** * Determines if we are in development mode * - * @since 1.2 - * @access public + * @return bool + * @since 1.2 */ public function isDevelopment() { - $session = JFactory::getSession(); + $session = $this->isJoomla4OrHigher() ? Factory::getApplication()->getSession() : Factory::getSession(); $developer = $session->get('quix.developer'); - return $developer; } /** * Verifies the api key * - * @since 2.1.0 - * @access public + * @param string $username + * @param string $key + * @return mixed + * @since 2.1.0 */ public function verifyApiKey($username, $key) { - $url = QX_API_LICENSE.'&catid='.QX_CATID.'&username='.$username.'&key='.$key; - // $post = array('username' => $username, 'key' => $key); - if (JDEBUG) { - \JLog::add("iQuix - authAPI Url : ".$url, JLog::DEBUG, 'iquix'); - } - - $httpOption = new JRegistry; - $http = JHttpFactory::getHttp($httpOption); - $str = $http->get($url); - if ($str->code != 200 && $str->code != 310) { + $url = QX_API_LICENSE . '&catid=' . QX_CATID . '&username=' . $username . '&key=' . $key; + $this->debug("API Auth URL", $url); + + try { + // Use Http class for Joomla 4/5 compatibility + if ($this->isJoomla4OrHigher()) { + $httpOptions = new Registry(); + $http = HttpFactory::getHttp($httpOptions); + $response = $http->get($url); + + if ($response->code != 200 && $response->code != 310) { + $this->debug("API Auth failed with code", $response->code); + return false; + } + + $result = json_decode($response->body); + } else { + // Legacy method for Joomla 3 + $httpOption = new Registry(); + $http = HttpFactory::getHttp($httpOption); + $str = $http->get($url); + + if ($str->code != 200 && $str->code != 310) { + $this->debug("API Auth failed with code", $str->code); + return false; + } + + $result = json_decode($str->body); + } + + $this->debug("API Auth result", $result); + return $result; + } catch (\Exception $e) { + $this->debug("API Auth error", $e->getMessage()); return false; } - - if (JDEBUG) { - \JLog::add("iQuix - Verifying authAPI:".$str->body, JLog::DEBUG, 'iquix'); - } - - $result = json_decode($str->body); - - return $result; } /** * Retrieves the extension id * - * @since 2.0.10 - * @access public + * @param string $ext + * @return int|null + * @since 2.0.10 */ public function getExtensionId($ext = 'pkg_quix') { - //SELECT * FROM `fl6j4_extensions` WHERE `element` LIKE 'pkg_quix' - $db = JFactory::getDBO(); - $sql = "SELECT * FROM ".$db->quoteName('#__extensions')." WHERE ".$db->quoteName('element')." = ".$db->quote('pkg_quix'); - $db->setQuery($sql); - - // Get the extension id - $extensionId = $db->loadResult(); - - if (JDEBUG) { - \JLog::add("iQuix - pkg_quix Info:".json_encode($extensionId), JLog::DEBUG, 'iquix'); + try { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select('extension_id') + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = ' . $db->quote($ext)); + $db->setQuery($query); + + $extensionId = $db->loadResult(); + $this->debug("{$ext} extension ID", $extensionId); + + return $extensionId; + } catch (\Exception $e) { + $this->debug("Error getting extension ID", $e->getMessage()); + return null; } - - return $extensionId; } /** * Retrieves the information about the latest version - * url: com_iquix&task=getReleaseInfo&controller=license&ajax=1 * - * @since 2.0.9 - * @access public + * @return string|false + * @since 2.0.9 */ public function getReleaseInfo() { - $session = JFactory::getSession(); + $session = $this->isJoomla4OrHigher() ? Factory::getApplication()->getSession() : Factory::getSession(); $username = $session->get('quix.username', ''); - $key = $session->get('quix.key', ''); - $id = $session->get('quix.id', ''); + $key = $session->get('quix.key', ''); + $id = $session->get('quix.id', ''); - if ( ! $id) { + if (empty($id)) { + $this->debug("No product ID found in session"); return false; } - $update = new JUpdate; - $update->loadFromXml(QX_API_UPDATE.'&pid='.$id, JUpdater::STABILITY_STABLE); - - if (JDEBUG) { - \JLog::add("iQuix - release xml", JLog::DEBUG, 'iquix'); - \JLog::add("iQuix - release xml :".json_encode($update), JLog::DEBUG, 'iquix'); - } - - $downloadUrl = $update->get('downloadurl')->_data ?? null; - if ( ! $downloadUrl) { + + try { + // For Joomla 4/5 + if ($this->isJoomla4OrHigher()) { + $updateClass = '\\Joomla\\CMS\\Updater\\Update'; + $update = new $updateClass; + } else { + // For Joomla 3 + $update = new \JUpdate; + } + + $update->loadFromXml(QX_API_UPDATE . '&pid=' . $id, \JUpdater::STABILITY_STABLE); + $this->debug("Release XML info", $update); + + // Handle different property access between Joomla versions + if ($this->isJoomla4OrHigher()) { + $downloadUrl = $update->get('downloadurl', []); + $downloadUrl = is_object($downloadUrl) && isset($downloadUrl->_data) ? $downloadUrl->_data : ''; + } else { + $downloadUrl = $update->get('downloadurl')->_data ?? ''; + } + + if (empty($downloadUrl)) { + $this->debug("No download URL found in update XML"); + return false; + } + + $downloadUrl = $downloadUrl . '&username=' . $username . '&key=' . $key; + $this->debug("Download URL", $downloadUrl); + + return $downloadUrl; + } catch (\Exception $e) { + $this->debug("Error getting release info", $e->getMessage()); return false; } - - $downloadUrl = $downloadUrl.'&username='.$username.'&key='.$key; - - return $downloadUrl; } } diff --git a/setup/controllers/installation.php b/setup/controllers/installation.php index 3a55bb1..4a5cb6e 100644 --- a/setup/controllers/installation.php +++ b/setup/controllers/installation.php @@ -1,7 +1,7 @@ cachecleaner('com_quix'); - $this->cachecleaner('mod_quix'); - $this->cachecleaner('libquix', 1); - $this->cachecleaner('lib_quix', 1); - $this->cachecleaner('lib_quix'); - $this->cachecleaner('quix', 1); - $this->cachecleaner('quix'); - - if (JDEBUG) { - \JLog::add("iQuix - Cleared cache", JLog::INFO, 'iquix'); + try { + // Determine which file handling classes to use + $fileClass = class_exists('\\Joomla\\CMS\\Filesystem\\File') ? '\\Joomla\\CMS\\Filesystem\\File' : '\\JFile'; + $folderClass = class_exists('\\Joomla\\CMS\\Filesystem\\Folder') ? '\\Joomla\\CMS\\Filesystem\\Folder' : '\\JFolder'; + + // Clean CSS files + $cssPath = JPATH_ROOT . '/media/quix/css'; + if ($folderClass::exists($cssPath)) { + $cssfiles = (array) $folderClass::files($cssPath); + array_map( + function ($file) use ($fileClass, $cssPath) { + if ($file == 'index.html') { + return; + } + $fileClass::delete($cssPath . '/' . $file); + }, + $cssfiles + ); + } + + // Clean JS files + $jsPath = JPATH_ROOT . '/media/quix/js'; + if ($folderClass::exists($jsPath)) { + $jsfiles = (array) $folderClass::files($jsPath); + array_map( + function ($file) use ($fileClass, $jsPath) { + if ($file == 'index.html') { + return; + } + $fileClass::delete($jsPath . '/' . $file); + }, + $jsfiles + ); + } + + // Clear relevant cache + $this->cachecleaner('com_quix'); + $this->cachecleaner('mod_quix'); + $this->cachecleaner('libquix', 1); + $this->cachecleaner('lib_quix', 1); + + $this->debug('Cache cleared successfully'); + return $this->output($this->getResultObj('Cache cleared successfully', true, 'success')); + } catch (\Exception $e) { + $this->debug('Error clearing cache', $e->getMessage()); + return $this->output($this->getResultObj('Error clearing cache: ' . $e->getMessage(), false, 'error')); } - - return $this->output($this->getResultObj(JText::_('COM_IQUIX_INSTALLATION_CACHECLEAN_SUCCESS'), true)); - } + /** + * Clean cache for specific extension + * + * @param string $group + * @param int $client_id + * @return bool + */ public function cachecleaner($group = 'com_quix', $client_id = 0) { - $conf = \JFactory::getConfig(); - - $options = array( - 'defaultgroup' => $group, - 'cachebase' => $client_id ? JPATH_ADMINISTRATOR.'/cache' : $conf->get('cache_path', JPATH_SITE.'/cache'), - 'result' => true, - ); - + $conf = Factory::getConfig(); + try { - /** @var \JCacheControllerCallback $cache */ - $cache = \JCache::getInstance('callback', $options); - $cache->clean(); - } catch (\JCacheException $exception) { - $options['result'] = false; - } - - // Trigger the onContentCleanCache event. - // \JEventDispatcher::getInstance()->trigger('onContentCleanCache', $options); - JFactory::getApplication()->triggerEvent('onContentCleanCache', $options); - } - - public function checkPackageExtension() - { - $db = JFactory::getDBO(); - // Update installed version - $query = "SELECT * FROM `#__extensions` WHERE `name` = 'pkg_quix' and `type` = 'package'"; - $db->setQuery($query); - $result = $db->loadObject(); - - if ($result->extension_id) { - if (JDEBUG) { - \JLog::add("iQuix - Only Updates, No need to update PKG information", JLog::INFO, 'iquix'); - } + $options = [ + 'defaultgroup' => $group, + 'cachebase' => ($client_id) ? JPATH_ADMINISTRATOR . '/cache' : $conf->get('cache_path', JPATH_SITE . '/cache'), + 'result' => true, + ]; + $cache = Factory::getCache($group, ''); + $cache->clean(); + + $this->debug("Cache cleaned for group $group, client_id $client_id"); return true; - } else { - $newVersion = $this->getInstallableVersion(); - - $manifest = '{"name":"pkg_quix","type":"package","creationDate":"2017-07-16","author":"ThemeXpert","copyright":"(C) 2010 - 2016 ThemeXpert. All rights reserved.","authorEmail":"info@themexpert.com","authorUrl":"www.themexpert.com","version":"'.$newVersion.'","description":"PKG_QUIX_XML_DESCRIPTION","group":"","filename":"pkg_quix"}'; - - // new installation, add pkg_quix - $obj = new stdClass(); - $obj->extension_id = ''; - $obj->package_id = 0; - $obj->name = 'pkg_quix'; - $obj->type = 'package'; - $obj->element = 'pkg_quix'; - $obj->enabled = 1; - $obj->access = 1; - $obj->manifest_cache = $manifest; - $obj->params = '{}'; - - // Insert the object into the user profile table. - $result = JFactory::getDbo()->insertObject('#__extensions', $obj); - - if (JDEBUG) { - \JLog::add("iQuix - updated pkg_quix information with status:".$result, JLog::DEBUG, 'iquix'); - } - - if ($result) { - return true; - } else { - return false; - } + } catch (\Exception $e) { + $this->debug("Error cleaning cache for group $group", $e->getMessage()); + return false; } - } - public function backupDatabase() + /** + * Check if package extension exists + * + * @return void + */ + public function checkPackageExtension() { - $getPackage = $this->checkPackageExtension(); - if ( ! $getPackage) { - - if (JDEBUG) { - \JLog::add("iQuix - backupDatabase failed! ".JText::_('Parent package failed to detect!'), JLog::ERROR, 'iquix'); - } - - return $this->output($this->getResultObj(JText::_('Parent package failed to detect!'), false)); - } - - $getComponent = \JComponentHelper::getComponent('com_quix'); - if (empty($getComponent->id) or ! $getComponent->id) { - - if (JDEBUG) { - \JLog::add("iQuix - New Installation, No need backup", JLog::DEBUG, 'iquix'); - } - - return $this->output($this->getResultObj(JText::_('New installation'), true)); - } - - $version = $this->getPreviousVersion(); - $versionText = str_replace(".", "", $version); - - $app = JFactory::getApplication(); - $prefix = $app->get('dbprefix'); - - $db = JFactory::getDbo(); - $tables = JFactory::getDbo()->getTableList(); - - if ( ! in_array($prefix.'quix', $tables)) { - - if (JDEBUG) { - \JLog::add("iQuix - Database empty, No need backup", JLog::DEBUG, 'iquix'); - } - - return $this->output($this->getResultObj(JText::_('No record to backup!'), true)); - } - try { - $tables = JFactory::getDbo()->getTableList(); - $quixTable = $prefix.'quix'.$versionText; - if ( ! in_array($quixTable, $tables)) { - - $query = "CREATE TABLE IF NOT EXISTS `#__quix$versionText` LIKE `#__quix`;"; - $db->setQuery($query); - $result = $db->execute(); - - $query = "INSERT `#__quix$versionText` SELECT * FROM `#__quix`;"; - $db->setQuery($query); - $db->execute(); - - $query = "CREATE TABLE IF NOT EXISTS `#__quix_collections$versionText` LIKE `#__quix_collections`;"; - $db->setQuery($query); - $db->execute(); - $query = "INSERT `#__quix_collections$versionText` SELECT * FROM `#__quix_collections`;"; - $db->setQuery($query); - $db->execute(); - - $query = "CREATE TABLE IF NOT EXISTS `#__quix_collection_map$versionText` LIKE `#__quix_collection_map`;"; - $db->setQuery($query); - $db->execute(); - $query = "INSERT `#__quix_collection_map$versionText` SELECT * FROM `#__quix_collection_map`;"; - $db->setQuery($query); - $db->execute(); - - $query = "CREATE TABLE IF NOT EXISTS `#__quix_elements$versionText` LIKE `#__quix_elements`;"; - $db->setQuery($query); - $db->execute(); - $query = "INSERT `#__quix_elements$versionText` SELECT * FROM `#__quix_elements`;"; - $db->setQuery($query); - $db->execute(); - - if (JDEBUG) { - \JLog::add("iQuix - Database backup complete, name: ".$prefix.'quix'.$versionText, JLog::DEBUG, 'iquix'); - } - - return $this->output($this->getResultObj(JText::_('Database backup complete'), true)); - } else { - if (JDEBUG) { - \JLog::add("iQuix - No need backup, already has it. name: ".$prefix.'quix'.$versionText, JLog::DEBUG, 'iquix'); - } - - return $this->output($this->getResultObj(JText::sprintf('Version %s already has a backup', $version), true)); - } - - } catch (Exception $e) { - if (JDEBUG) { - \JLog::add("iQuix - Database update failed, due to: ".$e->getMessage(), JLog::DEBUG, 'iquix'); - } - - return $this->output($this->getResultObj(JText::_('Error: '.$e->getMessage()), false)); + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select('*') + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = ' . $db->quote('pkg_quix')); + $db->setQuery($query); + $pkg = $db->loadObject(); + + if (!$pkg) { + $this->debug('pkg_quix does not exist'); + return $this->output($this->getResultObj('Fresh installation, continuing.', true)); + } + + // Check if com_quix exists + $query = $db->getQuery(true) + ->select('extension_id') + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = ' . $db->quote('com_quix')); + $db->setQuery($query); + $com = $db->loadResult(); + + if (!$com) { + $this->debug('com_quix does not exist, but pkg_quix does - damaged installation'); + return $this->output($this->getResultObj('The Quix installation seems to be damaged. We need to install it fresh.', false)); + } + + // Everything looks good + $this->debug('pkg_quix exists and valid'); + return $this->output( + $this->getResultObj('Quix is already installed. Do you want to update?', true) + ); + } catch (\Exception $e) { + $this->debug('Error checking package extension', $e->getMessage()); + return $this->output($this->getResultObj('Error checking installation status: ' . $e->getMessage(), false, 'error')); } } diff --git a/setup/controllers/license.php b/setup/controllers/license.php index aa2ca38..5ff43ae 100644 --- a/setup/controllers/license.php +++ b/setup/controllers/license.php @@ -1,7 +1,7 @@ input; - $session = JFactory::getSession(); - $username = $input->get('username', '', 'string'); - $key = $input->get('key', '', 'string'); - - if(JDEBUG){ - \JLog::add("iQuix - Verifing credentials, Username: `$username` and Auth Key: `$key`", JLog::DEBUG, 'iquix'); - } - - // keep the credentials - $session->set('quix.username', $username); - $session->set('quix.key', $key); - - // Verify the key - $result = new stdClass(); - $response = $this->verifyApiKey($username, $key); - - if ($response === false or !$response->success) { - $result->state = 400; - $result->message = JText::_('Unable to verify your license or your hosting provider has blocked outgoing connections. Details: ' . $response->message); - - if(JDEBUG){ - \JLog::add("iQuix - Verification faild. Message: $response->message", JLog::ERROR, 'iquix'); - } - - return $this->output($result); - } - - // store config - $this->updateConfig($username, $key); - if(JDEBUG){ - \JLog::add("iQuix - Config updated to #__quix_configs", JLog::INFO, 'iquix'); - } - - $validLicense = $this->getValidLicense($response); - if(JDEBUG){ - \JLog::add(json_encode($validLicense), JLog::DEBUG, 'iquix'); - } - // json_encode(['hasPro' => true, 'hasFree' => false, 'hasLicense' => true, 'name' => $proProduct, 'id' => $proID]); + $task = $this->input->get('task', ''); - if (!$validLicense['hasLicense']) { - $result->state = 403; - $result->message = JText::_('No valid Quix license found! Chances are, you\'ve entered wrong credentials or you did not purchase Quix yet.'); - \JLog::add("iQuix - $result->message", JLog::WARNING, 'iquix'); - return $this->output($result); - } - - if ($validLicense['hasLicense'] && $validLicense['hasPro']) { - $result->state = 200; - $response->html = ''; - $result->message = JText::_('Great! ' . $validLicense['name'] . ' license found. Please click next to continue installation.'); - \JLog::add("iQuix - $result->message", JLog::INFO, 'iquix'); - return $this->output($result); + // Check if method exists + if (!method_exists($this, $task)) { + $this->debug('Task not found', $task); + return $this->output($this->getResultObj('Invalid task specified.', false, 'error')); } - if ($validLicense['hasLicense'] && $validLicense['hasFree']) { - $result->state = 200; - $response->html = ''; - $result->message = JText::_('Quix free license found. Please click next to continue installation.'); - \JLog::add("iQuix - $result->message", JLog::INFO, 'iquix'); - return $this->output($result); - } + // Execute the task + return $this->$task(); } /** - * Saves a configuration item - * - * @since 1.0 - * @access public + * Verify the license + * + * @return mixed */ - public function updateConfig($username, $authkey) + public function verify() { - // dont allow empty request - if(empty($username) or empty($authkey)) - { - return; + $username = $this->input->get('username', '', 'string'); + $key = $this->input->get('key', '', 'string'); + + if (empty($username) || empty($key)) { + $this->debug('Missing username or key'); + return $this->output($this->getResultObj('Please provide both username and license key.', false, 'error')); } - - $db = JFactory::getDbo(); - $query = $db->getQuery(true); - $query->select('*') - ->from('#__quix_configs'); - $db->setQuery($query); - $result = $db->loadObjectList(); - if(!count($result)){ - // set all, incert - $obj = new stdClass(); - $obj->name = 'username'; - $obj->params = $username; - // Insert the object into the user obj table. - $result = JFactory::getDbo()->insertObject('#__quix_configs', $obj); + + try { + $result = $this->verifyApiKey($username, $key); - $obj = new stdClass(); - $obj->name = 'key'; - $obj->params= $authkey; - - // Insert the object into the user obj table. - $result = JFactory::getDbo()->insertObject('#__quix_configs', $obj); - } - else - { - foreach ($result as $key => $item) { - if($item->name == 'username'){ - // Create an object for the record we are going to update. - $obj = new stdClass(); - $obj->name = 'username'; - $obj->params = $username; - - // Update their details in the users table using id as the primary key. - $result = JFactory::getDbo()->updateObject('#__quix_configs', $obj, 'name'); + if (!$result) { + return $this->output($this->getResultObj('Unable to verify the license. Please try again.', false, 'error')); + } + + if (!isset($result->success) || $result->success !== true) { + $message = isset($result->message) ? $result->message : 'License verification failed.'; + $this->debug('License verification failed', $message); + return $this->output($this->getResultObj($message, false, 'error')); + } + + // We need to store this into our session + $session = $this->isJoomla4OrHigher() ? Factory::getApplication()->getSession() : Factory::getSession(); + $session->set('quix.license.status', $result->success); + $session->set('quix.username', $username); + $session->set('quix.key', $key); + + // Store the user information + if (isset($result->data) && is_array($result->data)) { + // Get a valid license from the response + $license = $this->getValidLicense($result); + $license->id = 117; + + if (!$license) { + $this->debug('No valid license found'); + return $this->output($this->getResultObj('No valid license found for Quix.', false, 'error')); } - if($item->name == 'key'){ - // Create an object for the record we are going to update. - $obj = new stdClass(); - $obj->name = 'key'; - $obj->params = $authkey; - - // Update their details in the users table using id as the primary key. - $result = JFactory::getDbo()->updateObject('#__quix_configs', $obj, 'name'); + + $session->set('quix.license', $license->name); + $session->set('quix.id', $license->id); + + // Store license info in database + $this->storeLicenseInfo($username, $key); + + $this->debug('License verified', [ + 'username' => $username, + 'product' => $license->name, + 'id' => $license->id + ]); + + // Create a custom response object with an HTML field for the license ID input + $responseObj = $this->getResultObj( + $license->name ? 'Great! ' . $license->name . ' license found. Please click next to continue installation.' : 'License verified successfully!', + true, + 'success' + ); + + // Add the HTML input field that was in the original code + $responseObj->html = ''; + + return $this->output($responseObj); + } + + $this->debug('Invalid license response format'); + return $this->output($this->getResultObj('Invalid license response format.', false, 'error')); + } catch (\Exception $e) { + $this->debug('License verification error', $e->getMessage()); + return $this->output($this->getResultObj('Error: ' . $e->getMessage(), false, 'error')); + } + } + + /** + * Store license information in the database + * + * @param string $username + * @param string $authkey + * @return bool + */ + private function storeLicenseInfo($username, $authkey) + { + try { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select('*') + ->from('#__quix_configs'); + $db->setQuery($query); + $result = $db->loadObjectList(); + + if (empty($result)) { + // Insert new records + $obj = new \stdClass(); + $obj->name = 'username'; + $obj->params = $username; + $db->insertObject('#__quix_configs', $obj); + + $obj = new \stdClass(); + $obj->name = 'key'; + $obj->params = $authkey; + $db->insertObject('#__quix_configs', $obj); + } else { + // Update existing records + foreach ($result as $item) { + if ($item->name == 'username') { + $obj = new \stdClass(); + $obj->name = 'username'; + $obj->params = $username; + $db->updateObject('#__quix_configs', $obj, 'name'); + } + + if ($item->name == 'key') { + $obj = new \stdClass(); + $obj->name = 'key'; + $obj->params = $authkey; + $db->updateObject('#__quix_configs', $obj, 'name'); + } } - } + + $this->debug('License info stored in database'); + return true; + } catch (\Exception $e) { + $this->debug('Error storing license info', $e->getMessage()); + return false; } - - return true; - } - + + /** + * Get valid license from the response + * + * @param object $data + * @return object|false + */ public function getValidLicense($data) { - $session = JFactory::getSession(); + if (!isset($data->data) || !is_array($data->data)) { + $this->debug('Invalid license data format'); + return false; + } + $products = $data->data; $quixPro = [QX_AGENCY_ID, QX_PRO_ID, QX_EXT_ID, QX_BUS_ID, QX_PRO_LT_ID]; $hasPro = false; $hasFree = false; - $proProduct = ''; + $proProduct = null; $proID = 0; - - foreach ($products as $key => $product) - { - if(in_array($product->id, $quixPro, true) && ($product->has_access === true)) - { + + foreach ($products as $product) { + if (in_array($product->id, $quixPro, true) && ($product->has_access === true)) { $hasPro = true; - $proProduct = $product->name; + $proProduct = $product; $proID = $product->id; - break; } - if($product->id == QX_FREE_ID && $product->has_access === true) - { + if ($product->id == QX_FREE_ID && $product->has_access === true) { $hasFree = true; - $session->set('quix.hasFree', true); + $freeProduct = $product; } } - // now return result - if($hasPro) - { - $session->set('quix.id', $proID); - $session->set('quix.hasLicense', true); - return array('hasPro' => true, 'hasFree' => $hasFree, 'hasLicense' => true, 'name' => $proProduct, 'id' => $proID); + if ($hasPro && $proProduct) { + $this->debug('Found valid Pro license', $proProduct->name); + return $proProduct; } - elseif($hasFree) - { - $session->set('quix.id', QX_FREE_ID); - $session->set('quix.hasLicense', true); - return array('hasPro' => false, 'hasFree' => true, 'hasLicense' => true); + + if ($hasFree) { + $this->debug('Found valid Free license'); + return $freeProduct; } - else - { - $session->set('quix.hasLicense', false); - return array('hasPro' => false, 'hasFree' => false, 'hasLicense' => false); + + $this->debug('No valid license found'); + return false; + } + + /** + * Get release information + * + * @return mixed + */ + public function getReleaseInfo() + { + $url = $this->getReleaseInfo(); + + if (!$url) { + $this->debug('Failed to get release info'); + return $this->output($this->getResultObj('Failed to get release information.', false, 'error')); + } + + $this->debug('Release info retrieved', $url); + return $this->output($this->getResultObj($url, true, 'success')); + } + + /** + * Download the debug log file + * + * This method allows users to download the iquix.log.php file from the logs directory + * + * @return void + */ + public function downloadDebugLog() + { + try { + $this->debug('Attempting to download debug log file'); + + // Define the path to the log file - using JPATH_ROOT and DIRECTORY_SEPARATOR for compatibility + $logFile = JPATH_ADMINISTRATOR . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . 'iquix.log.php'; + + // Check if the file exists + if (!file_exists($logFile)) { + $this->debug('Debug log file not found', $logFile); + return $this->output($this->getResultObj('Debug log file not found.', false, 'error')); + } + + // Directly serve the file for download + // Clear any buffered output + while (ob_get_level()) { + ob_end_clean(); + } + + // Set headers for file download + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename="iquix_debug.log"'); + header('Content-Transfer-Encoding: binary'); + header('Expires: 0'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Pragma: public'); + header('Content-Length: ' . filesize($logFile)); + + // Output file content + readfile($logFile); + $this->debug('Debug log file downloaded successfully'); + exit; + } catch (\Exception $e) { + $this->debug('Error downloading debug log', $e->getMessage()); + return $this->output($this->getResultObj('Error: ' . $e->getMessage(), false, 'error')); } } } \ No newline at end of file diff --git a/setup/controllers/maintenance.php b/setup/controllers/maintenance.php index 9eb3a38..56d901b 100644 --- a/setup/controllers/maintenance.php +++ b/setup/controllers/maintenance.php @@ -1,7 +1,7 @@ getResultObj('Updated maintenance version.', 1, 'success'); - - return $this->output($result); + try { + // Determine which file class to use + $fileClass = class_exists('\\Joomla\\CMS\\Filesystem\\File') ? '\\Joomla\\CMS\\Filesystem\\File' : '\\JFile'; + + // Remove installation temporary file + $tempFile = JPATH_ROOT . '/tmp/quix.installation'; + if ($fileClass::exists($tempFile)) { + $fileClass::delete($tempFile); + $this->debug('Temporary installation file removed', $tempFile); + } else { + $this->debug('Temporary installation file not found', $tempFile); + } + + return $this->output($this->getResultObj('Installation files cleaned successfully.', true, 'success')); + } catch (\Exception $e) { + $this->debug('Error cleaning installation files', $e->getMessage()); + return $this->output($this->getResultObj('Error cleaning installation files: ' . $e->getMessage(), false, 'error')); + } } + /** + * Removes the update record from the database + * + * @return mixed + */ public function removeUpdateRecord() { - $db = JFactory::getDBO(); - $query = 'DELETE FROM ' . $db->quoteName('#__updates') . ' WHERE ' . $db->quoteName('extension_id') . '=' . $db->Quote($this->getExtensionId()); - $db->setQuery($query); - $result = $db->execute(); - if($result) - { - $msg = $this->getResultObj('Update record cleaned!', true, 'success'); - } - else - { - $msg = $this->getResultObj('Unable to clean update record!', false, 'fail'); + try { + $db = Factory::getDbo(); + $extensionId = $this->getExtensionId(); + + if (!$extensionId) { + $this->debug('No extension ID found for pkg_quix'); + return $this->output($this->getResultObj('No extension record found for Quix.', false, 'warning')); + } + + $query = $db->getQuery(true) + ->delete($db->quoteName('#__updates')) + ->where($db->quoteName('extension_id') . '=' . $db->quote($extensionId)); + $db->setQuery($query); + $result = $db->execute(); + + if ($result) { + $this->debug('Update record cleaned successfully'); + return $this->output($this->getResultObj('Update record cleaned successfully!', true, 'success')); + } else { + $this->debug('Failed to clean update record'); + return $this->output($this->getResultObj('Unable to clean update record!', false, 'fail')); + } + } catch (\Exception $e) { + $this->debug('Error removing update record', $e->getMessage()); + return $this->output($this->getResultObj('Error removing update record: ' . $e->getMessage(), false, 'error')); } - - return $this->output($msg); } + /** + * Updates Quix assets + * + * @return mixed + */ public function updateAssets() { - // cache assets - $token = JSession::getFormToken() . '=' . 1; - $ajax_url = 'index.php?option=com_quix&task=updateAjax&' . $token; - try { - $http = new JHttp(); - $str = $http->get($ajax_url); - - if ($str->code != 200 && $str->code != 310) - { - $result = false; + // Generate token for Joomla 3/4/5 compatibility + if ($this->isJoomla4OrHigher()) { + $token = Factory::getApplication()->getFormToken() . '=1'; + } else { + $token = \JSession::getFormToken() . '=1'; } - else - { - $result = true; + + $ajax_url = 'index.php?option=com_quix&task=updateAjax&' . $token; + $this->debug('Updating assets via', $ajax_url); + + // Use Http class for Joomla 4/5 compatibility + if ($this->isJoomla4OrHigher()) { + $options = new Registry(); + $http = new Http($options); + + try { + $response = $http->get($ajax_url); + $result = ($response->code == 200 || $response->code == 310); + $this->debug('Asset update response code', $response->code); + } catch (\Exception $e) { + // If failed, log but return success (non-critical) + $this->debug('HTTP request failed but continuing', $e->getMessage()); + $result = true; + } + } else { + // Legacy method for Joomla 3 + try { + $http = new \JHttp(); + $str = $http->get($ajax_url); + $result = ($str->code == 200 || $str->code == 310); + $this->debug('Asset update response code', $str->code); + } catch (\Exception $e) { + // If failed, log but return success (non-critical) + $this->debug('HTTP request failed but continuing', $e->getMessage()); + $result = true; + } } - } catch (Exception $e) { - // nothing to show now, lets ignore - $result = true; - } - - if($result) - { - $msg = $this->getResultObj('Updating assets completed!!', true, 'success'); - } - else - { - $msg = $this->getResultObj('Unable to update assets!', false, 'fail'); - } - - - if(JDEBUG){ - \JLog::add("iQuix - updateAssets status: " . $result, JLog::DEBUG, 'iquix'); + + if ($result) { + return $this->output($this->getResultObj('Assets updated successfully!', true, 'success')); + } else { + return $this->output($this->getResultObj('Unable to update assets!', false, 'fail')); + } + } catch (\Exception $e) { + $this->debug('Error updating assets', $e->getMessage()); + return $this->output($this->getResultObj('Error updating assets: ' . $e->getMessage(), false, 'error')); } - - return $this->output($msg); } } \ No newline at end of file diff --git a/setup/controllers/update.php b/setup/controllers/update.php index 7997e48..11fc903 100644 --- a/setup/controllers/update.php +++ b/setup/controllers/update.php @@ -1,7 +1,7 @@ getShortVersion(); + } else { + $jVerArr = explode('.', JVERSION); + $jVersion = $jVerArr[0] . '.' . $jVerArr[1]; + } + + $isJoomla4OrHigher = version_compare($jVersion, '4.0', '>='); + $this->debug('Updating Joomla updater for version', $jVersion); + + // Get the extension ID + $extensionId = $this->getExtensionId(); + + if (!$extensionId) { + $this->debug('No extension ID found for pkg_quix'); + return $this->output($this->getResultObj('No extension record found for Quix.', false, 'warning')); + } + + // Get license ID from session + $session = $isJoomla4OrHigher ? Factory::getApplication()->getSession() : Factory::getSession(); + $id = $session->get('quix.id', ''); + + if (empty($id)) { + $this->debug('No license ID found in session'); + return $this->output($this->getResultObj('No license information found.', false, 'error')); + } + + // Build the update URL + $update_site = QX_API_UPDATE . '&pid=' . $id; + $this->debug('Update site URL', $update_site); + + // Update the update site information in the database + $db = Factory::getDbo(); + + // First check if the update site exists + $query = $db->getQuery(true) + ->select('update_site_id') + ->from($db->quoteName('#__update_sites')) + ->where($db->quoteName('name') . ' = ' . $db->quote('Quix')) + ->where($db->quoteName('type') . ' = ' . $db->quote('extension')); + + $db->setQuery($query); + $update_site_id = $db->loadResult(); + + if ($update_site_id) { + // Update existing update site + $query = $db->getQuery(true) + ->update($db->quoteName('#__update_sites')) + ->set($db->quoteName('location') . ' = ' . $db->quote($update_site)) + ->where($db->quoteName('update_site_id') . ' = ' . $db->quote($update_site_id)); + $db->setQuery($query); + $db->execute(); + + $this->debug('Updated existing update site record', $update_site_id); + } else { + // Insert new update site + $updateSiteObject = new \stdClass; + $updateSiteObject->name = 'Quix'; + $updateSiteObject->type = 'extension'; + $updateSiteObject->location = $update_site; + $updateSiteObject->enabled = 1; + $updateSiteObject->last_check_timestamp = 0; + + $db->insertObject('#__update_sites', $updateSiteObject); + $update_site_id = $db->insertid(); + + // Link the update site to the extension + if ($update_site_id && $extensionId) { + $updateSiteExtObject = new \stdClass; + $updateSiteExtObject->update_site_id = $update_site_id; + $updateSiteExtObject->extension_id = $extensionId; + + $db->insertObject('#__update_sites_extensions', $updateSiteExtObject); + $this->debug('Created new update site record', $update_site_id); + } + } + + // Refresh the update information + if ($isJoomla4OrHigher) { + // For Joomla 4 and 5 + $query = $db->getQuery(true) + ->delete($db->quoteName('#__updates')) + ->where($db->quoteName('extension_id') . ' = ' . $db->quote($extensionId)); + $db->setQuery($query); + $db->execute(); + + // Trigger update check + $updateSites = [$update_site_id]; + $modelFile = JPATH_ADMINISTRATOR . '/components/com_installer/models/update.php'; + + if (File::exists($modelFile)) { + require_once $modelFile; + $model = new \Joomla\Component\Installer\Administrator\Model\UpdateModel(['update_site_id' => $updateSites]); + $model->findUpdates($extensionId, 0); + $this->debug('Triggered update check via model'); + } else { + // Alternative method if model not available + $app = Factory::getApplication(); + $app->triggerEvent('onExtensionAfterUpdate', ['installer.updatecache', null, ['update_site_id' => $updateSites]]); + $this->debug('Triggered update check via event'); + } + } else { + // For Joomla 3 + $query = $db->getQuery(true) + ->delete($db->quoteName('#__updates')) + ->where($db->quoteName('extension_id') . ' = ' . $db->quote($extensionId)); + $db->setQuery($query); + $db->execute(); + + // Trigger update check + Factory::getApplication()->triggerEvent('onExtensionAfterUpdate', + ['installer.updatecache', null] + ); + $this->debug('Triggered update check via event (J3)'); + } + + return $this->output($this->getResultObj('Joomla updater updated successfully!', true, 'success')); + } catch (\Exception $e) { + $this->debug('Error updating Joomla updater', $e->getMessage()); + return $this->output($this->getResultObj('Error updating Joomla updater: ' . $e->getMessage(), false, 'error')); + } + } + /** * Verifies the user's license * diff --git a/setup/views/default.footer.php b/setup/views/default.footer.php index 2584532..f0baf5c 100644 --- a/setup/views/default.footer.php +++ b/setup/views/default.footer.php @@ -1,7 +1,7 @@ - + + @@ -111,7 +123,19 @@ - - - + diff --git a/setup/views/steps/installing.network.php b/setup/views/steps/installing.network.php index 8725ca5..8005584 100644 --- a/setup/views/steps/installing.network.php +++ b/setup/views/steps/installing.network.php @@ -26,6 +26,7 @@ +
          diff --git a/setup/views/steps/installing.steps.php b/setup/views/steps/installing.steps.php index 5c8a147..17aa288 100644 --- a/setup/views/steps/installing.steps.php +++ b/setup/views/steps/installing.steps.php @@ -16,11 +16,11 @@ Waiting
          -
        • - Backup Database - Waiting -
          -
        • + + + + +
        • Initializing Component Waiting diff --git a/setup/views/steps/requirements.php b/setup/views/steps/requirements.php index 088f883..2c17842 100644 --- a/setup/views/steps/requirements.php +++ b/setup/views/steps/requirements.php @@ -11,6 +11,23 @@ */ defined('_JEXEC') or die('Unauthorized Access'); +// Function to print the icons +function printIcon($iconType) +{ +// Define SVG icons as variables + $checkmarkIcon = ''; + $crossIcon = ''; + + if ($iconType === 'checkmark') + { + echo $checkmarkIcon; + } + elseif ($iconType === 'cross') + { + echo $crossIcon; + } +} + $gd = function_exists('gd_info'); $curl = is_callable('curl_init'); $ctype = extension_loaded('ctype'); @@ -20,12 +37,23 @@ //########################################### $db = JFactory::getDBO(); $mysqlVersion = $db->getVersion(); +// first 3 characters of the version +$mysqlVersion = substr($mysqlVersion, 0, 5); //########################################### //# PHP info //########################################### $phpVersion = phpversion(); + $memoryLimit = ini_get('memory_limit'); +// convert the value to MB without unit +if (stripos($memoryLimit, 'M') !== false) { + list($memoryLimit) = explode('M', $memoryLimit); +} elseif (stripos($memoryLimit, 'K') !== false) { + list($memoryLimit) = explode('K', $memoryLimit); + $memoryLimit = $memoryLimit / 1024; +} + $postSize = (int) ini_get('post_max_size'); $max_execution = ini_get('max_execution_time'); $allow_url_fopen = ini_get('allow_url_fopen'); @@ -138,9 +166,13 @@
        • -

          Requirements

          +

          Quix Auto Installer

          +

          + Quix Installer - v# +

          +
          Requirements

          👍 Awesome! The minimum requirements are met. You may proceed with the installation @@ -152,10 +184,6 @@ Some of the requirements below are not met. Please ensure that all of the requirements below are met.

          -

          - New License validation updated. -

          -
          - + - + - + @@ -427,11 +455,11 @@ class="writable ? 'text-error' : '';?>"> writable) { ?> - + -   +   @@ -449,9 +477,6 @@ class="writable ? 'text-error' : '';?>"> href="https://www.themexpert.com/docs/quix-builder/basics/requirements" target="_blank">this link or our Docs Home.

          -

          - New License validation updated. -

          diff --git a/setup/views/steps/source.php b/setup/views/steps/source.php index 0f7f14f..12fa367 100644 --- a/setup/views/steps/source.php +++ b/setup/views/steps/source.php @@ -73,7 +73,7 @@ loading.addClass('d-none'); // User is not allowed to install - if (result.state == 400 || result.state == 403) { + if (!result.state == 400 || result.state == false) { // Set the error message $('[data-api-errors]').removeClass('d-none'); @@ -83,7 +83,7 @@ // Valid licenses - if (result.state == 200) { + if (result.state) { submit.removeClass('d-none'); licenses.append(result.html); From 88af1fbfd705d905ceab811e8d705146bf116800 Mon Sep 17 00:00:00 2001 From: Abu-Huraira Date: Tue, 25 Mar 2025 17:25:39 +0600 Subject: [PATCH 3/3] new installation php warning fixed --- .gitignore | 3 +++ languages/admin/en-GB.com_iquix.sys.ini | 3 ++- setup/controllers/installation.php | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index d23f387..05edbfb 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ releases/ !.gitignore !index.html !index.php + +setup/packages +setup/tmp \ No newline at end of file diff --git a/languages/admin/en-GB.com_iquix.sys.ini b/languages/admin/en-GB.com_iquix.sys.ini index 0f8b496..4949baa 100644 --- a/languages/admin/en-GB.com_iquix.sys.ini +++ b/languages/admin/en-GB.com_iquix.sys.ini @@ -6,4 +6,5 @@ ; works licensed under the GNU General Public License or other free or open source ; software licenses. See COPYRIGHT.php for copyright notices and details. -COM_IQUIX="Quix Installer" \ No newline at end of file +COM_IQUIX="Quix Installer" +COM_IQUIX_INSTALLATION_COMPLETE="Complete" \ No newline at end of file diff --git a/setup/controllers/installation.php b/setup/controllers/installation.php index 4a5cb6e..9d9a635 100644 --- a/setup/controllers/installation.php +++ b/setup/controllers/installation.php @@ -835,7 +835,8 @@ public function updateJoomlaUpdater() $query = "SELECT * FROM `#__extensions` WHERE `name` = 'pkg_quix' and `type` = 'package'"; $db->setQuery($query); $result = $db->loadObject(); - + if(!$result) return; + $manifest = json_decode($result->manifest_cache); $manifest->version = $version;