2021-03-01 14:20:52 +00:00
< ? php
2021-03-26 16:16:21 +00:00
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd .
* Copyright ( C ) 2021 SalesAgility Ltd .
*
* This program is free software ; you can redistribute it and / or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7 ( a ) : FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY , SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE . See the GNU Affero General Public License for more
* details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />.
*
* In accordance with Section 7 ( b ) of the GNU Affero General Public License
* version 3 , these Appropriate Legal Notices must retain the display of the
* " Supercharged by SuiteCRM " logo . If the display of the logos is not reasonably
* feasible for technical reasons , the Appropriate Legal Notices must display
* the words " Supercharged by SuiteCRM " .
*/
2021-03-01 14:20:52 +00:00
2021-03-25 11:01:14 +00:00
namespace App\Install\LegacyHandler ;
2021-03-01 14:20:52 +00:00
2021-03-25 11:01:14 +00:00
use App\Engine\LegacyHandler\LegacyHandler ;
use App\Engine\LegacyHandler\LegacyScopeState ;
2021-09-21 13:48:11 +05:30
use App\Engine\Model\Feedback ;
use App\Install\Service\Installation\InstallStatus ;
2021-08-07 00:12:34 +05:30
use App\Install\Service\InstallationUtilsTrait ;
2024-01-12 09:47:47 +00:00
use App\Install\Service\InstallPreChecks ;
2024-06-19 17:24:00 +01:00
use App\Security\AppSecretGenerator ;
2024-03-18 15:48:42 +00:00
use Exception ;
2024-03-07 12:17:41 +00:00
use Monolog\Handler\StreamHandler ;
use Monolog\Logger ;
2021-08-07 00:12:34 +05:30
use PDO ;
use PDOException ;
2021-03-01 14:20:52 +00:00
use Psr\Log\LoggerInterface ;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface ;
use Symfony\Component\Filesystem\Filesystem ;
2023-10-04 15:36:24 +01:00
use Symfony\Component\HttpFoundation\RequestStack ;
2025-01-10 15:05:46 +00:00
use Throwable ;
2021-03-01 14:20:52 +00:00
/**
* Class InstallHandler
* @ package App\Legacy
*/
class InstallHandler extends LegacyHandler
{
2021-08-07 00:12:34 +05:30
use InstallationUtilsTrait ;
2021-03-01 14:20:52 +00:00
public const HANDLER_KEY = 'install' ;
/**
* @ var string
*/
protected $legacyDir ;
/**
* @ var LoggerInterface
*/
private $logger ;
2024-06-19 17:24:00 +01:00
protected AppSecretGenerator $appSecretGenerator ;
2021-03-01 14:20:52 +00:00
/**
* @ inheritDoc
*/
public function getHandlerKey () : string
{
return self :: HANDLER_KEY ;
}
/**
* InstallHandler constructor .
* @ param string $projectDir
* @ param string $legacyDir
* @ param string $legacySessionName
* @ param string $defaultSessionName
* @ param LegacyScopeState $legacyScopeState
2024-02-14 09:03:24 +00:00
* @ param RequestStack $requestStack
2021-03-01 14:20:52 +00:00
* @ param LoggerInterface $logger
2024-06-19 17:24:00 +01:00
* @ param AppSecretGenerator $appSecretGenerator
2021-03-01 14:20:52 +00:00
*/
public function __construct (
2024-06-19 17:24:00 +01:00
string $projectDir ,
string $legacyDir ,
string $legacySessionName ,
string $defaultSessionName ,
LegacyScopeState $legacyScopeState ,
RequestStack $requestStack ,
LoggerInterface $logger ,
AppSecretGenerator $appSecretGenerator
2021-10-13 16:13:54 +05:30
)
{
2021-03-26 01:25:41 +00:00
parent :: __construct (
$projectDir ,
$legacyDir ,
$legacySessionName ,
$defaultSessionName ,
$legacyScopeState ,
2024-02-14 09:03:24 +00:00
$requestStack
2021-03-26 01:25:41 +00:00
);
2021-03-01 14:20:52 +00:00
$this -> legacyDir = $legacyDir ;
$this -> logger = $logger ;
2024-06-19 17:24:00 +01:00
$this -> appSecretGenerator = $appSecretGenerator ;
2021-03-01 14:20:52 +00:00
}
/**
2021-09-21 13:48:11 +05:30
* Init legacy
2021-03-01 14:20:52 +00:00
*/
2021-09-21 13:48:11 +05:30
public function initLegacy () : void
{
$this -> switchSession ( $this -> legacySessionName );
chdir ( $this -> legacyDir );
2021-09-27 19:20:15 +01:00
global $installing ;
$installing = true ;
2021-09-21 13:48:11 +05:30
}
/**
* Close legacy
*/
public function closeLegacy () : void
{
chdir ( $this -> projectDir );
$this -> switchSession ( $this -> defaultSessionName );
}
/**
* @ return Feedback
*/
public function installLegacy () : Feedback
2021-03-01 14:20:52 +00:00
{
chdir ( $this -> legacyDir );
$errorLevelStored = error_reporting ();
error_reporting ( 0 );
2021-09-21 13:48:11 +05:30
$feedback = new Feedback ();
2021-03-01 14:20:52 +00:00
if ( ! is_file ( 'config_si.php' )) {
$this -> logger -> error ( 'config_si.php is required for CLI Install.' );
2021-09-21 13:48:11 +05:30
return $feedback -> setSuccess ( false ) -> setMessages ([ 'config_si.php is required for CLI Install.' ]);
2021-03-01 14:20:52 +00:00
}
$_REQUEST [ 'goto' ] = 'SilentInstall' ;
$_REQUEST [ 'cli' ] = 'true' ;
2025-01-10 15:05:46 +00:00
$installResult = [];
2025-01-13 16:44:06 +00:00
if ( ! is_readable ( 'include/portability/Install/AppInstallService.php' )) {
$this -> logger -> error ( 'An error occurred while installing SuiteCRM - not able to access portability/Install/AppInstallService.php' );
$feedback -> setSuccess ( false ) -> setMessages ([ 'An error occurred while installing SuiteCRM - not able to access portability/Install/AppInstallService.php' ]);
chdir ( $this -> projectDir );
error_reporting ( $errorLevelStored );
return $feedback ;
}
2025-01-10 15:05:46 +00:00
try {
ob_start ();
ob_start ();
/* @noinspection PhpIncludeInspection */
2025-01-13 16:44:06 +00:00
require_once 'include/portability/Install/AppInstallService.php' ;
$appInstallService = new \AppInstallService ();
$installResult = $appInstallService -> runInstall ();
2025-01-10 15:05:46 +00:00
ob_end_clean ();
ob_end_clean ();
} catch ( Throwable $t ) {
2025-01-13 16:44:06 +00:00
$this -> logger -> error ( 'An error occurred while installing SuiteCRM : ' . $t -> getMessage ());
2025-01-10 15:05:46 +00:00
2025-01-13 16:44:06 +00:00
$installResult = $installResult ? ? [];
$installResult [ 'success' ] = false ;
$installResult [ 'messages' ] = $installResult [ 'messages' ] ? ? [];
$installResult [ 'messages' ] = array_merge ( $installResult [ 'messages' ], [ 'Exception: ' . $t -> getMessage ()]);
2025-01-10 15:05:46 +00:00
}
2025-01-13 16:44:06 +00:00
$success = ( $installResult [ 'success' ] ? ? false ) && is_file ( 'config.php' );
$installMessages = $installResult [ 'messages' ] ? ? [];
2021-03-01 14:20:52 +00:00
2025-01-13 16:44:06 +00:00
$messages = [ 'SuiteCRM Installation Completed' ];
if ( ! $success ) {
2025-01-10 15:05:46 +00:00
$messages = [ 'An error occurred while installing SuiteCRM. Please check the logs.' ];
2021-09-21 13:48:11 +05:30
}
2025-01-13 16:44:06 +00:00
$messages = array_merge ( $messages , $installMessages );
$feedback -> setSuccess ( $success ) -> setMessages ( $messages );
2021-09-21 13:48:11 +05:30
chdir ( $this -> projectDir );
error_reporting ( $errorLevelStored );
return $feedback ;
}
/**
* @ param array $context
* @ return Feedback
*/
public function runSystemCheck ( array & $context ) : Feedback
{
$this -> switchSession ( $this -> legacySessionName );
chdir ( $this -> legacyDir );
$errorLevelStored = error_reporting ();
error_reporting ( 0 );
2022-12-21 13:02:06 +00:00
$this -> runLegacyEntryPoint ();
2021-09-28 11:30:42 +01:00
/* @noinspection PhpIncludeInspection */
2021-09-21 13:48:11 +05:30
require_once 'include/portability/InstallValidation/InstallValidation.php' ;
$validator = ( new \InstallValidation ()) -> validate ( $context );
$result = $validator -> result ();
$feedback = new Feedback ();
$feedback -> setSuccess ( true );
$hasErrors = $result [ 'hasValidationError' ] ? ? false ;
if ( $hasErrors === true ) {
$feedback -> setSuccess ( false );
$feedback -> setStatusCode ( InstallStatus :: VALIDATION_FAILED );
$feedback -> setErrors ( $result );
2021-03-01 14:20:52 +00:00
}
2024-02-25 15:16:43 +00:00
file_put_contents ( '.installed_checked' , 'true' );
2021-03-01 14:20:52 +00:00
chdir ( $this -> projectDir );
$this -> switchSession ( $this -> defaultSessionName );
error_reporting ( $errorLevelStored );
2021-09-21 13:48:11 +05:30
return $feedback ;
2021-03-01 14:20:52 +00:00
}
2024-01-12 09:47:47 +00:00
public function runCheckRouteAccess ( array $inputArray ) : FeedBack
{
$results = [];
$url = $inputArray [ 'site_host' ];
2024-03-07 12:17:41 +00:00
$log = new Logger ( 'install.log' );
2024-03-18 15:48:42 +00:00
$log -> pushHandler ( new StreamHandler ( __DIR__ . '/../../../../logs/install.log' , Logger :: DEBUG ));
$feedback = new Feedback ();
$feedback -> setSuccess ( true );
2024-03-07 12:17:41 +00:00
2024-05-28 10:34:28 +01:00
require_once __DIR__ . " /../../../../core/backend/Install/Service/InstallPreChecks.php " ;
2024-03-07 12:17:41 +00:00
$installChecks = new InstallPreChecks ( $log );
2024-03-18 15:48:42 +00:00
2024-01-12 09:47:47 +00:00
$results [] = $installChecks -> checkMainPage ( $url );
$results [] = $installChecks -> checkGraphQlAPI ( $url );
$modStrings = $installChecks -> getLanguageStrings ();
$warnings = [];
2024-03-07 12:17:41 +00:00
$errorsFound = false ;
2024-01-12 09:47:47 +00:00
foreach ( $results as $result ) {
if ( is_array ( $result [ 'errors' ])) {
foreach ( $result [ 'errors' ] as $error ) {
2024-03-18 15:48:42 +00:00
$errorsFound = true ;
2024-06-19 17:24:00 +01:00
if ( empty ( $error )) {
2024-03-18 15:48:42 +00:00
continue ;
}
if ( in_array ( $error , $modStrings ) && $error !== $modStrings [ 'LBL_EMPTY' ]) {
2024-03-04 10:25:37 +00:00
$warnings [] = " One or More Failed Checks: " . $error . " Please refer to the logs/install.log " ;
2024-01-12 09:47:47 +00:00
}
2024-03-07 12:17:41 +00:00
2024-01-12 09:47:47 +00:00
}
continue ;
}
if ( ! empty ( $result [ 'errors' ])) {
$warnings [] = $result [ 'errors' ];
}
}
2024-03-18 15:48:42 +00:00
if ( $errorsFound ) {
2024-03-07 12:17:41 +00:00
$warnings [] = 'One or More Failed Checks: Please refer to the logs/install.log' ;
}
2024-03-18 15:48:42 +00:00
if ( isset ( $warnings )) {
2024-01-12 09:47:47 +00:00
$feedback -> setWarnings ( $warnings );
}
return $feedback ;
}
2021-03-01 14:20:52 +00:00
/**
* @ param array $inputArray
2021-08-07 00:12:34 +05:30
* @ return bool
2021-03-01 14:20:52 +00:00
*/
2021-08-07 00:12:34 +05:30
public function createConfig ( array $inputArray ) : bool
2021-03-01 14:20:52 +00:00
{
2024-03-07 12:17:41 +00:00
$siteURL = rtrim ( $inputArray [ 'site_host' ] ? ? '' , " \t \n \r \0 \x0B / " );;
2021-03-01 14:20:52 +00:00
$configArray = [
'dbUSRData' => 'same' ,
'default_currency_iso4217' => 'USD' ,
'default_currency_name' => 'US Dollar' ,
'default_currency_significant_digits' => '2' ,
'default_currency_symbol' => '$' ,
'default_date_format' => 'Y-m-d' ,
'default_decimal_seperator' => '.' ,
'default_export_charset' => 'ISO-8859-1' ,
'default_language' => 'en_us' ,
'default_locale_name_format' => 's f l' ,
'default_number_grouping_seperator' => ',' ,
'default_time_format' => 'H:i' ,
'export_delimiter' => ',' ,
'setup_db_admin_password' => $inputArray [ 'db_password' ],
'setup_db_admin_user_name' => $inputArray [ 'db_username' ],
2021-10-13 16:13:54 +05:30
'setup_db_port_num' => $inputArray [ 'db_port' ],
2021-03-01 14:20:52 +00:00
'setup_db_create_database' => 1 ,
'setup_db_database_name' => $inputArray [ 'db_name' ],
'setup_db_drop_tables' => 0 ,
'setup_db_host_name' => $inputArray [ 'db_host' ],
2021-03-26 01:25:41 +00:00
'demoData' => $inputArray [ 'demoData' ],
2021-03-01 14:20:52 +00:00
'setup_db_type' => 'mysql' ,
'setup_db_username_is_privileged' => true ,
'setup_site_admin_password' => $inputArray [ 'site_password' ],
'setup_site_admin_user_name' => $inputArray [ 'site_username' ],
2021-03-26 01:25:41 +00:00
'setup_site_url' => $siteURL ,
2021-03-01 14:20:52 +00:00
'setup_system_name' => 'SuiteCRM' ,
];
$contents = '<?php' . " \n " . '$sugar_config_si = ' . var_export ( $configArray , 1 ) . " ; \n " ;
$filesystem = new Filesystem ();
try {
chdir ( $this -> legacyDir );
$filesystem -> dumpFile ( 'config_si.php' , $contents );
chdir ( $this -> projectDir );
2021-08-07 00:12:34 +05:30
return true ;
2021-03-01 14:20:52 +00:00
} catch ( IOExceptionInterface $exception ) {
2021-08-07 00:12:34 +05:30
$this -> logger -> error ( 'An error occurred while creating your silent install config at ' . $exception -> getPath ());
2021-09-21 13:48:11 +05:30
2021-08-07 00:12:34 +05:30
return false ;
}
}
/**
* Check db host connection before proceeding
* @ param array $inputArray
* @ return bool
*/
public function checkDBConnection ( array $inputArray ) : bool
{
2021-12-10 12:17:04 +00:00
$dbHost = $inputArray [ " db_host " ];
$dbPort = $inputArray [ " db_port " ];
$hostString = ! empty ( $dbPort ) ? $dbHost . ':' . $dbPort : $dbHost ;
2021-08-07 00:12:34 +05:30
try {
2021-09-21 13:48:11 +05:30
new PDO (
2021-12-10 12:17:04 +00:00
" mysql:host= " . $hostString . " ; " ,
2021-09-21 13:48:11 +05:30
$inputArray [ 'db_username' ],
$inputArray [ 'db_password' ]
);
2021-08-07 00:12:34 +05:30
} catch ( PDOException $e ) {
$this -> logger -> error ( 'An error occurred while checking the Database Host Connection ' . $e -> getMessage ());
2021-09-21 13:48:11 +05:30
2021-08-07 00:12:34 +05:30
return false ;
2021-03-01 14:20:52 +00:00
}
2021-08-07 00:12:34 +05:30
return true ;
2021-03-01 14:20:52 +00:00
}
2021-03-26 01:25:41 +00:00
/**
* Create local env file
* @ param array $inputArray
2021-08-07 00:12:34 +05:30
* @ return bool
2021-03-26 01:25:41 +00:00
*/
2021-08-07 00:12:34 +05:30
public function createEnv ( array $inputArray ) : bool
2021-03-26 01:25:41 +00:00
{
2021-09-21 13:48:11 +05:30
$password = urlencode ( $inputArray [ 'db_password' ] ? ? '' );
$username = urlencode ( $inputArray [ 'db_username' ] ? ? '' );
2021-03-26 01:25:41 +00:00
$dbName = $inputArray [ 'db_name' ] ? ? '' ;
$host = $inputArray [ 'db_host' ] ? ? '' ;
2021-12-10 12:17:04 +00:00
$port = $inputArray [ 'db_port' ] ? ? '' ;
$hostString = ! empty ( $port ) ? $host . ':' . $port : $host ;
2021-03-26 01:25:41 +00:00
2024-06-19 17:24:00 +01:00
$content = " DATABASE_URL= \" mysql:// $username : $password @ $hostString / $dbName\ " \n " ;
$content .= " APP_SECRET= " . $this -> appSecretGenerator -> generate ();
$this -> logger -> info ( 'Generated randomly generated APP_SECRET for .env.local' );
2021-03-26 01:25:41 +00:00
$filesystem = new Filesystem ();
2021-08-07 00:12:34 +05:30
try {
chdir ( $this -> projectDir );
2024-06-19 17:24:00 +01:00
$filesystem -> dumpFile ( '.env.local' , $content );
2021-08-07 00:12:34 +05:30
chdir ( $this -> legacyDir );
return true ;
} catch ( IOExceptionInterface $exception ) {
$this -> logger -> error ( 'An error occurred while creating the Database Env config at ' . $exception -> getPath ());
2021-09-21 13:48:11 +05:30
2021-08-07 00:12:34 +05:30
return false ;
}
2021-03-26 01:25:41 +00:00
}
/**
* Check if is installed
* @ return bool is installed
*/
public function isInstalled () : bool
{
$filesystem = new Filesystem ();
2021-08-07 00:12:34 +05:30
$this -> logger -> error ( 'A SuiteCRM Instance is already been installed. Stopping ' );
2021-03-26 01:25:41 +00:00
return $filesystem -> exists ( '.env.local' );
}
2021-08-07 00:12:34 +05:30
2021-10-29 22:09:21 +05:30
/**
* Check if is legacy app is installed
* @ return bool is installed
*/
public function isLegacyInstalled () : bool
{
return $this -> isAppInstalled ( $this -> legacyDir );
}
2021-08-07 00:12:34 +05:30
/**
* Check if is installer locked
* @ return bool is locked
*/
public function isInstallerLocked () : bool
{
return $this -> isAppInstallerLocked ( $this -> legacyDir );
}
2021-10-26 13:10:22 +01:00
/**
* Load legacy config
* @ return array | null is locked
*/
public function loadLegacyConfig () : ? array
{
return $this -> getLegacyConfig ( $this -> legacyDir );
}
2021-03-01 14:20:52 +00:00
}