Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 237 |
|
0.00% |
0 / 17 |
CRAP | |
0.00% |
0 / 1 |
| tao_install_Installator | |
0.00% |
0 / 237 |
|
0.00% |
0 / 17 |
3306 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
| install | |
0.00% |
0 / 167 |
|
0.00% |
0 / 1 |
702 | |||
| getServiceManager | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| retryInstallation | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
20 | |||
| isWindows | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| generateSessionName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| checkInstallData | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 | |||
| escapeCheck | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| getEscapedChecks | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| setEscapedChecks | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| isEscapedCheck | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| log | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
56 | |||
| getLog | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getGenerisConfig | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getConfigPath | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| setInstallationFinished | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| recreateDependencyInjectionContainerCache | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU General Public License |
| 6 | * as published by the Free Software Foundation; under version 2 |
| 7 | * of the License (non-upgradable). |
| 8 | * |
| 9 | * This program is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with this program; if not, write to the Free Software |
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 17 | * |
| 18 | * Copyright (c) 2002-2008 (original work) Public Research Centre Henri Tudor & University of Luxembourg |
| 19 | * (under the project TAO & TAO2); |
| 20 | * 2008-2010 (update and modification) Deutsche Institut für Internationale Pädagogische Forschung |
| 21 | * (under the project TAO-TRANSFER); |
| 22 | * 2009-2012 (update and modification) Public Research Centre Henri Tudor |
| 23 | * (under the project TAO-SUSTAIN & TAO-DEV); |
| 24 | * 2013-2017 (update and modification) Open Assessment Technologies SA (under the project TAO-PRODUCT); |
| 25 | */ |
| 26 | |
| 27 | use oat\generis\persistence\DriverConfigurationFeeder; |
| 28 | use oat\oatbox\cache\SetupFileCache; |
| 29 | use oat\tao\helpers\InstallHelper; |
| 30 | use oat\oatbox\install\Installer; |
| 31 | use oat\oatbox\service\ServiceManager; |
| 32 | use oat\tao\model\OperatedByService; |
| 33 | use oat\generis\persistence\sql\DbCreator; |
| 34 | use oat\generis\persistence\sql\SetupDb; |
| 35 | use oat\generis\persistence\PersistenceManager; |
| 36 | use oat\generis\model\data\Ontology; |
| 37 | use oat\tao\model\TaoOntology; |
| 38 | use oat\generis\model\GenerisRdf; |
| 39 | use oat\tao\model\user\TaoRoles; |
| 40 | use oat\tao\model\service\ApplicationService; |
| 41 | use oat\oatbox\service\ServiceNotFoundException; |
| 42 | |
| 43 | /** |
| 44 | * |
| 45 | * |
| 46 | * Installation main class |
| 47 | * |
| 48 | * @access public |
| 49 | * @author Jérôme Bogaerts, <jerome@taotesting.com> |
| 50 | * @package tao |
| 51 | */ |
| 52 | |
| 53 | class tao_install_Installator |
| 54 | { |
| 55 | // Adding container and logger. |
| 56 | use \oat\oatbox\log\ContainerLoggerTrait; |
| 57 | |
| 58 | /** |
| 59 | * Installator related dependencies will be reached under this offset. |
| 60 | */ |
| 61 | public const CONTAINER_INDEX = 'taoInstallInstallator'; |
| 62 | |
| 63 | protected $options = []; |
| 64 | |
| 65 | private $log = []; |
| 66 | |
| 67 | private $escapedChecks = []; |
| 68 | |
| 69 | private $oatBoxInstall = null; |
| 70 | |
| 71 | public function __construct($options) |
| 72 | { |
| 73 | // Using the container if it's necessary with automatic dependency returning. |
| 74 | $options = $this->initContainer($options, static::CONTAINER_INDEX); |
| 75 | |
| 76 | if (!isset($options['root_path'])) { |
| 77 | throw new tao_install_utils_Exception("root_path option must be defined to perform installation."); |
| 78 | } |
| 79 | if (!isset($options['install_path'])) { |
| 80 | throw new tao_install_utils_Exception("install_path option must be defined to perform installation."); |
| 81 | } |
| 82 | |
| 83 | $this->options = $options; |
| 84 | |
| 85 | $this->options['root_path'] = rtrim($this->options['root_path'], '/\\') . DIRECTORY_SEPARATOR; |
| 86 | $this->options['install_path'] = rtrim($this->options['install_path'], '/\\') . DIRECTORY_SEPARATOR; |
| 87 | |
| 88 | $this->oatBoxInstall = new Installer(); |
| 89 | } |
| 90 | |
| 91 | /** |
| 92 | * Run the TAO install from the given data |
| 93 | * @throws tao_install_utils_Exception |
| 94 | * @param $installData array data coming from the install form |
| 95 | * @param $callback callable|null post install callback |
| 96 | */ |
| 97 | public function install(array $installData, callable $callback = null) |
| 98 | { |
| 99 | try { |
| 100 | /** |
| 101 | * It's a quick hack for solving reinstall issue. |
| 102 | * Should be a better option. |
| 103 | */ |
| 104 | @unlink($this->options['root_path'] . 'config/generis.conf.php'); |
| 105 | |
| 106 | /* |
| 107 | * 0 - Check input parameters. |
| 108 | */ |
| 109 | $this->log('i', "Checking install data"); |
| 110 | self::checkInstallData($installData); |
| 111 | |
| 112 | $this->log('i', "Starting TAO install"); |
| 113 | |
| 114 | // Sanitize $installData if needed. |
| 115 | if (!preg_match("/\/$/", $installData['module_url'])) { |
| 116 | $installData['module_url'] .= '/'; |
| 117 | } |
| 118 | |
| 119 | // Define the ROOT_URL constant if not defined (can be used in manifest files) |
| 120 | if (!defined('ROOT_URL')) { |
| 121 | define('ROOT_URL', $installData['module_url']); |
| 122 | } |
| 123 | |
| 124 | if (isset($installData['extensions'])) { |
| 125 | $extensionIDs = is_array($installData['extensions']) |
| 126 | ? $installData['extensions'] |
| 127 | : explode(',', $installData['extensions']); |
| 128 | } else { |
| 129 | $extensionIDs = ['taoCe']; |
| 130 | } |
| 131 | |
| 132 | $this->log('d', 'Extensions to be installed: ' . var_export($extensionIDs, true)); |
| 133 | |
| 134 | $installData['file_path'] = rtrim($installData['file_path'], DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; |
| 135 | |
| 136 | /* |
| 137 | * 1 - Check configuration with checks described in the manifest. |
| 138 | */ |
| 139 | $configChecker = tao_install_utils_ChecksHelper::getConfigChecker($extensionIDs); |
| 140 | |
| 141 | // Silence checks to have to be escaped. |
| 142 | foreach ($configChecker->getComponents() as $c) { |
| 143 | if (method_exists($c, 'getName') && in_array($c->getName(), $this->getEscapedChecks())) { |
| 144 | $configChecker->silent($c); |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | $reports = $configChecker->check(); |
| 149 | foreach ($reports as $r) { |
| 150 | $msg = $r->getMessage(); |
| 151 | $component = $r->getComponent(); |
| 152 | $this->log('i', $msg); |
| 153 | |
| 154 | if ($r->getStatus() !== common_configuration_Report::VALID && !$component->isOptional()) { |
| 155 | throw new tao_install_utils_Exception($msg); |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | /* |
| 160 | * X - Setup Oatbox |
| 161 | */ |
| 162 | |
| 163 | $this->log('d', 'Removing old config'); |
| 164 | $consistentOptions = array_merge($installData, $this->options); |
| 165 | $consistentOptions['config_path'] = $this->getConfigPath(); |
| 166 | $this->oatBoxInstall->setOptions($consistentOptions); |
| 167 | $this->oatBoxInstall->install(); |
| 168 | $this->log('d', 'Oatbox was installed!'); |
| 169 | |
| 170 | ServiceManager::setServiceManager($this->getServiceManager()); |
| 171 | |
| 172 | /* |
| 173 | * 2 - Setup RDS persistence |
| 174 | */ |
| 175 | if (!$this->getServiceManager()->has(DriverConfigurationFeeder::SERVICE_ID)) { |
| 176 | $this->getServiceManager()->register( |
| 177 | DriverConfigurationFeeder::SERVICE_ID, |
| 178 | new DriverConfigurationFeeder( |
| 179 | [ |
| 180 | DriverConfigurationFeeder::OPTION_DRIVER_OPTIONS => [] |
| 181 | ] |
| 182 | ) |
| 183 | ); |
| 184 | } |
| 185 | |
| 186 | if ($this->getServiceManager()->has(PersistenceManager::SERVICE_ID)) { |
| 187 | $persistenceManager = $this->getServiceManager()->get(PersistenceManager::SERVICE_ID); |
| 188 | } else { |
| 189 | $this->log('i', "Spawning new PersistenceManager"); |
| 190 | $persistenceManager = new PersistenceManager(); |
| 191 | } |
| 192 | if (!$persistenceManager->hasPersistence('default')) { |
| 193 | $this->log('i', "Register default Persistence"); |
| 194 | $dbalConfigCreator = new tao_install_utils_DbalConfigCreator(); |
| 195 | $persistenceManager->registerPersistence('default', $dbalConfigCreator->createDbalConfig($installData)); |
| 196 | $this->getServiceManager()->register(PersistenceManager::SERVICE_ID, $persistenceManager); |
| 197 | } |
| 198 | |
| 199 | $dbCreator = new SetupDb(); |
| 200 | $dbCreator->setLogger($this->logger); |
| 201 | $dbCreator->setupDatabase($persistenceManager->getPersistenceById('default')); |
| 202 | |
| 203 | /* |
| 204 | * 4 - Create the generis config files |
| 205 | */ |
| 206 | |
| 207 | $this->log('d', 'Writing generis config'); |
| 208 | $generisConfigWriter = new tao_install_utils_ConfigWriter( |
| 209 | $this->options['root_path'] . 'generis/config/sample/generis.conf.php', |
| 210 | $this->getGenerisConfig() |
| 211 | ); |
| 212 | |
| 213 | $session_name = $installData['session_name'] ?? self::generateSessionName(); |
| 214 | $generisConfigWriter->createConfig(); |
| 215 | $constants = [ |
| 216 | 'LOCAL_NAMESPACE' => $installData['module_namespace'], |
| 217 | 'GENERIS_INSTANCE_NAME' => $installData['instance_name'], |
| 218 | 'GENERIS_SESSION_NAME' => $session_name, |
| 219 | 'ROOT_PATH' => $this->options['root_path'], |
| 220 | 'FILES_PATH' => $installData['file_path'], |
| 221 | 'ROOT_URL' => $installData['module_url'], |
| 222 | 'DEFAULT_LANG' => $installData['module_lang'], |
| 223 | 'DEBUG_MODE' => ($installData['module_mode'] == 'debug') ? true : false, |
| 224 | 'TIME_ZONE' => $installData['timezone'] |
| 225 | ]; |
| 226 | |
| 227 | $constants['DEFAULT_ANONYMOUS_INTERFACE_LANG'] = $installData['anonymous_lang'] |
| 228 | ?? $installData['module_lang']; |
| 229 | |
| 230 | $generisConfigWriter->writeConstants($constants); |
| 231 | $this->log( |
| 232 | 'd', |
| 233 | 'The following constants were written in generis config:' . PHP_EOL . var_export($constants, true) |
| 234 | ); |
| 235 | |
| 236 | /* |
| 237 | * 4b - Prepare the file/cache folder (FILES_PATH) not yet defined) |
| 238 | * @todo solve this more elegantly |
| 239 | */ |
| 240 | $file_path = $installData['file_path']; |
| 241 | if (is_dir($file_path)) { |
| 242 | $this->log('i', 'Data from previous install found and will be removed'); |
| 243 | if (!helpers_File::emptyDirectory($file_path, true)) { |
| 244 | throw new common_exception_Error('Unable to empty ' . $file_path . ' folder.'); |
| 245 | } |
| 246 | } else { |
| 247 | if (mkdir($file_path, 0700, true)) { |
| 248 | $this->log('d', $file_path . ' directory was created!'); |
| 249 | } else { |
| 250 | throw new Exception($file_path . ' directory creation was failed!'); |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | $setupFileCache = $this->getServiceManager()->get(SetupFileCache::class); |
| 255 | $cachePath = $file_path . 'generis' . DIRECTORY_SEPARATOR . 'cache'; |
| 256 | $setupFileCache->createDirectory($cachePath); |
| 257 | $this->log('d', $cachePath . ' directory was created!'); |
| 258 | |
| 259 | foreach ((array)$installData['extra_persistences'] as $k => $persistence) { |
| 260 | $persistenceManager->registerPersistence($k, $persistence); |
| 261 | } |
| 262 | |
| 263 | /* |
| 264 | * 5 - Run the extensions bootstrap |
| 265 | */ |
| 266 | $this->log('d', 'Running the extensions bootstrap'); |
| 267 | common_Config::load($this->getGenerisConfig()); |
| 268 | |
| 269 | /* |
| 270 | * 5b - Create cache persistence |
| 271 | */ |
| 272 | $this->log('d', 'Creating cache persistence..'); |
| 273 | $setupFileCache->createPersistence(); |
| 274 | |
| 275 | /* |
| 276 | * 6 - Finish Generis Install |
| 277 | */ |
| 278 | |
| 279 | $this->log('d', 'Finishing generis install..'); |
| 280 | $generis = common_ext_ExtensionsManager::singleton()->getExtensionById('generis'); |
| 281 | |
| 282 | $generisInstaller = new common_ext_GenerisInstaller($generis, true); |
| 283 | $generisInstaller->initContainer($this->getContainer()); |
| 284 | $generisInstaller->install(); |
| 285 | |
| 286 | /* |
| 287 | * 7 - Add languages |
| 288 | */ |
| 289 | $this->log('d', 'Adding languages..'); |
| 290 | $ontology = $this->getServiceManager()->get(Ontology::SERVICE_ID); |
| 291 | $langModel = \tao_models_classes_LanguageService::singleton()->getLanguageDefinition(); |
| 292 | $rdfModel = $ontology->getRdfInterface(); |
| 293 | foreach ($langModel as $triple) { |
| 294 | $rdfModel->add($triple); |
| 295 | } |
| 296 | |
| 297 | /* |
| 298 | * 8 - Install the extensions |
| 299 | */ |
| 300 | InstallHelper::initContainer($this->container); |
| 301 | $installed = InstallHelper::installRecursively($extensionIDs, $installData); |
| 302 | $this->log('ext', $installed); |
| 303 | |
| 304 | /* |
| 305 | * 8b - Generates client side translation bundles (depends on extension install) |
| 306 | */ |
| 307 | $this->log('i', 'Generates client side translation bundles'); |
| 308 | |
| 309 | tao_models_classes_LanguageService::singleton()->generateAll(); |
| 310 | |
| 311 | /* |
| 312 | * 9 - Insert Super User |
| 313 | */ |
| 314 | $this->log('i', 'Spawning SuperUser ' . $installData['user_login']); |
| 315 | |
| 316 | $userClass = $ontology->getClass(TaoOntology::CLASS_URI_TAO_USER); |
| 317 | $userid = $installData['module_namespace'] . TaoOntology::DEFAULT_USER_URI_SUFFIX; |
| 318 | $userpwd = core_kernel_users_Service::getPasswordHash()->encrypt($installData['user_pass1']); |
| 319 | $userLang = 'http://www.tao.lu/Ontologies/TAO.rdf#Lang' . $installData['module_lang']; |
| 320 | |
| 321 | $superUser = $userClass->createInstance( |
| 322 | 'Super User', |
| 323 | 'super user created during the TAO installation', |
| 324 | $userid |
| 325 | ); |
| 326 | $superUser->setPropertiesValues([ |
| 327 | GenerisRdf::PROPERTY_USER_ROLES => [ |
| 328 | TaoRoles::GLOBAL_MANAGER, |
| 329 | TaoRoles::SYSTEM_ADMINISTRATOR |
| 330 | ], |
| 331 | TaoOntology::PROPERTY_USER_FIRST_TIME => GenerisRdf::GENERIS_TRUE, |
| 332 | GenerisRdf::PROPERTY_USER_LOGIN => $installData['user_login'], |
| 333 | GenerisRdf::PROPERTY_USER_PASSWORD => $userpwd, |
| 334 | GenerisRdf::PROPERTY_USER_LASTNAME => $installData['user_lastname'], |
| 335 | GenerisRdf::PROPERTY_USER_FIRSTNAME => $installData['user_firstname'], |
| 336 | GenerisRdf::PROPERTY_USER_MAIL => $installData['user_email'], |
| 337 | GenerisRdf::PROPERTY_USER_DEFLG => $userLang, |
| 338 | GenerisRdf::PROPERTY_USER_UILG => $userLang, |
| 339 | GenerisRdf::PROPERTY_USER_TIMEZONE => TIME_ZONE |
| 340 | ]); |
| 341 | |
| 342 | /* |
| 343 | * 10 - Secure the install for production mode |
| 344 | */ |
| 345 | if ($installData['module_mode'] == 'production') { |
| 346 | $extensions = common_ext_ExtensionsManager::singleton()->getInstalledExtensions(); |
| 347 | $this->log('i', 'Securing tao for production'); |
| 348 | |
| 349 | // 11.0 Protect TAO dist |
| 350 | $shield = new tao_install_utils_Shield(array_keys($extensions)); |
| 351 | $shield->disableRewritePattern(["!/test/", "!/doc/"]); |
| 352 | $shield->denyAccessTo([ |
| 353 | 'views/sass', |
| 354 | 'views/js/test', |
| 355 | 'views/build' |
| 356 | ]); |
| 357 | $shield->protectInstall(); |
| 358 | } |
| 359 | |
| 360 | /* |
| 361 | * 11 - Create the version file |
| 362 | */ |
| 363 | $this->log('d', 'Creating TAO version file'); |
| 364 | file_put_contents($installData['file_path'] . 'version', TAO_VERSION); |
| 365 | |
| 366 | /* |
| 367 | * 12 - Register Information about organization operating the system |
| 368 | */ |
| 369 | $this->log('t', 'Registering information about the organization operating the system'); |
| 370 | $operatedByService = $this->getServiceManager()->get(OperatedByService::SERVICE_ID); |
| 371 | |
| 372 | if (!empty($installData['operated_by_name'])) { |
| 373 | $operatedByService->setName($installData['operated_by_name']); |
| 374 | } |
| 375 | |
| 376 | if (!empty($installData['operated_by_email'])) { |
| 377 | $operatedByService->setEmail($installData['operated_by_email']); |
| 378 | } |
| 379 | |
| 380 | $this->getServiceManager()->register(OperatedByService::SERVICE_ID, $operatedByService); |
| 381 | if ($callback) { |
| 382 | $callback(); |
| 383 | } |
| 384 | |
| 385 | $this->recreateDependencyInjectionContainerCache(); |
| 386 | $this->setInstallationFinished(); |
| 387 | } catch (Exception $e) { |
| 388 | if ($this->retryInstallation($e)) { |
| 389 | return; |
| 390 | } |
| 391 | |
| 392 | // In any case, we transmit a single exception type (at the moment) |
| 393 | // for a clearer API for client code. |
| 394 | $this->log('e', 'Error Occurs : ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString()); |
| 395 | throw new tao_install_utils_Exception($e->getMessage(), 0, $e); |
| 396 | } |
| 397 | } |
| 398 | |
| 399 | public function getServiceManager() |
| 400 | { |
| 401 | return $this->oatBoxInstall->setupServiceManager($this->getConfigPath()); |
| 402 | } |
| 403 | |
| 404 | private function retryInstallation($exception) |
| 405 | { |
| 406 | $returnValue = false; |
| 407 | $err = $exception->getMessage(); |
| 408 | |
| 409 | if (strpos($err, 'cannot construct the resource because the uri cannot be empty') === 0 && $this->isWindows()) { |
| 410 | /* |
| 411 | * a known issue |
| 412 | * @see http://forge.taotesting.com/issues/3014 |
| 413 | * this issue can only be fixed by an administrator |
| 414 | * changing the thread_stack system variable in my.ini as following: |
| 415 | * '256K' on 64bit windows |
| 416 | * '192K' on 32bit windows |
| 417 | */ |
| 418 | |
| 419 | $this->log('e', 'Error Occurs : ' . $err . PHP_EOL . $exception->getTraceAsString()); |
| 420 | throw new tao_install_utils_Exception( |
| 421 | "Error in mysql system variable 'thread_stack':<br>It is required to change its value in " |
| 422 | . "my.ini as following<br>'192K' on 32bit windows<br>'256K' on 64bit windows.<br><br>Note that " |
| 423 | . "such configuration changes will only take effect after server restart.<br><br>", |
| 424 | 0, |
| 425 | $exception |
| 426 | ); |
| 427 | } |
| 428 | |
| 429 | if (!$returnValue) { |
| 430 | return false; |
| 431 | } |
| 432 | |
| 433 | // it is a known issue, go ahead to retry with the issue fixer |
| 434 | $this->install($this->config); |
| 435 | return true; |
| 436 | } |
| 437 | |
| 438 | private function isWindows() |
| 439 | { |
| 440 | return strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'; |
| 441 | } |
| 442 | |
| 443 | /** |
| 444 | * Generate an alphanum token to be used as a PHP session name. |
| 445 | * |
| 446 | * @access public |
| 447 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 448 | * @return string |
| 449 | */ |
| 450 | public static function generateSessionName() |
| 451 | { |
| 452 | return 'tao_' . helpers_Random::generateString(8); |
| 453 | } |
| 454 | |
| 455 | /** |
| 456 | * Check the install data information such as |
| 457 | * - instance name |
| 458 | * - database driver |
| 459 | * - ... |
| 460 | * |
| 461 | * If a parameter of the $installData is not valid regarding the install |
| 462 | * business rules, an MalformedInstall |
| 463 | * |
| 464 | * @param array $installData |
| 465 | */ |
| 466 | public static function checkInstallData(array $installData) |
| 467 | { |
| 468 | // instance name |
| 469 | if (empty($installData['instance_name'])) { |
| 470 | $msg = "Missing install parameter 'instance_name'."; |
| 471 | throw new tao_install_utils_MalformedParameterException($msg); |
| 472 | } elseif (!is_string($installData['instance_name'])) { |
| 473 | $msg = "Malformed install parameter 'instance_name'. It must be a string."; |
| 474 | throw new tao_install_utils_MalformedParameterException($msg); |
| 475 | } elseif (1 === preg_match('/\s/u', $installData['instance_name'])) { |
| 476 | $msg = "Malformed install parameter 'instance_name'. It cannot contain spacing characters " |
| 477 | . "(tab, backspace)."; |
| 478 | throw new tao_install_utils_MalformedParameterException($msg); |
| 479 | } |
| 480 | } |
| 481 | |
| 482 | /** |
| 483 | * Tell the Installator instance to not take into account |
| 484 | * a Configuration Check with ID = $id. |
| 485 | * |
| 486 | * @param string $id The identifier of the check to escape. |
| 487 | */ |
| 488 | public function escapeCheck($id) |
| 489 | { |
| 490 | $checks = $this->getEscapedChecks(); |
| 491 | array_push($checks, $id); |
| 492 | $checks = array_unique($checks); |
| 493 | $this->setEscapedChecks($checks); |
| 494 | } |
| 495 | |
| 496 | /** |
| 497 | * Obtain an array of Configuration Check IDs to be escaped by |
| 498 | * the Installator. |
| 499 | * |
| 500 | * @return array |
| 501 | */ |
| 502 | public function getEscapedChecks() |
| 503 | { |
| 504 | return $this->escapedChecks; |
| 505 | } |
| 506 | |
| 507 | /** |
| 508 | * Set the array of Configuration Check IDs to be escaped by |
| 509 | * the Installator. |
| 510 | * |
| 511 | * @param array $escapedChecks An array of strings. |
| 512 | * @return void |
| 513 | */ |
| 514 | public function setEscapedChecks(array $escapedChecks) |
| 515 | { |
| 516 | $this->escapedChecks = $escapedChecks; |
| 517 | } |
| 518 | |
| 519 | /** |
| 520 | * Informs you if a given Configuration Check ID corresponds |
| 521 | * to a Check that has to be escaped. |
| 522 | */ |
| 523 | public function isEscapedCheck($id) |
| 524 | { |
| 525 | return in_array($id, $this->getEscapedChecks()); |
| 526 | } |
| 527 | |
| 528 | /** |
| 529 | * Log message and add it to $this->log array; |
| 530 | * @see common_Logger class |
| 531 | * @param string $logLevel |
| 532 | * <ul> |
| 533 | * <li>'w' - warning</li> |
| 534 | * <li>'t' - trace</li> |
| 535 | * <li>'d' - debug</li> |
| 536 | * <li>'i' - info</li> |
| 537 | * <li>'e' - error</li> |
| 538 | * <li>'f' - fatal</li> |
| 539 | * <li>'ext' - installed extensions</li> |
| 540 | * </ul> |
| 541 | * @param string $message |
| 542 | * @param array $tags |
| 543 | */ |
| 544 | public function log($logLevel, $message, $tags = []) |
| 545 | { |
| 546 | if (!is_array($tags)) { |
| 547 | $tags = [$tags]; |
| 548 | } |
| 549 | if ($this->getLogger() instanceof \Psr\Log\LoggerInterface) { |
| 550 | if ($logLevel === 'ext') { |
| 551 | $this->logNotice('Installed extensions: ' . implode(', ', $message)); |
| 552 | } else { |
| 553 | $this->getLogger()->log( |
| 554 | common_log_Logger2Psr::getPsrLevelFromCommon($logLevel), |
| 555 | $message |
| 556 | ); |
| 557 | } |
| 558 | } |
| 559 | if (method_exists('common_Logger', $logLevel)) { |
| 560 | call_user_func('common_Logger::' . $logLevel, $message, $tags); |
| 561 | } |
| 562 | if (is_array($message)) { |
| 563 | $this->log[$logLevel] = (isset($this->log[$logLevel])) |
| 564 | ? array_merge($this->log[$logLevel], $message) |
| 565 | : $message; |
| 566 | } else { |
| 567 | $this->log[$logLevel][] = $message; |
| 568 | } |
| 569 | } |
| 570 | |
| 571 | /** |
| 572 | * Get array of log messages |
| 573 | * @return array |
| 574 | */ |
| 575 | public function getLog() |
| 576 | { |
| 577 | return $this->log; |
| 578 | } |
| 579 | |
| 580 | /** |
| 581 | * Get the config file platform e.q. generis.conf.php |
| 582 | * |
| 583 | * @return string |
| 584 | */ |
| 585 | protected function getGenerisConfig() |
| 586 | { |
| 587 | return $this->getConfigPath() . 'generis.conf.php'; |
| 588 | } |
| 589 | |
| 590 | /** |
| 591 | * Get the config path for installation |
| 592 | * If options have installation_config_path, it's taken otherwise it's root_path |
| 593 | * |
| 594 | * @return string |
| 595 | */ |
| 596 | protected function getConfigPath() |
| 597 | { |
| 598 | if (isset($this->options['installation_config_path'])) { |
| 599 | return $this->options['installation_config_path']; |
| 600 | } else { |
| 601 | return $this->options['root_path'] . 'config' . DIRECTORY_SEPARATOR; |
| 602 | } |
| 603 | } |
| 604 | |
| 605 | /** |
| 606 | * Mark application as ready to be used (all extensions installed and post scripts executed) |
| 607 | * @throws common_Exception |
| 608 | */ |
| 609 | private function setInstallationFinished() |
| 610 | { |
| 611 | $applicationService = $this->getServiceManager()->get(ApplicationService::SERVICE_ID); |
| 612 | $applicationService->setOption(ApplicationService::OPTION_INSTALLATION_FINISHED, true); |
| 613 | $this->getServiceManager()->register(ApplicationService::SERVICE_ID, $applicationService); |
| 614 | } |
| 615 | |
| 616 | private function recreateDependencyInjectionContainerCache(): void |
| 617 | { |
| 618 | ServiceManager::getServiceManager()->rebuildContainer(); |
| 619 | } |
| 620 | } |