Add GUI support for language package installation plugin
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / devtools / project / DevtoolsProject.class.php
CommitLineData
d7424422
AE
1<?php
2namespace wcf\data\devtools\project;
d7424422
AE
3use wcf\data\package\installation\plugin\PackageInstallationPluginList;
4use wcf\data\package\Package;
5use wcf\data\package\PackageCache;
e7de794a 6use wcf\data\DatabaseObject;
d7424422
AE
7use wcf\system\devtools\package\DevtoolsPackageArchive;
8use wcf\system\devtools\pip\DevtoolsPip;
9use wcf\system\package\validation\PackageValidationException;
52da8ead 10use wcf\system\Regex;
d7424422 11use wcf\system\WCF;
52da8ead 12use wcf\util\DirectoryUtil;
d7424422
AE
13
14/**
15 * Represents a devtools project.
16 *
17 * @author Alexander Ebert
c839bd49 18 * @copyright 2001-2018 WoltLab GmbH
d7424422
AE
19 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
20 * @package WoltLabSuite\Core\Devtools\Project
21 * @since 3.1
22 *
23 * @property-read integer $projectID unique id of the project
24 * @property-read string $name internal name for display inside the ACP
25 * @property-read string $path file system path
26 */
27class DevtoolsProject extends DatabaseObject {
28 /**
29 * @var boolean
30 */
31 protected $isCore;
32
33 /**
34 * @var Package
35 */
36 protected $package;
37
38 /**
39 * @var DevtoolsPackageArchive
40 */
41 protected $packageArchive;
42
d4955651
AE
43 /**
44 * Returns a list of decorated PIPs.
45 *
46 * @return DevtoolsPip[]
47 */
d7424422
AE
48 public function getPips() {
49 $pipList = new PackageInstallationPluginList();
50 $pipList->sqlOrderBy = 'pluginName';
51 $pipList->readObjects();
52
53 $pips = [];
54 foreach ($pipList as $pip) {
532a045a
MS
55 $pip = new DevtoolsPip($pip);
56 $pip->setProject($this);
57
58 $pips[] = $pip;
d7424422
AE
59 }
60
61 return $pips;
62 }
63
d4955651
AE
64 /**
65 * Validates the repository and returns the first error message, or
66 * an empty string on success.
67 *
68 * @return string
69 */
d7424422
AE
70 public function validate() {
71 $errorType = self::validatePath($this->path);
72 if ($errorType !== '') {
73 return WCF::getLanguage()->get('wcf.acp.devtools.project.path.error.' . $errorType);
74 }
75
76 return $this->validatePackageXml();
77 }
78
d4955651
AE
79 /**
80 * Returns true if this project appears to be `WoltLab Suite Core`.
81 *
82 * @return boolean
83 */
d7424422
AE
84 public function isCore() {
85 if ($this->isCore === null) {
86 $this->isCore = self::pathIsCore($this->path);
87 }
88
89 return $this->isCore;
90 }
91
d4955651
AE
92 /**
93 * Validates the package.xml and checks if the package is already installed.
94 *
95 * @return string
96 */
d7424422
AE
97 public function validatePackageXml() {
98 $packageXml = $this->path . ($this->isCore() ? 'com.woltlab.wcf/' : '') . 'package.xml';
99 $this->packageArchive = new DevtoolsPackageArchive($packageXml);
100 try {
101 $this->packageArchive->openArchive();
102 }
103 catch (PackageValidationException $e) {
104 return $e->getErrorMessage();
105 }
106
107 $this->package = PackageCache::getInstance()->getPackageByIdentifier($this->packageArchive->getPackageInfo('name'));
108 if ($this->package === null) {
109 return WCF::getLanguage()->getDynamicVariable('wcf.acp.devtools.project.path.error.notInstalled', [
110 'package' => $this->packageArchive->getPackageInfo('name')
111 ]);
112 }
113
d2b357c6
AE
114 $normalizeVersion = function($version) {
115 return preg_replace('~^(\d+)\.(\d+)\..*$~', '\\1.\\2', $version);
116 };
117
118 if ($normalizeVersion($this->packageArchive->getPackageInfo('version')) !== $normalizeVersion($this->package->packageVersion)) {
119 return WCF::getLanguage()->getDynamicVariable('wcf.acp.devtools.project.path.error.versionMismatch', [
120 'version' => $this->packageArchive->getPackageInfo('version'),
121 'packageVersion' => $this->package->packageVersion
122 ]);
123 }
124
125 if (!$this->isCore()) {
68e8cb7f
TD
126 $compatibleVersions = $this->packageArchive->getCompatibleVersions();
127 if (empty($compatibleVersions)) {
128 return WCF::getLanguage()->getDynamicVariable('wcf.acp.devtools.project.path.error.missingCompatibility');
129 }
130 $isCompatible = $isOlderVersion = false;
131 foreach ($compatibleVersions as $version) {
132 if (WCF::isSupportedApiVersion($version)) {
133 $isCompatible = true;
d2b357c6
AE
134 break;
135 }
68e8cb7f
TD
136 else if ($version < WSC_API_VERSION) {
137 $isOlderVersion = true;
138 }
d2b357c6
AE
139 }
140
68e8cb7f
TD
141 if (!$isCompatible) {
142 return WCF::getLanguage()->getDynamicVariable('wcf.acp.devtools.project.path.error.unsupportedCompatibility', ['isOlderVersion' => $isOlderVersion]);
d2b357c6
AE
143 }
144 }
145
d7424422
AE
146 return '';
147 }
148
149 /**
150 * @return Package
151 */
152 public function getPackage() {
153 return $this->package;
154 }
155
156 /**
157 * @return DevtoolsPackageArchive
158 */
159 public function getPackageArchive() {
160 return $this->packageArchive;
161 }
162
52da8ead
MS
163 /**
164 * Returns the absolute paths of the language files.
165 *
166 * @return string[]
167 */
168 public function getLanguageFiles() {
169 $languageDirectory = $this->path . ($this->isCore() ? 'wcfsetup/install/lang/' : 'language/');
170
171 return array_values(DirectoryUtil::getInstance($languageDirectory)->getFiles(SORT_ASC, Regex::compile('\w+\.xml')));
172 }
173
d7424422
AE
174 /**
175 * Validates the provided path and returns an error code
176 * if the path does not exist (`notFound`) or if there is
177 * no package.xml (`packageXml`).
178 *
179 * @param string $path
180 * @return string
181 */
182 public static function validatePath($path) {
183 if (!is_dir($path)) {
184 return 'notFound';
185 }
186 else if (!file_exists($path . 'package.xml')) {
187 // check if this is `com.woltlab.wcf`
188 if (!self::pathIsCore($path)) {
189 return 'packageXml';
190 }
191 }
192
193 return '';
194 }
195
d4955651
AE
196 /**
197 * Returns true if the path appears to point to `WoltLab Suite Core`.
198 *
199 * @param string $path
200 * @return boolean
201 */
d7424422
AE
202 public static function pathIsCore($path) {
203 return (is_dir($path . 'com.woltlab.wcf') && file_exists($path . 'com.woltlab.wcf/package.xml'));
204 }
205}