Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Setup 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 Setup, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
45 | class Setup { |
||
46 | /** @var \OCP\IConfig */ |
||
47 | protected $config; |
||
48 | /** @var IniGetWrapper */ |
||
49 | protected $iniWrapper; |
||
50 | /** @var IL10N */ |
||
51 | protected $l10n; |
||
52 | /** @var \OC_Defaults */ |
||
53 | protected $defaults; |
||
54 | /** @var ILogger */ |
||
55 | protected $logger; |
||
56 | /** @var ISecureRandom */ |
||
57 | protected $random; |
||
58 | |||
59 | /** |
||
60 | * @param IConfig $config |
||
61 | * @param IniGetWrapper $iniWrapper |
||
62 | * @param \OC_Defaults $defaults |
||
63 | */ |
||
64 | 12 | function __construct(IConfig $config, |
|
65 | IniGetWrapper $iniWrapper, |
||
66 | IL10N $l10n, |
||
67 | \OC_Defaults $defaults, |
||
68 | ILogger $logger, |
||
69 | ISecureRandom $random |
||
70 | ) { |
||
71 | 12 | $this->config = $config; |
|
72 | 12 | $this->iniWrapper = $iniWrapper; |
|
73 | 12 | $this->l10n = $l10n; |
|
74 | 12 | $this->defaults = $defaults; |
|
75 | 12 | $this->logger = $logger; |
|
76 | 12 | $this->random = $random; |
|
77 | 12 | } |
|
78 | |||
79 | static $dbSetupClasses = array( |
||
80 | 'mysql' => '\OC\Setup\MySQL', |
||
81 | 'pgsql' => '\OC\Setup\PostgreSQL', |
||
82 | 'oci' => '\OC\Setup\OCI', |
||
83 | 'sqlite' => '\OC\Setup\Sqlite', |
||
84 | 'sqlite3' => '\OC\Setup\Sqlite', |
||
85 | ); |
||
86 | |||
87 | /** |
||
88 | * Wrapper around the "class_exists" PHP function to be able to mock it |
||
89 | * @param string $name |
||
90 | * @return bool |
||
91 | */ |
||
92 | 7 | protected function class_exists($name) { |
|
95 | |||
96 | /** |
||
97 | * Wrapper around the "is_callable" PHP function to be able to mock it |
||
98 | * @param string $name |
||
99 | * @return bool |
||
100 | */ |
||
101 | 7 | protected function is_callable($name) { |
|
104 | |||
105 | /** |
||
106 | * Wrapper around \PDO::getAvailableDrivers |
||
107 | * |
||
108 | * @return array |
||
109 | */ |
||
110 | 7 | protected function getAvailableDbDriversForPdo() { |
|
113 | |||
114 | /** |
||
115 | * Get the available and supported databases of this instance |
||
116 | * |
||
117 | * @param bool $allowAllDatabases |
||
118 | * @return array |
||
119 | * @throws Exception |
||
120 | */ |
||
121 | 11 | public function getSupportedDatabases($allowAllDatabases = false) { |
|
122 | $availableDatabases = array( |
||
123 | 'sqlite' => array( |
||
124 | 11 | 'type' => 'class', |
|
125 | 11 | 'call' => 'SQLite3', |
|
126 | 'name' => 'SQLite' |
||
127 | 11 | ), |
|
128 | 'mysql' => array( |
||
129 | 11 | 'type' => 'pdo', |
|
130 | 11 | 'call' => 'mysql', |
|
131 | 'name' => 'MySQL/MariaDB' |
||
132 | 11 | ), |
|
133 | 'pgsql' => array( |
||
134 | 11 | 'type' => 'function', |
|
135 | 11 | 'call' => 'pg_connect', |
|
136 | 'name' => 'PostgreSQL' |
||
137 | 11 | ), |
|
138 | 'oci' => array( |
||
139 | 11 | 'type' => 'function', |
|
140 | 11 | 'call' => 'oci_connect', |
|
141 | 'name' => 'Oracle' |
||
142 | 11 | ) |
|
143 | 11 | ); |
|
144 | 11 | if ($allowAllDatabases) { |
|
145 | $configuredDatabases = array_keys($availableDatabases); |
||
146 | } else { |
||
147 | 11 | $configuredDatabases = $this->config->getSystemValue('supportedDatabases', |
|
148 | 11 | array('sqlite', 'mysql', 'pgsql')); |
|
149 | } |
||
150 | 11 | if(!is_array($configuredDatabases)) { |
|
151 | 1 | throw new Exception('Supported databases are not properly configured.'); |
|
152 | } |
||
153 | |||
154 | 10 | $supportedDatabases = array(); |
|
155 | |||
156 | 10 | foreach($configuredDatabases as $database) { |
|
157 | 10 | if(array_key_exists($database, $availableDatabases)) { |
|
158 | 10 | $working = false; |
|
159 | 10 | $type = $availableDatabases[$database]['type']; |
|
160 | 10 | $call = $availableDatabases[$database]['call']; |
|
161 | |||
162 | 10 | if($type === 'class') { |
|
163 | 10 | $working = $this->class_exists($call); |
|
164 | 10 | } elseif ($type === 'function') { |
|
165 | 10 | $working = $this->is_callable($call); |
|
166 | 10 | } elseif($type === 'pdo') { |
|
167 | 10 | $working = in_array($call, $this->getAvailableDbDriversForPdo(), TRUE); |
|
168 | 10 | } |
|
169 | 10 | if($working) { |
|
170 | 9 | $supportedDatabases[$database] = $availableDatabases[$database]['name']; |
|
171 | 9 | } |
|
172 | 10 | } |
|
173 | 10 | } |
|
174 | |||
175 | 10 | return $supportedDatabases; |
|
176 | } |
||
177 | |||
178 | /** |
||
179 | * Gathers system information like database type and does |
||
180 | * a few system checks. |
||
181 | * |
||
182 | * @return array of system info, including an "errors" value |
||
183 | * in case of errors/warnings |
||
184 | */ |
||
185 | public function getSystemInfo($allowAllDatabases = false) { |
||
186 | $databases = $this->getSupportedDatabases($allowAllDatabases); |
||
187 | |||
188 | $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data'); |
||
189 | |||
190 | $errors = array(); |
||
191 | |||
192 | // Create data directory to test whether the .htaccess works |
||
193 | // Notice that this is not necessarily the same data directory as the one |
||
194 | // that will effectively be used. |
||
195 | @mkdir($dataDir); |
||
196 | $htAccessWorking = true; |
||
197 | if (is_dir($dataDir) && is_writable($dataDir)) { |
||
198 | // Protect data directory here, so we can test if the protection is working |
||
199 | \OC\Setup::protectDataDirectory(); |
||
200 | |||
201 | try { |
||
202 | $util = new \OC_Util(); |
||
203 | $htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig()); |
||
204 | } catch (\OC\HintException $e) { |
||
205 | $errors[] = array( |
||
206 | 'error' => $e->getMessage(), |
||
207 | 'hint' => $e->getHint() |
||
208 | ); |
||
209 | $htAccessWorking = false; |
||
210 | } |
||
211 | } |
||
212 | |||
213 | if (\OC_Util::runningOnMac()) { |
||
214 | $errors[] = array( |
||
215 | 'error' => $this->l10n->t( |
||
216 | 'Mac OS X is not supported and %s will not work properly on this platform. ' . |
||
217 | 'Use it at your own risk! ', |
||
218 | $this->defaults->getName() |
||
|
|||
219 | ), |
||
220 | 'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.') |
||
221 | ); |
||
222 | } |
||
223 | |||
224 | if($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) { |
||
225 | $errors[] = array( |
||
226 | 'error' => $this->l10n->t( |
||
227 | 'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' . |
||
228 | 'This will lead to problems with files over 4 GB and is highly discouraged.', |
||
229 | $this->defaults->getName() |
||
230 | ), |
||
231 | 'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.') |
||
232 | ); |
||
233 | } |
||
234 | |||
235 | return array( |
||
236 | 'hasSQLite' => isset($databases['sqlite']), |
||
237 | 'hasMySQL' => isset($databases['mysql']), |
||
238 | 'hasPostgreSQL' => isset($databases['pgsql']), |
||
239 | 'hasOracle' => isset($databases['oci']), |
||
240 | 'databases' => $databases, |
||
241 | 'directory' => $dataDir, |
||
242 | 'htaccessWorking' => $htAccessWorking, |
||
243 | 'errors' => $errors, |
||
244 | ); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * @param $options |
||
249 | * @return array |
||
250 | */ |
||
251 | public function install($options) { |
||
389 | |||
390 | /** |
||
391 | * @return string Absolute path to htaccess |
||
392 | */ |
||
393 | 1 | private function pathToHtaccess() { |
|
396 | |||
397 | /** |
||
398 | * Checks if the .htaccess contains the current version parameter |
||
399 | * |
||
400 | * @return bool |
||
401 | */ |
||
402 | 1 | private function isCurrentHtaccess() { |
|
411 | |||
412 | /** |
||
413 | * Append the correct ErrorDocument path for Apache hosts |
||
414 | * |
||
415 | * @throws \OC\HintException If .htaccess does not include the current version |
||
416 | */ |
||
417 | public static function updateHtaccess() { |
||
440 | |||
441 | public static function protectDataDirectory() { |
||
459 | } |
||
460 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: