Passed
Push — developer ( 6b5868...bed0f9 )
by Radosław
22:42 queued 03:39
created

Install_InitSchema_Model   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 46
eloc 133
c 0
b 0
f 0
dl 0
loc 202
rs 8.72

6 Methods

Rating   Name   Duplication   Size   Complexity  
B initializeDatabase() 0 40 10
A setDefaultUsersAccess() 0 26 5
B setLanguage() 0 5 8
A initialize() 0 35 2
C splitQueries() 0 44 15
A createConfigFiles() 0 21 6

How to fix   Complexity   

Complex Class

Complex classes like Install_InitSchema_Model often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Install_InitSchema_Model, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* +***********************************************************************************
3
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
4
 * ("License"); You may not use this file except in compliance with the License
5
 * The Original Code is:  vtiger CRM Open Source
6
 * The Initial Developer of the Original Code is vtiger.
7
 * Portions created by vtiger are Copyright (C) vtiger.
8
 * All Rights Reserved.
9
 * *********************************************************************************** */
10
11
class Install_InitSchema_Model
12
{
13
	protected $sql_directory = 'install/install_schema/';
14
	protected $migration_schema = 'install/migrate_schema/';
15
16
	/**
17
	 * Function starts applying schema changes.
18
	 */
19
	public function initialize()
20
	{
21
		$this->db = \App\Db::getInstance();
0 ignored issues
show
Bug Best Practice introduced by
The property db does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
22
		$this->initializeDatabase($this->sql_directory, ['scheme', 'data']);
23
		if ($_SESSION['installation_success'] ?? false) {
24
			$this->setLanguage();
25
			$this->createConfigFiles();
26
			$this->setDefaultUsersAccess();
27
			$this->db->createCommand()
28
				->update('vtiger_currency_info', [
29
					'currency_name' => $_SESSION['config_file_info']['currency_name'],
30
					'currency_code' => $_SESSION['config_file_info']['currency_code'],
31
					'currency_symbol' => $_SESSION['config_file_info']['currency_symbol'],
32
				])->execute();
33
			$this->db->createCommand()
34
				->update('vtiger_version', [
35
					'current_version' => \App\Version::get(),
36
					'old_version' => \App\Version::get(),
37
				])->execute();
38
			// recalculate all sharing rules for users
39
			require_once 'include/utils/CommonUtils.php';
40
			require_once 'include/fields/DateTimeField.php';
41
			require_once 'include/fields/DateTimeRange.php';
42
			require_once 'include/fields/CurrencyField.php';
43
			require_once 'include/CRMEntity.php';
44
			require_once 'modules/Vtiger/CRMEntity.php';
45
			require_once 'include/runtime/Cache.php';
46
			require_once 'modules/Vtiger/helpers/Util.php';
47
			require_once 'modules/PickList/DependentPickListUtils.php';
48
			require_once 'modules/Users/Users.php';
49
			require_once 'include/Webservices/Utils.php';
50
			\App\UserPrivilegesFile::recalculateAll();
51
			\App\Cache::clear();
52
			\App\Cache::clearOpcache();
53
			\App\Module::createModuleMetaFile();
54
		}
55
	}
56
57
	public function initializeDatabase($location, $filesName = [])
58
	{
59
		try {
60
			$return = false;
61
			$this->db->createCommand('SET FOREIGN_KEY_CHECKS = 0;')->execute();
62
			if (!$filesName) {
63
				throw new \App\Exceptions\AppException('No files', 405);
64
			}
65
			$splitQueries = '';
66
			foreach ($filesName as $name) {
67
				$sql_file = $location . $name . '.sql';
68
				$return = true;
69
				if (!($fileBuffer = file_get_contents($sql_file))) {
70
					throw new \App\Exceptions\AppException('Invalid file: ' . $sql_file, 405);
71
				}
72
				$splitQueries .= $fileBuffer;
73
			}
74
			$createQuery = substr_count($splitQueries, 'CREATE TABLE');
75
			$insertQuery = substr_count($splitQueries, 'INSERT INTO');
76
			$alterQuery = substr_count($splitQueries, 'ALTER TABLE');
77
			$executedQuery = 0;
78
			$queries = $this->splitQueries($splitQueries);
79
			foreach ($queries as $query) {
80
				// Trim any whitespace.
81
				$query = trim($query);
82
				if (!empty($query) && ('#' != $query[0]) && ('-' != $query[0])) {
83
					$this->db->createCommand($query)->execute();
84
					++$executedQuery;
85
				}
86
			}
87
			\App\Log::info("create_query: $createQuery | insert_query: $insertQuery | alter_query: $alterQuery | executed_query: $executedQuery");
88
			$_SESSION['installation_success'] = $createQuery && $executedQuery;
89
		} catch (Throwable $e) {
90
			$return = false;
91
			\App\Log::error($e->__toString(), 'Install');
92
			$_SESSION['installation_success'] = false;
93
		} finally {
94
			$this->db->createCommand('SET FOREIGN_KEY_CHECKS = 1;')->execute();
95
		}
96
		return ['status' => $return, 'create' => $createQuery, 'insert' => $insertQuery, 'alter' => $alterQuery, 'executed' => $executedQuery];
97
	}
98
99
	/**
100
	 * Function creates default user's Role, Profiles.
101
	 */
102
	public function setDefaultUsersAccess()
103
	{
104
		if (empty($_SESSION['config_file_info']['user_name'])) {
105
			return false;
106
		}
107
		$lang = $_SESSION['language'] ?? '';
108
		$this->db->createCommand()
109
			->update('vtiger_users', [
110
				'user_name' => $_SESSION['config_file_info']['user_name'],
111
				'date_format' => $_SESSION['config_file_info']['dateformat'],
112
				'time_zone' => $_SESSION['config_file_info']['default_timezone'],
113
				'first_name' => $_SESSION['config_file_info']['firstname'],
114
				'last_name' => $_SESSION['config_file_info']['lastname'],
115
				'email1' => $_SESSION['config_file_info']['admin_email'],
116
				'accesskey' => \App\Encryption::generatePassword(20, 'lbn'),
117
				'language' => ($lang && \App\Language::DEFAULT_LANG !== $lang && \App\Language::getLangInfo($lang)) ? $lang : \App\Language::DEFAULT_LANG,
118
			])->execute();
119
		$userRecordModel = Users_Record_Model::getInstanceById(1, 'Users');
120
		$userRecordModel->set('user_password', $_SESSION['config_file_info']['password']);
121
		$userRecordModel->save();
122
		$this->db->createCommand()
123
			->update('vtiger_users', [
124
				'force_password_change' => 0,
125
			])->execute();
126
		require_once 'app/UserPrivilegesFile.php';
127
		\App\UserPrivilegesFile::createUserPrivilegesfile(1);
128
	}
129
130
	public function splitQueries($query)
131
	{
132
		$buffer = [];
133
		$queries = [];
134
		$in_string = false;
135
136
		// Trim any whitespace.
137
		$query = trim($query);
138
		// Remove comment lines.
139
		$query = preg_replace("/\n\\#[^\n]*/", '', "\n" . $query);
140
		// Remove PostgreSQL comment lines.
141
		$query = preg_replace("/\n\\--[^\n]*/", '', "\n" . $query);
142
		// Find function
143
		$funct = explode('CREATE || REPLACE FUNCTION', $query);
144
		// Save sql before function and parse it
145
		$query = $funct[0];
146
147
		// Parse the schema file to break up queries.
148
		for ($i = 0; $i < \strlen($query) - 1; ++$i) {
149
			if (';' == $query[$i] && !$in_string) {
150
				$queries[] = substr($query, 0, $i);
151
				$query = substr($query, $i + 1);
152
				$i = 0;
153
			}
154
			if ($in_string && ($query[$i] == $in_string) && '\\' != $buffer[1]) {
155
				$in_string = false;
156
			} elseif (!$in_string && ('"' == $query[$i] || "'" == $query[$i]) && (!isset($buffer[0]) || '\\' != $buffer[0])) {
157
				$in_string = $query[$i];
158
			}
159
			if (isset($buffer[1])) {
160
				$buffer[0] = $buffer[1];
161
			}
162
			$buffer[1] = $query[$i];
163
		}
164
		// If the is anything left over, add it to the queries.
165
		if (!empty($query)) {
166
			$queries[] = $query;
167
		}
168
		// Add function part as is
169
		$countFunct = \count($funct);
170
		for ($f = 1; $f < $countFunct; ++$f) {
171
			$queries[] = 'CREATE || REPLACE FUNCTION ' . $funct[$f];
172
		}
173
		return $queries;
174
	}
175
176
	/**
177
	 * Set default language.
178
	 *
179
	 * @return void
180
	 */
181
	private function setLanguage()
182
	{
183
		$lang = $_SESSION['language'] ?? '';
184
		if ($lang && \App\Language::DEFAULT_LANG !== $lang && ($languages = \App\Installer\Languages::getAll()) && isset($languages[$lang]) && (int) $languages[$lang]['progress'] > 60 && \App\Installer\Languages::download($lang) && \App\Language::getLangInfo($lang)) {
185
			Settings_LangManagement_Module_Model::setAsDefault($lang);
186
		}
187
	}
188
189
	/**
190
	 * Create config files.
191
	 */
192
	private function createConfigFiles()
193
	{
194
		$skip = ['main', 'db', 'performance', 'debug', 'security', 'module', 'component'];
195
		foreach (array_diff(\App\ConfigFile::TYPES, $skip) as $type) {
196
			(new \App\ConfigFile($type))->create();
197
		}
198
		$dirPath = \ROOT_DIRECTORY . \DIRECTORY_SEPARATOR . 'config' . \DIRECTORY_SEPARATOR . 'Modules';
199
		if (!is_dir($dirPath)) {
200
			mkdir($dirPath);
201
		}
202
		$dataReader = (new \App\Db\Query())->select(['name'])->from('vtiger_tab')->createCommand()->query();
203
		while ($moduleName = $dataReader->readColumn(0)) {
204
			$filePath = 'modules' . \DIRECTORY_SEPARATOR . $moduleName . \DIRECTORY_SEPARATOR . 'ConfigTemplate.php';
205
			if (file_exists($filePath)) {
206
				(new \App\ConfigFile('module', $moduleName))->create();
207
			}
208
		}
209
		$path = \ROOT_DIRECTORY . \DIRECTORY_SEPARATOR . 'config' . \DIRECTORY_SEPARATOR . 'Components' . \DIRECTORY_SEPARATOR . 'ConfigTemplates.php';
210
		$componentsData = require_once "$path";
211
		foreach ($componentsData as $component => $data) {
212
			(new \App\ConfigFile('component', $component))->create();
213
		}
214
	}
215
}
216