2 namespace wcf\system\form\builder\field\devtools\project;
3 use wcf\data\application\Application;
4 use wcf\data\package\installation\plugin\PackageInstallationPlugin;
5 use wcf\data\package\installation\plugin\PackageInstallationPluginList;
6 use wcf\data\package\Package;
7 use wcf\system\application\ApplicationHandler;
8 use wcf\system\form\builder\field\AbstractFormField;
9 use wcf\system\form\builder\field\TDefaultIdFormField;
10 use wcf\system\form\builder\field\validation\FormFieldValidationError;
13 * Form field implementation for the instructions of a devtools project.
15 * @author Matthias Schmidt
16 * @copyright 2001-2018 WoltLab GmbH
17 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
18 * @package WoltLabSuite\Core\System\Form\Builder\Field\Devtools\Project
21 class DevtoolsProjectInstructionsFormField extends AbstractFormField {
22 use TDefaultIdFormField;
25 * list of available applications
26 * @var null|Application[]
28 protected $applications;
31 * list of available package installation plugins
32 * @var null|PackageInstallationPlugin[]
34 protected $packageInstallationPlugins = null;
39 protected $templateName = '__devtoolsProjectInstructionsFormField';
44 protected $__value = [];
47 * names of package installation plugins that support the `application`
51 protected static $applicationPips = [
59 * Returns the applications for which file-based package installation plugins
62 * @return Application[]
64 public function getApplications() {
65 if ($this->applications === null) {
66 $this->applications = [];
67 foreach (ApplicationHandler::getInstance()->getApplications() as $application) {
68 $this->applications[$application->getAbbreviation()] = $application;
71 uasort($this->applications, function(Application $app1, Application $app2) {
72 return $app1->getAbbreviation() <=> $app2->getAbbreviation();
76 return $this->applications;
82 public function getHtmlVariables() {
84 'apps' => $this->getApplications(),
85 'packageInstallationPlugins' => $this->getPackageInstallationPlugins()
90 * Returns the package installation plugins that can be used for instructions.
92 * @return PackageInstallationPlugin[]
94 public function getPackageInstallationPlugins() {
95 if ($this->packageInstallationPlugins === null) {
96 $packageInstallationPluginList = new PackageInstallationPluginList();
97 $packageInstallationPluginList->sqlOrderBy = 'pluginName ASC';
98 $packageInstallationPluginList->readObjects();
100 foreach ($packageInstallationPluginList as $packageInstallationPlugin) {
101 $this->packageInstallationPlugins[$packageInstallationPlugin->pluginName] = $packageInstallationPlugin;
105 return $this->packageInstallationPlugins;
111 public function readValue() {
112 if ($this->getDocument()->hasRequestData($this->getPrefixedId()) && is_array($this->getDocument()->getRequestData($this->getPrefixedId()))) {
113 $this->__value = $this->getDocument()->getRequestData($this->getPrefixedId());
123 public function validate() {
124 // everything is already validated by JavaScript thus we skip
125 // reporting specific errors and simply remove manipulated values
126 $this->value(array_filter($this->getValue(), function($instructions) {
127 if (!is_array($instructions)) {
131 // ensure that all relevant elements are present
132 if (!isset($instructions['type'])) {
135 if (!isset($instructions['instructions'])) {
136 $instructions['instructions'] = [];
138 if (!is_array($instructions['instructions'])) {
142 if ($instructions['type'] !== 'install' && $instructions['type'] !== 'update') {
146 if ($instructions['type'] === 'update') {
147 if (!isset($instructions['fromVersion'])) {
151 if (strpos($instructions['fromVersion'], '*') !== false) {
152 if (!Package::isValidVersion(str_replace('*', '0', $instructions['fromVersion']))) {
156 else if (!Package::isValidVersion($instructions['fromVersion'])) {
161 foreach ($instructions['instructions'] as $instruction) {
162 if (!isset($instruction['pip']) || !isset($this->getPackageInstallationPlugins()[$instruction['pip']])) {
166 if (!empty($instruction['application'])) {
167 if (!isset($this->getApplications()[$instruction['application']])) {
171 if (!in_array($instruction['pip'], static::$applicationPips)) {
176 $instruction['runStandalone'] = $instruction['runStandalone'] ?? 0;
177 $instruction['value'] = $instruction['value'] ?? '';
183 // the only thing left to validate is to ensure that there are
184 // installation instructions
185 $hasInstallInstructions = false;
186 foreach ($this->getValue() as $instructions) {
187 if ($instructions['type'] === 'install') {
188 $hasInstallInstructions = true;
193 if (!$hasInstallInstructions) {
194 $this->addValidationError(
195 new FormFieldValidationError(
196 'noInstallationInstructions',
197 'wcf.acp.devtools.project.instructions.error.noInstallationInstructions'
206 protected static function getDefaultId() {
207 return 'instructions';