]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Core/Install.php
bc16b85ae3bd969c56d0d594df9c17ed637a297c
[galette.git] / galette / lib / Galette / Core / Install.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Galette installation
7 *
8 * PHP version 5
9 *
10 * Copyright © 2013-2014 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Core
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2013-2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.8 - 2013-01-09
35 */
36
37 namespace Galette\Core;
38
39 use Throwable;
40 use Analog\Analog;
41 use Laminas\Db\Adapter\Adapter;
42
43 /**
44 * Galette installation
45 *
46 * @category Core
47 * @name Install
48 * @package Galette
49 * @author Johan Cwiklinski <johan@x-tnd.be>
50 * @copyright 2013-2014 The Galette Team
51 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
52 * @link http://galette.tuxfamily.org
53 * @since Available since 0.8 - 2013-01-09
54 */
55 class Install
56 {
57 public const STEP_CHECK = 0;
58 public const STEP_TYPE = 1;
59 public const STEP_DB = 2;
60 public const STEP_DB_CHECKS = 3;
61 public const STEP_VERSION = 4; //only for update
62 public const STEP_DB_UPGRADE = 5;
63 public const STEP_DB_INSTALL = 6;
64 public const STEP_ADMIN = 7;
65 public const STEP_GALETTE_INIT = 8;
66 public const STEP_END = 9;
67
68 public const INSTALL = 'i';
69 public const UPDATE = 'u';
70
71 //db version/galette version mapper
72 private $versions_mapper = array(
73 '0.700' => '0.70',
74 '0.701' => '0.71',
75 '0.702' => '0.74',
76 '0.703' => '0.75',
77 '0.704' => '0.76'
78 );
79
80 private $_step;
81 private $_mode;
82 private $_version;
83 private $_installed_version;
84
85 private $_db_type;
86 private $_db_host;
87 private $_db_port;
88 private $_db_name;
89 private $_db_user;
90 private $_db_pass;
91
92 private $_db_connected;
93 private $_report;
94
95 private $_admin_login;
96 private $_admin_pass;
97
98 private $_error;
99
100 /**
101 * Main constructor
102 */
103 public function __construct()
104 {
105 $this->_step = self::STEP_CHECK;
106 $this->_mode = null;
107 $this->_version = str_replace('v', '', GALETTE_VERSION);
108 $this->_db_connected = false;
109 $this->_db_prefix = null;
110 }
111
112 /**
113 * Return current step title
114 *
115 * @return string
116 */
117 public function getStepTitle()
118 {
119 $step_title = null;
120 switch ($this->_step) {
121 case self::STEP_CHECK:
122 $step_title = _T("Checks");
123 break;
124 case self::STEP_TYPE:
125 $step_title = _T("Installation mode");
126 break;
127 case self::STEP_DB:
128 $step_title = _T("Database");
129 break;
130 case self::STEP_DB_CHECKS:
131 $step_title = _T("Database access and permissions");
132 break;
133 case self::STEP_VERSION:
134 $step_title = _T("Previous version selection");
135 break;
136 case self::STEP_DB_UPGRADE:
137 $step_title = _T("Datapase upgrade");
138 break;
139 case self::STEP_DB_INSTALL:
140 $step_title = _T("Tables Creation");
141 break;
142 case self::STEP_ADMIN:
143 $step_title = _T("Admin parameters");
144 break;
145 case self::STEP_GALETTE_INIT:
146 $step_title = _T("Galette initialization");
147 break;
148 case self::STEP_END:
149 $step_title = _T("End!");
150 break;
151 }
152 return $step_title;
153 }
154
155 /**
156 * HTML validation image
157 *
158 * @param boolean $arg Argument
159 *
160 * @return html string
161 */
162 public function getValidationImage($arg)
163 {
164 $img_name = ($arg === true) ? 'valid' : 'invalid';
165 $src = GALETTE_THEME_DIR . 'images/icon-' . $img_name . '.png';
166 $alt = ($arg === true) ? _T("Ok") : _T("Ko");
167 $img = '<img src="' . $src . '" alt="' . $alt . '"/>';
168 return $img;
169 }
170
171 /**
172 * Get current mode
173 *
174 * @return char
175 */
176 public function getMode()
177 {
178 return $this->_mode;
179 }
180
181 /**
182 * Are we installing?
183 *
184 * @return boolean
185 */
186 public function isInstall()
187 {
188 return $this->_mode === self::INSTALL;
189 }
190
191 /**
192 * Are we upgrading?
193 *
194 * @return boolean
195 */
196 public function isUpgrade()
197 {
198 return $this->_mode === self::UPDATE;
199 }
200
201 /**
202 * Set installation mode
203 *
204 * @param char $mode Requested mode
205 *
206 * @return void
207 */
208 public function setMode($mode)
209 {
210 if ($mode === self::INSTALL || $mode === self::UPDATE) {
211 $this->_mode = $mode;
212 } else {
213 throw new \UnexpectedValueException('Unknown mode "' . $mode . '"');
214 }
215 }
216
217 /**
218 * Go back to previous step
219 *
220 * @return void
221 */
222 public function atPreviousStep()
223 {
224 if ($this->_step > 0) {
225 if (
226 $this->_step - 1 !== self::STEP_DB_INSTALL
227 && $this->_step !== self::STEP_END
228 ) {
229 if ($this->_step === self::STEP_DB_INSTALL) {
230 $this->_step = self::STEP_DB_CHECKS;
231 } else {
232 if ($this->_step === self::STEP_DB_UPGRADE) {
233 $this->setInstalledVersion(null);
234 }
235 $this->_step = $this->_step - 1;
236 }
237 } else {
238 $msg = null;
239 if ($this->_step === self::STEP_END) {
240 $msg = 'Ok man, install is finished already!';
241 } else {
242 $msg = 'It is forbidden to rerun database install!';
243 }
244 Analog::log($msg, Analog::WARNING);
245 }
246 }
247 }
248
249 /**
250 * Are we at check step?
251 *
252 * @return boolean
253 */
254 public function isCheckStep()
255 {
256 return $this->_step === self::STEP_CHECK;
257 }
258
259 /**
260 * Set step to type of installation
261 *
262 * @return void
263 */
264 public function atTypeStep()
265 {
266 $this->_step = self::STEP_TYPE;
267 }
268
269 /**
270 * Are we at type step?
271 *
272 * @return boolean
273 */
274 public function isTypeStep()
275 {
276 return $this->_step === self::STEP_TYPE;
277 }
278
279 /**
280 * Set step to database information
281 *
282 * @return void
283 */
284 public function atDbStep()
285 {
286 $this->_step = self::STEP_DB;
287 }
288
289 /**
290 * Are we at database step?
291 *
292 * @return boolean
293 */
294 public function isDbStep()
295 {
296 return $this->_step === self::STEP_DB;
297 }
298
299 /**
300 * Is DB step passed?
301 *
302 * @return boolean
303 */
304 public function postCheckDb()
305 {
306 return $this->_step > self::STEP_DB_CHECKS;
307 }
308
309 /**
310 * Set database type
311 *
312 * @param string $type Database type
313 * @param array $errs Errors array
314 *
315 * @return boolean
316 */
317 public function setDbType($type, &$errs)
318 {
319 switch ($type) {
320 case Db::MYSQL:
321 case Db::PGSQL:
322 $this->_db_type = $type;
323 break;
324 default:
325 $errs[] = _T("Database type unknown");
326 }
327 }
328
329 /**
330 * Get database type
331 *
332 * @return string
333 */
334 public function getDbType()
335 {
336 return $this->_db_type;
337 }
338
339 /**
340 * Set connection information
341 *
342 * @param string $host Database host
343 * @param string $port Database port
344 * @param string $name Database name
345 * @param string $user Database user name
346 * @param string $pass Database user's password
347 *
348 * @return void
349 */
350 public function setDsn($host, $port, $name, $user, $pass)
351 {
352 $this->_db_host = $host;
353 $this->_db_port = $port;
354 $this->_db_name = $name;
355 $this->_db_user = $user;
356 $this->_db_pass = $pass;
357 }
358
359 /**
360 * Set tables prefix
361 *
362 * @param string $prefix Prefix
363 *
364 * @return void
365 */
366 public function setTablesPrefix($prefix)
367 {
368 $this->_db_prefix = $prefix;
369 }
370
371 /**
372 * Retrieve database host
373 *
374 * @return string
375 */
376 public function getDbHost()
377 {
378 return $this->_db_host;
379 }
380
381 /**
382 * Retrieve database port
383 *
384 * @return string
385 */
386 public function getDbPort()
387 {
388 return $this->_db_port;
389 }
390
391 /**
392 * Retrieve database name
393 *
394 * @return string
395 */
396 public function getDbName()
397 {
398 return $this->_db_name;
399 }
400
401 /**
402 * Retrieve database user
403 *
404 * @return string
405 */
406 public function getDbUser()
407 {
408 return $this->_db_user;
409 }
410
411 /**
412 * Retrieve database password
413 *
414 * @return string
415 */
416 public function getDbPass()
417 {
418 return $this->_db_pass;
419 }
420
421 /**
422 * Retrieve tables prefix
423 *
424 * @return string
425 */
426 public function getTablesPrefix()
427 {
428 return $this->_db_prefix;
429 }
430
431 /**
432 * Set step to database checks
433 *
434 * @return void
435 */
436 public function atDbCheckStep()
437 {
438 $this->_step = self::STEP_DB_CHECKS;
439 }
440
441 /**
442 * Are we at database check step?
443 *
444 * @return boolean
445 */
446 public function isDbCheckStep()
447 {
448 return $this->_step === self::STEP_DB_CHECKS;
449 }
450
451 /**
452 * Test database connection
453 *
454 * @return true|array true if connection was successfull,
455 * an array with some infos otherwise
456 */
457 public function testDbConnexion()
458 {
459 return Db::testConnectivity(
460 $this->_db_type,
461 $this->_db_user,
462 $this->_db_pass,
463 $this->_db_host,
464 $this->_db_port,
465 $this->_db_name
466 );
467 }
468
469 /**
470 * Is database connexion ok?
471 *
472 * @return boolean
473 */
474 public function isDbConnected()
475 {
476 return $this->_db_connected;
477 }
478
479 /**
480 * Set step to version selection
481 *
482 * @return void
483 */
484 public function atVersionSelection()
485 {
486 $this->_step = self::STEP_VERSION;
487 }
488
489 /**
490 * Are we at version selection step?
491 *
492 * @return boolean
493 */
494 public function isVersionSelectionStep()
495 {
496 return $this->_step === self::STEP_VERSION;
497 }
498
499 /**
500 * Set step to database installation
501 *
502 * @return void
503 */
504 public function atDbInstallStep()
505 {
506 $this->_step = self::STEP_DB_INSTALL;
507 }
508
509 /**
510 * Are we at db installation step?
511 *
512 * @return boolean
513 */
514 public function isDbinstallStep()
515 {
516 return $this->_step === self::STEP_DB_INSTALL;
517 }
518
519 /**
520 * Set step to database upgrade
521 *
522 * @return void
523 */
524 public function atDbUpgradeStep()
525 {
526 $this->_step = self::STEP_DB_UPGRADE;
527 }
528
529 /**
530 * Are we at db upgrade step?
531 *
532 * @return boolean
533 */
534 public function isDbUpgradeStep()
535 {
536 return $this->_step === self::STEP_DB_UPGRADE;
537 }
538
539
540 /**
541 * Install/Update SQL scripts
542 *
543 * @param string $path Path to scripts (defaults to core scripts)
544 *
545 * @return array
546 */
547 public function getScripts($path = null)
548 {
549 if ($path === null) {
550 $path = GALETTE_ROOT . '/install';
551 }
552 $update_scripts = array();
553
554 if ($this->isUpgrade()) {
555 $update_scripts = self::getUpdateScripts(
556 $path,
557 $this->_db_type,
558 $this->_installed_version
559 );
560 } else {
561 $update_scripts['current'] = $this->_db_type . '.sql';
562 }
563
564 return $update_scripts;
565 }
566
567 /**
568 * List updates scripts from given path
569 *
570 * @param string $path Scripts path
571 * @param string $db_type Database type
572 * @param string $version Previous version, defaults to null
573 *
574 * @return array If a previous version is provided, update scripts
575 * file path from this one to the latest will be returned.
576 * If no previous version is provided, that will return all
577 * updates versions known.
578 */
579 public static function getUpdateScripts(
580 $path,
581 $db_type = 'mysql',
582 $version = null
583 ) {
584 $dh = opendir($path . '/scripts');
585 $php_update_scripts = array();
586 $sql_update_scripts = array();
587 if ($dh !== false) {
588 while (($file = readdir($dh)) !== false) {
589 if (preg_match("/upgrade-to-(.*).php/", $file, $ver)) {
590 if ($version === null) {
591 $php_update_scripts[$ver[1]] = $ver[1];
592 } else {
593 if ($version < $ver[1]) {
594 $php_update_scripts[$ver[1]] = $file;
595 }
596 }
597 }
598 if (
599 preg_match(
600 "/upgrade-to-(.*)-" . $db_type . ".sql/",
601 $file,
602 $ver
603 )
604 ) {
605 if ($version === null) {
606 $sql_update_scripts[$ver[1]] = $ver[1];
607 } else {
608 if ($version < $ver[1]) {
609 $sql_update_scripts[$ver[1]] = $file;
610 }
611 }
612 }
613 }
614 $update_scripts = array_merge($sql_update_scripts, $php_update_scripts);
615 closedir($dh);
616 ksort($update_scripts);
617 }
618 return $update_scripts;
619 }
620
621 /**
622 * Execute SQL scripts
623 *
624 * @param Galette\Core\Db $zdb Database instance
625 * @param string $spath Path to scripts
626 *
627 * @return boolean
628 */
629 public function executeScripts($zdb, $spath = null)
630 {
631 $queries_results = array();
632 $fatal_error = false;
633 $update_scripts = $this->getScripts($spath);
634 $this->_report = array();
635 $scripts_path = ($spath ?? GALETTE_ROOT . '/install') . '/scripts/';
636
637 foreach ($update_scripts as $key => $val) {
638 if (substr($val, -strlen('.sql')) === '.sql') {
639 //just a SQL script, run it
640 $script = fopen($scripts_path . $val, 'r');
641
642 if ($script === false) {
643 throw new \RuntimeException(
644 'Unable to read SQL script from ' . $scripts_path . $val
645 );
646 }
647
648 $sql_query = @fread(
649 $script,
650 @filesize($scripts_path . $val)
651 ) . "\n";
652
653 $sql_res = $this->executeSql($zdb, $sql_query);
654 if (!$sql_res) {
655 $fatal_error = true;
656 }
657 } else {
658 //we got an update class
659 include_once $scripts_path . $val;
660 $className = '\Galette\Updates\UpgradeTo' .
661 str_replace('.', '', $key);
662 $ret = array(
663 'message' => null,
664 'res' => false
665 );
666 try {
667 $updater = new $className();
668 if ($updater instanceof \Galette\Updater\AbstractUpdater) {
669 $updater->run($zdb, $this);
670 $ret = $updater->getReport();
671 $this->_report = array_merge($this->_report, $ret);
672 } else {
673 $fatal_error = true;
674 Analog::log(
675 'Update class does not extends AbstractUpdater!',
676 Analog::ERROR
677 );
678 }
679
680 $ret['message'] = str_replace(
681 '%version',
682 $key,
683 _T("%version script has been successfully executed :)")
684 );
685 $ret['res'] = true;
686 $this->_report[] = $ret;
687 } catch (\RuntimeException $e) {
688 Analog::log(
689 $e->getMessage(),
690 Analog::ERROR
691 );
692 $ret['message'] = str_replace(
693 '%version',
694 $key,
695 _T("Unable to run %version update script :(")
696 );
697 $fatal_error = true;
698 $this->_report[] = $ret;
699 }
700 }
701
702 Analog::log(
703 str_replace('%s', $key, 'Upgrade to %s complete'),
704 Analog::INFO
705 );
706 }
707
708 return !$fatal_error;
709 }
710
711 /**
712 * Executes SQL queries
713 *
714 * @param Db $zdb Database instance
715 * @param string $sql_query SQL instructions
716 *
717 * @return boolean;
718 */
719 public function executeSql($zdb, $sql_query)
720 {
721 $fatal_error = false;
722
723 // begin : copyright (2002) the phpbb group (support@phpbb.com)
724 // load in the sql parser
725 include_once GALETTE_ROOT . 'includes/sql_parse.php';
726
727 $sql_query = preg_replace('/galette_/', $this->_db_prefix, $sql_query);
728 $sql_query = remove_remarks($sql_query);
729
730 $sql_query = split_sql_file($sql_query, ';');
731
732 $zdb->connection->beginTransaction();
733
734 $sql_size = sizeof($sql_query);
735 for ($i = 0; $i < $sql_size; $i++) {
736 $query = trim($sql_query[$i]);
737 if ($query != '' && $query[0] != '-') {
738 //some output infos
739 $ret = array(
740 'message' => $query,
741 'res' => false
742 );
743
744 try {
745 $zdb->db->query(
746 $query,
747 Adapter::QUERY_MODE_EXECUTE
748 );
749 $ret['res'] = true;
750 } catch (Throwable $e) {
751 $log_lvl = Analog::WARNING;
752 //if error are on drop, DROP, rename or RENAME we can continue
753 $parts = explode(' ', $query, 1);
754 if (
755 (strcasecmp(trim($parts[0]), 'drop') != 0)
756 && (strcasecmp(trim($parts[0]), 'rename') != 0)
757 ) {
758 $log_lvl = Analog::ERROR;
759 $ret['debug'] = $e->getMessage();
760 $ret['query'] = $query;
761 $ret['res'] = false;
762 $fatal_error = true;
763 } else {
764 $ret['res'] = true;
765 }
766 Analog::log(
767 'Error executing query | ' . $e->getMessage(),
768 $log_lvl
769 );
770 }
771
772 $queries_results[] = $ret;
773 }
774 }
775
776 if ($fatal_error) {
777 $zdb->connection->rollBack();
778 } else {
779 try {
780 $zdb->connection->commit();
781 } catch (\PDOException $e) {
782 //to avoid php8/mysql autocommit issue
783 if ($zdb->isPostgres() || (!$zdb->isPostgres() && !str_contains($e->getMessage(), 'no active transaction'))) {
784 throw $e;
785 }
786 }
787 }
788
789 $this->_report = array_merge($this->_report, $queries_results);
790 return !$fatal_error;
791 }
792
793 /**
794 * Retrieve database installation report
795 *
796 * @return array
797 */
798 public function getDbInstallReport()
799 {
800 return $this->_report;
801 }
802
803 /**
804 * Reinitialize report array
805 *
806 * @return void
807 */
808 public function reinitReport()
809 {
810 $this->_report = array();
811 }
812
813 /**
814 * Set step to super admin information
815 *
816 * @return void
817 */
818 public function atAdminStep()
819 {
820 $this->_step = self::STEP_ADMIN;
821 }
822
823 /**
824 * Are we at super admin information step?
825 *
826 * @return boolean
827 */
828 public function isAdminStep()
829 {
830 return $this->_step === self::STEP_ADMIN;
831 }
832
833 /**
834 * Set super administrator information
835 *
836 * @param string $login Login
837 * @param string $pass Password
838 *
839 * @return void
840 */
841 public function setAdminInfos($login, $pass)
842 {
843 $this->_admin_login = $login;
844 $this->_admin_pass = password_hash($pass, PASSWORD_BCRYPT);
845 }
846
847 /**
848 * Retrieve super admin login
849 *
850 * @return string
851 */
852 public function getAdminLogin()
853 {
854 return $this->_admin_login;
855 }
856
857 /**
858 * Retrieve super admin password
859 *
860 * @return string
861 */
862 public function getAdminPass()
863 {
864 return $this->_admin_pass;
865 }
866
867 /**
868 * Set step to Galette initialization
869 *
870 * @return void
871 */
872 public function atGaletteInitStep()
873 {
874 $this->_step = self::STEP_GALETTE_INIT;
875 }
876
877 /**
878 * Are we at Galette initialization step?
879 *
880 * @return boolean
881 */
882 public function isGaletteInitStep()
883 {
884 return $this->_step === self::STEP_GALETTE_INIT;
885 }
886
887 /**
888 * Load existing config
889 *
890 * @param array $post_data Data posted
891 * @param array $error_detected Errors array
892 *
893 * @return void
894 */
895 public function loadExistingConfig($post_data, &$error_detected)
896 {
897 if (file_exists(GALETTE_CONFIG_PATH . 'config.inc.php')) {
898 $existing = $this->loadExistingConfigFile($post_data);
899
900 if ($existing['db_type'] !== null) {
901 $this->setDbType($existing['db_type'], $error_detected);
902 }
903
904 if (
905 $existing['db_host'] !== null
906 || $existing['db_user'] !== null
907 || $existing['db_name'] !== null
908 ) {
909 $this->setDsn(
910 $existing['db_host'],
911 $existing['db_port'],
912 $existing['db_name'],
913 $existing['db_user'],
914 null
915 );
916 }
917
918 if ($existing['prefix'] !== null) {
919 $this->setTablesPrefix(
920 $existing['prefix']
921 );
922 }
923 }
924 }
925
926 /**
927 * Load contents from existing config file
928 *
929 * @param array $post_data Data posted
930 * @param boolean $pass Retrieve password
931 *
932 * @return array
933 */
934 private function loadExistingConfigFile($post_data = array(), $pass = false)
935 {
936 $existing = array(
937 'db_type' => null,
938 'db_host' => null,
939 'db_port' => null,
940 'db_user' => null,
941 'db_name' => null,
942 'prefix' => null
943 );
944
945 if (file_exists(GALETTE_CONFIG_PATH . 'config.inc.php')) {
946 $conf = file_get_contents(GALETTE_CONFIG_PATH . 'config.inc.php');
947 if ($conf !== false) {
948 if (!isset($post_data['install_dbtype'])) {
949 $res = preg_match(
950 '/TYPE_DB["\'], ["\'](.*)["\']\);/',
951 $conf,
952 $matches
953 );
954 if (isset($matches[1])) {
955 $existing['db_type'] = $matches[1];
956 }
957 }
958 if (!isset($post_data['install_dbhost'])) {
959 $res = preg_match(
960 '/HOST_DB["\'], ["\'](.*)["\']\);/',
961 $conf,
962 $matches
963 );
964 if (isset($matches[1])) {
965 $existing['db_host'] = $matches[1];
966 }
967 }
968 if (!isset($post_data['install_dbport'])) {
969 $res = preg_match(
970 '/PORT_DB["\'], ["\'](.*)["\']\);/',
971 $conf,
972 $matches
973 );
974 if (isset($matches[1])) {
975 $existing['db_port'] = $matches[1];
976 }
977 }
978 if (!isset($post_data['install_dbuser'])) {
979 $res = preg_match(
980 '/USER_DB["\'], ["\'](.*)["\']\);/',
981 $conf,
982 $matches
983 );
984 if (isset($matches[1])) {
985 $existing['db_user'] = $matches[1];
986 }
987 }
988 if (!isset($post_data['install_dbname'])) {
989 $res = preg_match(
990 '/NAME_DB["\'], ["\'](.*)["\']\);/',
991 $conf,
992 $matches
993 );
994 if (isset($matches[1])) {
995 $existing['db_name'] = $matches[1];
996 }
997 }
998
999
1000 if (!isset($post_data['install_dbprefix'])) {
1001 $res = preg_match(
1002 '/PREFIX_DB["\'], ["\'](.*)["\']\);/',
1003 $conf,
1004 $matches
1005 );
1006 if (isset($matches[1])) {
1007 $existing['prefix'] = $matches[1];
1008 }
1009 }
1010
1011 if ($pass === true) {
1012 $res = preg_match(
1013 '/PWD_DB["\'], ["\'](.*)["\']\);/',
1014 $conf,
1015 $matches
1016 );
1017 if (isset($matches[1])) {
1018 $existing['pwd_db'] = $matches[1];
1019 }
1020 }
1021 }
1022 }
1023
1024 return $existing;
1025 }
1026
1027 /**
1028 * Write configuration file to disk
1029 *
1030 * @return boolean
1031 */
1032 public function writeConfFile()
1033 {
1034 $error = false;
1035 $ret = array(
1036 'message' => _T("Write configuration file"),
1037 'res' => false
1038 );
1039
1040 //if config file is already up-to-date, nothing to write
1041 $existing = $this->loadExistingConfigFile(array(), true);
1042
1043 if (
1044 isset($existing['db_type'])
1045 && $existing['db_type'] == $this->_db_type
1046 && isset($existing['db_host'])
1047 && $existing['db_host'] == $this->_db_host
1048 && isset($existing['db_port'])
1049 && $existing['db_port'] == $this->_db_port
1050 && isset($existing['db_user'])
1051 && $existing['db_user'] == $this->_db_user
1052 && isset($existing['pwd_db'])
1053 && $existing['pwd_db'] == $this->_db_pass
1054 && isset($existing['db_name'])
1055 && $existing['db_name'] == $this->_db_name
1056 && isset($existing['prefix'])
1057 && $existing['prefix'] == $this->_db_prefix
1058 ) {
1059 Analog::log(
1060 'Config file is already up-to-date, nothing to do.',
1061 Analog::INFO
1062 );
1063
1064 $this->_report[] = array(
1065 'message' => _T("Config file already exists and is up to date"),
1066 'res' => true
1067 );
1068 return true;
1069 }
1070
1071 $conffile = GALETTE_CONFIG_PATH . 'config.inc.php';
1072 if (
1073 is_writable(GALETTE_CONFIG_PATH)
1074 && (!file_exists($conffile) || file_exists($conffile) && is_writable($conffile))
1075 && $fd = @fopen($conffile, 'w')
1076 ) {
1077 $data = "<?php
1078 define('TYPE_DB', '" . $this->_db_type . "');
1079 define('HOST_DB', '" . $this->_db_host . "');
1080 define('PORT_DB', '" . $this->_db_port . "');
1081 define('USER_DB', '" . $this->_db_user . "');
1082 define('PWD_DB', '" . $this->_db_pass . "');
1083 define('NAME_DB', '" . $this->_db_name . "');
1084 define('PREFIX_DB', '" . $this->_db_prefix . "');
1085 ";
1086 fwrite($fd, $data);
1087 fclose($fd);
1088 $ret['res'] = true;
1089 Analog::log('Configuration file written on disk', Analog::INFO);
1090 } else {
1091 $str = str_replace(
1092 '%path',
1093 $conffile,
1094 _T("Unable to create configuration file (%path)")
1095 );
1096 Analog::log($str, Analog::WARNING);
1097 $ret['error'] = $str;
1098 $error = true;
1099 }
1100 $this->_report[] = $ret;
1101 return !$error;
1102 }
1103
1104 /**
1105 * Initialize Galette relevant objects
1106 *
1107 * @param I18n $i18n I18n
1108 * @param Db $zdb Database instance
1109 * @param Login $login Loged in instance
1110 *
1111 * @return boolean
1112 */
1113 public function initObjects(I18n $i18n, Db $zdb, Login $login)
1114 {
1115 if ($this->isInstall()) {
1116 $preferences = new Preferences($zdb, false);
1117 $ct = new \Galette\Entity\ContributionsTypes($zdb);
1118 $status = new \Galette\Entity\Status($zdb);
1119 include_once '../includes/fields_defs/members_fields.php';
1120 include_once '../includes/fields_defs/members_fields_cats.php';
1121 $fc = new \Galette\Entity\FieldsConfig(
1122 $zdb,
1123 \Galette\Entity\Adherent::TABLE,
1124 $members_fields,
1125 $members_fields_cats,
1126 true
1127 );
1128
1129 global $login;
1130 $login = new \Galette\Core\Login($zdb, $i18n);
1131 //$fc = new \Galette\Entity\FieldsCategories();
1132 $texts = new \Galette\Entity\Texts($preferences);
1133 $titles = new \Galette\Repository\Titles();
1134
1135 $models = new \Galette\Repository\PdfModels($zdb, $preferences, $login);
1136
1137 $this->_error = false;
1138
1139 //Install preferences
1140 $res = $preferences->installInit(
1141 $i18n->getID(),
1142 $this->getAdminLogin(),
1143 $this->getAdminPass()
1144 );
1145 $this->proceedReport(_T("Preferences"), $res);
1146
1147 //Install contributions types
1148 $res = $ct->installInit();
1149 $this->proceedReport(_T("Contributions types"), $res);
1150
1151 //Install statuses
1152 $res = $status->installInit();
1153 $this->proceedReport(_T("Status"), $res);
1154
1155 //Install fields configuration and categories
1156 $res = $fc->installInit();
1157 $this->proceedReport(_T("Fields config and categories"), $res);
1158
1159 //Install texts
1160 $res = $texts->installInit(false);
1161 $this->proceedReport(_T("Mails texts"), $res);
1162
1163 //Install titles
1164 $res = $titles->installInit($zdb);
1165 $this->proceedReport(_T("Titles"), $res);
1166
1167 //Install PDF models
1168 $res = $models->installInit(false);
1169 $this->proceedReport(_T("PDF Models"), $res);
1170
1171 return !$this->_error;
1172 } elseif ($this->isUpgrade()) {
1173 $preferences = new Preferences($zdb);
1174 $preferences->store();
1175 $this->proceedReport(_T("Update preferences"), true);
1176
1177 $models = new \Galette\Repository\PdfModels($zdb, $preferences, new Login($zdb, $i18n));
1178 $res = $models->installInit(true);
1179 $this->proceedReport(_T("Update models"), true);
1180
1181 $texts = new \Galette\Entity\Texts($preferences);
1182 $res = $texts->installInit(true);
1183 $this->proceedReport(_T("Mails texts"), true);
1184
1185 return true;
1186 }
1187 }
1188
1189 /**
1190 * Proceed installation report for each Entity/Repository
1191 *
1192 * @param string $msg Report message title
1193 * @param mixed $res Initialialization result
1194 *
1195 * @return void
1196 */
1197 private function proceedReport($msg, $res)
1198 {
1199 $ret = array(
1200 'message' => $msg,
1201 'res' => false
1202 );
1203
1204 if ($res instanceof \Exception) {
1205 $ret['debug'] = $res->getMessage();
1206 $this->_error = true;
1207 } else {
1208 $ret['res'] = true;
1209 }
1210 $this->_report[] = $ret;
1211 }
1212 /**
1213 * Retrieve galette initialization report
1214 *
1215 * @return array
1216 */
1217 public function getInitializationReport()
1218 {
1219 return $this->_report;
1220 }
1221
1222 /**
1223 * Set step to database installation
1224 *
1225 * @return void
1226 */
1227 public function atEndStep()
1228 {
1229 $this->_step = self::STEP_END;
1230 }
1231
1232 /**
1233 * Are we at end step?
1234 *
1235 * @return boolean
1236 */
1237 public function isEndStep()
1238 {
1239 return $this->_step === self::STEP_END;
1240 }
1241
1242 /**
1243 * Set installed version if we're upgrading
1244 *
1245 * @param string $version Installed version
1246 *
1247 * @return void
1248 */
1249 public function setInstalledVersion($version)
1250 {
1251 $this->_installed_version = $version;
1252 }
1253
1254 /**
1255 * Current Galette installed version, according to database
1256 *
1257 * @param Db $zdb Database instance
1258 *
1259 * @return string
1260 */
1261 public function getCurrentVersion($zdb)
1262 {
1263 try {
1264 $db_ver = $zdb->getDbVersion(true);
1265 if (isset($this->versions_mapper[$db_ver])) {
1266 return $this->versions_mapper[$db_ver];
1267 } else {
1268 return $db_ver;
1269 }
1270 } catch (\LogicException $e) {
1271 return false;
1272 }
1273 }
1274
1275 /**
1276 * Check if step is passed
1277 *
1278 * @param int $step Step
1279 *
1280 * @return boolean
1281 */
1282 public function isStepPassed($step)
1283 {
1284 return $this->_step > $step;
1285 }
1286 }