Commit | Line | Data |
---|---|---|
36d0127b MW |
1 | <?php |
2 | namespace wcf\system\package\plugin; | |
b68f0af4 | 3 | use wcf\data\package\Package; |
eeae8f3b | 4 | use wcf\data\package\PackageList; |
ec1b1daf | 5 | use wcf\system\exception\SystemException; |
870b0938 | 6 | use wcf\system\package\PackageArchive; |
ec1b1daf | 7 | use wcf\system\package\PackageInstallationSQLParser; |
2bc9f31d | 8 | use wcf\system\WCF; |
36d0127b MW |
9 | |
10 | /** | |
a17de04e | 11 | * Executes the delivered sql file. |
9f959ced | 12 | * |
849f69b7 | 13 | * @author Alexander Ebert |
ca4ba303 | 14 | * @copyright 2001-2014 WoltLab GmbH |
36d0127b MW |
15 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
16 | * @package com.woltlab.wcf | |
17 | * @subpackage system.package.plugin | |
9f959ced | 18 | * @category Community Framework |
36d0127b MW |
19 | */ |
20 | class SQLPackageInstallationPlugin extends AbstractPackageInstallationPlugin { | |
21 | /** | |
0ad90fc3 | 22 | * @see \wcf\system\package\plugin\AbstractPackageInstallationPlugin::$tableName |
9f959ced | 23 | */ |
36d0127b MW |
24 | public $tableName = 'package_installation_sql_log'; |
25 | ||
26 | /** | |
0ad90fc3 | 27 | * @see \wcf\system\package\plugin\IPackageInstallationPlugin::install() |
36d0127b MW |
28 | */ |
29 | public function install() { | |
30 | parent::install(); | |
9f959ced | 31 | |
36d0127b MW |
32 | // extract sql file from archive |
33 | if ($queries = $this->getSQL($this->instruction['value'])) { | |
34 | $package = $this->installation->getPackage(); | |
eeae8f3b MS |
35 | |
36 | // replace app1_ with app{WCF_N}_ in the table names for | |
37 | // all applications | |
38 | $packageList = new PackageList(); | |
39 | $packageList->getConditionBuilder()->add('package.isApplication = ?', array(1)); | |
40 | $packageList->readObjects(); | |
41 | foreach ($packageList as $package) { | |
42 | $abbreviation = Package::getAbbreviation($package->package); | |
36d0127b | 43 | |
838e315b | 44 | $queries = str_replace($abbreviation.'1_', $abbreviation.WCF_N.'_', $queries); |
36d0127b MW |
45 | } |
46 | ||
36d0127b | 47 | // check queries |
bee17d66 | 48 | $parser = new PackageInstallationSQLParser($queries, $this->installation->getPackage(), $this->installation->getAction()); |
36d0127b | 49 | $conflicts = $parser->test(); |
840ba5e8 | 50 | if (!empty($conflicts) && (isset($conflicts['CREATE TABLE']) || isset($conflicts['DROP TABLE']))) { |
5efa06c9 MS |
51 | $unknownCreateTable = isset($conflicts['CREATE TABLE']) ? $conflicts['CREATE TABLE'] : array(); |
52 | $unknownDropTable = isset($conflicts['DROP TABLE']) ? $conflicts['DROP TABLE'] : array(); | |
ffdf6f14 | 53 | |
5efa06c9 MS |
54 | $errorMessage = "Can't"; |
55 | if (!empty($unknownDropTable)) { | |
56 | $errorMessage .= " drop unknown table"; | |
57 | if (count($unknownDropTable) > 1) { | |
58 | $errorMessage .= "s"; | |
59 | } | |
60 | $errorMessage .= " '".implode("', '", $unknownDropTable)."'"; | |
61 | } | |
62 | if (!empty($unknownCreateTable)) { | |
63 | if (!empty($unknownDropTable)) { | |
64 | $errorMessage .= " and can't"; | |
65 | } | |
66 | ||
67 | $errorMessage .= " overwrite unknown table"; | |
68 | if (count($unknownCreateTable) > 1) { | |
69 | $errorMessage .= "s"; | |
70 | } | |
71 | $errorMessage .= " '".implode("', '", $unknownCreateTable)."'"; | |
72 | } | |
73 | ||
74 | throw new SystemException($errorMessage); | |
36d0127b MW |
75 | } |
76 | ||
77 | // execute queries | |
78 | $parser->execute(); | |
79 | ||
80 | // log changes | |
81 | $parser->log(); | |
82 | } | |
83 | } | |
84 | ||
85 | /** | |
0ad90fc3 | 86 | * @see \wcf\system\package\plugin\IPackageInstallationPlugin::uninstall() |
36d0127b MW |
87 | */ |
88 | public function uninstall() { | |
89 | // get logged sql tables/columns | |
b6ae7d04 MW |
90 | $sql = "SELECT * |
91 | FROM wcf".WCF_N."_package_installation_sql_log | |
92 | WHERE packageID = ? | |
39bea7dd | 93 | ORDER BY sqlIndex DESC, sqlColumn DESC"; |
36d0127b MW |
94 | $statement = WCF::getDB()->prepareStatement($sql); |
95 | $statement->execute(array($this->installation->getPackageID())); | |
96 | $entries = array(); | |
97 | while ($row = $statement->fetchArray()) { | |
98 | $entries[] = $row; | |
99 | } | |
100 | ||
101 | // get all tablenames from database | |
102 | $existingTableNames = WCF::getDB()->getEditor()->getTablenames(); | |
103 | ||
104 | // delete or alter tables | |
105 | foreach ($entries as $entry) { | |
106 | // don't alter table if it should be dropped | |
b6ae7d04 | 107 | if (!empty($entry['sqlColumn'])/* || !empty($entry['sqlIndex'])*/) { |
36d0127b MW |
108 | $isDropped = false; |
109 | foreach ($entries as $entry2) { | |
110 | if ($entry['sqlTable'] == $entry2['sqlTable'] && empty($entry2['sqlColumn']) && empty($entry2['sqlIndex'])) { | |
111 | $isDropped = true; | |
112 | } | |
113 | } | |
114 | if ($isDropped) continue; | |
115 | } | |
116 | // drop table | |
117 | if (!empty($entry['sqlTable']) && empty($entry['sqlColumn']) && empty($entry['sqlIndex'])) { | |
118 | WCF::getDB()->getEditor()->dropTable($entry['sqlTable']); | |
119 | } | |
120 | // drop column | |
121 | else if (in_array($entry['sqlTable'], $existingTableNames) && !empty($entry['sqlColumn'])) { | |
122 | WCF::getDB()->getEditor()->dropColumn($entry['sqlTable'], $entry['sqlColumn']); | |
123 | } | |
124 | // drop index | |
125 | else if (in_array($entry['sqlTable'], $existingTableNames) && !empty($entry['sqlIndex'])) { | |
b6ae7d04 MW |
126 | if (substr($entry['sqlIndex'], -3) == '_fk') { |
127 | WCF::getDB()->getEditor()->dropForeignKey($entry['sqlTable'], $entry['sqlIndex']); | |
128 | } | |
129 | else { | |
130 | WCF::getDB()->getEditor()->dropIndex($entry['sqlTable'], $entry['sqlIndex']); | |
131 | } | |
36d0127b MW |
132 | } |
133 | } | |
134 | // delete from log table | |
135 | parent::uninstall(); | |
136 | } | |
137 | ||
138 | /** | |
139 | * Extracts and returns the sql file. | |
140 | * If the specified sql file was not found, an error message is thrown. | |
9f959ced | 141 | * |
36d0127b | 142 | * @param string $filename |
39bea7dd | 143 | * @return string |
36d0127b MW |
144 | */ |
145 | protected function getSQL($filename) { | |
146 | // search sql files in package archive | |
147 | if (($fileindex = $this->installation->getArchive()->getTar()->getIndexByFilename($filename)) === false) { | |
4fe0b42b | 148 | throw new SystemException("SQL file '".$filename."' not found."); |
36d0127b | 149 | } |
a17de04e | 150 | |
36d0127b MW |
151 | // extract sql file to string |
152 | return $this->installation->getArchive()->getTar()->extractToString($fileindex); | |
39bea7dd | 153 | } |
870b0938 AE |
154 | |
155 | /** | |
156 | * @see \wcf\system\package\plugin\IPackageInstallationPlugin::isValid() | |
157 | */ | |
158 | public static function isValid(PackageArchive $archive, $instruction) { | |
159 | if (preg_match('~\.sql$~', $instruction)) { | |
160 | // check if file actually exists | |
161 | try { | |
162 | if ($archive->getTar()->getIndexByFilename($instruction) === false) { | |
163 | return false; | |
164 | } | |
165 | } | |
166 | catch (\SystemException $e) { | |
167 | return false; | |
168 | } | |
169 | ||
170 | return true; | |
171 | } | |
172 | ||
173 | return false; | |
174 | } | |
36d0127b | 175 | } |