<parent>wcf.acp.menu.link.management</parent>
<showorder>1</showorder>
</acpmenuitem>
+ <acpmenuitem name="wcf.acp.menu.link.systemCheck">
+ <controller>wcf\acp\page\SystemCheckPage</controller>
+ <parent>wcf.acp.menu.link.maintenance</parent>
+ <permissions>admin.configuration.package.canInstallPackage</permissions>
+ <showorder>1</showorder>
+ </acpmenuitem>
<acpmenuitem name="wcf.acp.menu.link.cronjob.list">
<controller>wcf\acp\page\CronjobListPage</controller>
<parent>wcf.acp.menu.link.maintenance</parent>
<permissions>admin.management.canManageCronjob</permissions>
- <showorder>1</showorder>
+ <showorder>2</showorder>
</acpmenuitem>
<acpmenuitem name="wcf.acp.menu.link.cronjob.add">
<controller>wcf\acp\form\CronjobAddForm</controller>
<parent>wcf.acp.menu.link.cronjob.list</parent>
<permissions>admin.management.canManageCronjob</permissions>
- <showorder>2</showorder>
+ <showorder>3</showorder>
<icon>fa-plus</icon>
</acpmenuitem>
<acpmenuitem name="wcf.acp.menu.link.maintenance.cache">
--- /dev/null
+{include file='header'}
+
+<header class="contentHeader">
+ <h1 class="contentTitle">{lang}wcf.acp.systemCheck{/lang}</h1>
+</header>
+
+{event name='userNotice'}
+
+{capture assign='statusOk'}<span class="icon icon16 fa-check green"></span>{/capture}
+{capture assign='statusSufficient'}<span class="icon icon16 fa-exclamation-triangle orange"></span>{/capture}
+{capture assign='statusInsufficient'}<span class="icon icon16 fa-exclamation-triangle red"></span>{/capture}
+
+<section class="section">
+ <h2 class="sectionTitle">{lang}wcf.acp.systemCheck.result{/lang}</h2>
+
+ <dl{if !$results[status][php]} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.php{/lang}</dt>
+ <dd>
+ {if $results[status][php]}
+ {if $results[php][version][result] === 'sufficient'}
+ {@$statusSufficient} {lang}wcf.acp.systemCheck.sufficient{/lang}
+ {else}
+ {@$statusOk} {lang}wcf.acp.systemCheck.pass{/lang}
+ {/if}
+ {else}
+ {@$statusInsufficient} {lang}wcf.acp.systemCheck.insufficient{/lang}
+ {/if}
+ </dd>
+ </dl>
+
+ <dl{if !$results[status][mysql]} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.mysql{/lang}</dt>
+ <dd>
+ {if $results[status][mysql]}
+ {@$statusOk} {lang}wcf.acp.systemCheck.pass{/lang}
+ {else}
+ {@$statusInsufficient} {lang}wcf.acp.systemCheck.insufficient{/lang}
+ {/if}
+ </dd>
+ </dl>
+
+ <dl{if !$results[status][directories]} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.directories{/lang}</dt>
+ <dd>
+ {if $results[status][directories]}
+ {@$statusOk} {lang}wcf.acp.systemCheck.pass{/lang}
+ {else}
+ {@$statusInsufficient} {lang}wcf.acp.systemCheck.insufficient{/lang}
+ {/if}
+ </dd>
+ </dl>
+</section>
+
+<section class="section">
+ <h2 class="sectionTitle">{lang}wcf.acp.systemCheck.php{/lang}</h2>
+
+ <dl{if $results[php][version][result] === 'unsupported'} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.php.version{/lang}</dt>
+ <dd>
+ {if $results[php][version][result] === 'recommended'}
+ {@$statusOk}
+ {elseif $results[php][version][result] === 'sufficient'}
+ {@$statusSufficient}
+ {else}
+ {@$statusInsufficient}
+ {/if}
+ {$results[php][version][value]}
+ <small>{lang}wcf.acp.systemCheck.php.version.description{/lang}</small>
+ </dd>
+ </dl>
+
+ <dl{if !$results[php][extension]|empty} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.php.extension{/lang}</dt>
+ <dd>
+ {if $results[php][extension]|empty}
+ {@$statusOk} {lang}wcf.acp.systemCheck.pass{/lang}
+ {else}
+ <ul class="nativeList">
+ {foreach from=$results[php][extension] item=extension}
+ <li>{@$statusInsufficient} <kbd>{$extension}</kbd></li>
+ {/foreach}
+ </ul>
+ {/if}
+ <small>{lang}wcf.acp.systemCheck.php.extension.description{/lang}</small>
+ </dd>
+ </dl>
+
+ <dl{if !$results[php][memoryLimit][result]} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.php.memoryLimit{/lang}</dt>
+ <dd>
+ {if $results[php][memoryLimit][result]}{@$statusOk}{else}{@$statusInsufficient}{/if} {$results[php][memoryLimit][value]}
+ <small>{lang}wcf.acp.systemCheck.php.memoryLimit.description{/lang}</small>
+ </dd>
+ </dl>
+
+ <dl{if !$results[php][sha256]} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.php.sha256{/lang}</dt>
+ <dd>
+ {if $results[php][sha256]}
+ {@$statusOk} {lang}wcf.acp.systemCheck.pass{/lang}
+ {else}
+ {@$statusInsufficient} {lang}wcf.acp.systemCheck.notSupported{/lang}
+ {/if}
+ <small>{lang}wcf.acp.systemCheck.php.sha256.description{/lang}</small>
+ </dd>
+ </dl>
+</section>
+
+<section class="section">
+ <h2 class="sectionTitle">{lang}wcf.acp.systemCheck.mysql{/lang}</h2>
+
+ <dl{if !$results[mysql][result]} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.mysql.version{/lang}</dt>
+ <dd>
+ {if $results[mysql][result]}{@$statusOk}{else}{@$statusInsufficient}{/if}
+ {if $results[mysql][mariadb]}MariaDB{else}MySQL{/if} {$results[mysql][version]}
+ <small>{lang}wcf.acp.systemCheck.mysql.version.description{/lang}</small>
+ </dd>
+ </dl>
+
+ <dl{if !$results[mysql][innodb]} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.mysql.innodb{/lang}</dt>
+ <dd>
+ {if $results[mysql][innodb]}
+ {@$statusOk} {lang}wcf.acp.systemCheck.pass{/lang}
+ {else}
+ {@$statusInsufficient} {lang}wcf.acp.systemCheck.notSupported{/lang}
+ {/if}
+ <small>{lang}wcf.acp.systemCheck.mysql.innodb.description{/lang}</small>
+ </dd>
+ </dl>
+</section>
+
+<section class="section">
+ <h2 class="sectionTitle">{lang}wcf.acp.systemCheck.directories{/lang}</h2>
+
+ <dl{if !$results[directories]|empty} class="formError"{/if}>
+ <dt>{lang}wcf.acp.systemCheck.directories.writable{/lang}</dt>
+ <dd>
+ {if $results[directories]|empty}
+ {@$statusOk} {lang}wcf.acp.systemCheck.pass{/lang}
+ {else}
+ <ul class="nativeList">
+ {foreach from=$results[directories] item=directory}
+ <li>{@$statusInsufficient} <kbd>{$directory}</kbd></li>
+ {/foreach}
+ </ul>
+ {/if}
+ <small>{lang}wcf.acp.systemCheck.directories.writable.description{/lang}</small>
+ </dd>
+ </dl>
+</section>
+
+{include file='footer'}
--- /dev/null
+<?php
+namespace wcf\acp\page;
+use wcf\data\application\Application;
+use wcf\page\AbstractPage;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+
+/**
+ * Shows the style list page.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Acp\Page
+ * @since 5.2
+ */
+class SystemCheckPage extends AbstractPage {
+ /**
+ * @inheritDoc
+ */
+ public $activeMenuItem = 'wcf.acp.menu.link.systemCheck';
+
+ /**
+ * @inheritDoc
+ */
+ public $neededPermissions = ['admin.configuration.package.canInstallPackage'];
+
+ /**
+ * A list of directories that need to be writable at all times, grouped by their application
+ * identifier. Only the directory itself is checked, unless the path ends with `/*`.
+ * @var string[][]
+ */
+ public $directories = [
+ 'wcf' => [
+ '/',
+ '/acp/style',
+ '/acp/templates/compiled',
+ '/attachments',
+ '/cache',
+ '/images/*',
+ '/language',
+ '/log',
+ '/media_files/*',
+ '/sitemaps',
+ '/style',
+ '/templates/compiled',
+ '/tmp',
+ ],
+ ];
+
+ public $mysqlVersions = [
+ 'mysql' => '5.5.35',
+ 'mariadb' => [
+ // MariaDB 5.5.47+ or 10.0.22+ are required
+ // https://jira.mariadb.org/browse/MDEV-8756
+ '5' => '5.5.47',
+ '10' => '10.0.22',
+ ],
+ ];
+
+ public $phpExtensions = [
+ 'mbstring',
+ 'libxml',
+ 'dom',
+ 'zlib',
+ 'pdo',
+ 'pdo_mysql',
+ 'json',
+ 'pcre',
+ 'gd',
+ 'hash',
+ ];
+
+ public $phpMemoryLimit = 128;
+
+ public $phpVersions = [
+ 'minimum' => '7.0.22',
+ 'sufficient' => ['7.0'],
+ 'recommended' => ['7.1', '7.2', '7.3'],
+ ];
+
+ public $results = [
+ 'directories' => [],
+ 'mysql' => [
+ 'innodb' => false,
+ 'mariadb' => false,
+ 'result' => false,
+ 'version' => '0.0.0',
+ ],
+ 'php' => [
+ 'extension' => [],
+ 'memoryLimit' => [
+ 'required' => '0',
+ 'result' => false,
+ 'value' => '0',
+ ],
+ 'sha256' => false,
+ 'version' => [
+ 'result' => 'unsupported',
+ 'value' => '0.0.0',
+ ],
+ ],
+ 'status' => [
+ 'directories' => false,
+ 'mysql' => false,
+ 'php' => false,
+ ],
+ ];
+
+ /**
+ * @inheritDoc
+ */
+ public function readData() {
+ parent::readData();
+
+ if (IMAGE_ADAPTER_TYPE === 'imagick' && !in_array('imagick', $this->phpExtensions)) {
+ $this->phpExtensions[] = 'imagick';
+ }
+
+ $this->validateMysql();
+ $this->validatePhpExtensions();
+ $this->validatePhpMemoryLimit();
+ $this->validatePhpVersion();
+ $this->validateWritableDirectories();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ WCF::getTPL()->assign([
+ 'mysqlVersions' => $this->mysqlVersions,
+ 'phpExtensions' => $this->phpExtensions,
+ 'phpMemoryLimit' => $this->phpMemoryLimit,
+ 'phpVersions' => $this->phpVersions,
+ 'results' => $this->results,
+ ]);
+ }
+
+ protected function validateMysql() {
+ // check sql version
+ $sqlVersion = WCF::getDB()->getVersion();
+ $compareSQLVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $sqlVersion);
+ // Do not use the "raw" version, it usually contains a lot of noise.
+ $this->results['mysql']['version'] = $compareSQLVersion;
+ if (stripos($sqlVersion, 'MariaDB') !== false) {
+ $this->results['mysql']['mariadb'] = true;
+
+ // MariaDB has some legacy version that use the major version '5'.
+ if ($compareSQLVersion[0] === '5') {
+ $this->results['mysql']['result'] = (version_compare($compareSQLVersion, $this->mysqlVersions['mariadb']['5']) >= 0);
+ }
+ else {
+ $this->results['mysql']['result'] = (version_compare($compareSQLVersion, $this->mysqlVersions['mariadb']['10']) >= 0);
+ }
+ }
+ else if (version_compare($compareSQLVersion, $this->mysqlVersions['mysql']) >= 0) {
+ $this->results['mysql']['result'] = true;
+ }
+
+ // check innodb support
+ $sql = "SHOW ENGINES";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
+ while ($row = $statement->fetchArray()) {
+ if ($row['Engine'] == 'InnoDB' && in_array($row['Support'], ['DEFAULT', 'YES'])) {
+ $this->results['mysql']['innodb'] = true;
+ break;
+ }
+ }
+
+ if ($this->results['mysql']['result'] && $this->results['mysql']['innodb']) {
+ $this->results['status']['mysql'] = true;
+ }
+ }
+
+ protected function validatePhpExtensions() {
+ foreach ($this->phpExtensions as $phpExtension) {
+ $result = extension_loaded($phpExtension);
+ if (!$result) {
+ $this->results['php']['extension'][] = $phpExtension;
+ }
+ }
+
+ if (extension_loaded('hash')) {
+ $this->results['php']['sha256'] = in_array('sha256', hash_algos());
+ }
+
+ $this->results['status']['php'] = empty($this->results['php']['extension']) && $this->results['php']['sha256'];
+ }
+
+ protected function validatePhpMemoryLimit() {
+ $this->results['php']['memoryLimit']['required'] = $this->phpMemoryLimit . 'M';
+
+ $memoryLimit = ini_get('memory_limit');
+
+ // Memory is not limited through PHP.
+ if ($memoryLimit == -1) {
+ $this->results['php']['memoryLimit']['value'] = '∞';
+ $this->results['php']['memoryLimit']['result'] = true;
+ }
+ else {
+ // Completely numeric, PHP assumes this to be a value in bytes.
+ if (is_numeric($memoryLimit)) {
+ $memoryLimit = $memoryLimit / 1024 / 1024;
+
+ $this->results['php']['memoryLimit']['value'] = $memoryLimit . 'M';
+ $this->results['php']['memoryLimit']['result'] = ($memoryLimit >= $this->phpMemoryLimit);
+ }
+ else {
+ // PHP supports the 'K', 'M' and 'G' shorthand notations.
+ if (preg_match('~^(\d+)([KMG])$~', $memoryLimit, $matches)) {
+ switch ($matches[2]) {
+ case 'K':
+ $memoryLimit = $matches[1] * 1024;
+
+ $this->results['php']['memoryLimit']['value'] = $memoryLimit . 'M';
+ $this->results['php']['memoryLimit']['result'] = ($memoryLimit >= $this->phpMemoryLimit);
+ break;
+
+ case 'M':
+ $this->results['php']['memoryLimit']['value'] = $memoryLimit;
+ $this->results['php']['memoryLimit']['result'] = ($matches[1] >= $this->phpMemoryLimit);
+ break;
+
+ case 'G':
+ $this->results['php']['memoryLimit']['value'] = $memoryLimit;
+ $this->results['php']['memoryLimit']['result'] = ($matches[1] * 1024 >= $this->phpMemoryLimit);
+ break;
+
+ default:
+ $this->results['php']['memoryLimit']['value'] = $memoryLimit;
+ $this->results['php']['memoryLimit']['result'] = false;
+ return;
+ }
+ }
+ }
+ }
+
+ $this->results['status']['php'] = $this->results['status']['php'] && $this->results['php']['memoryLimit']['result'];
+ }
+
+ protected function validatePhpVersion() {
+ $phpVersion = phpversion();
+ $comparePhpVersion = preg_replace('/^(\d+\.\d+\.\d+).*$/', '\\1', $phpVersion);
+ // Do not use the "raw" version, it usually contains a lot of noise.
+ $this->results['php']['version']['value'] = $comparePhpVersion;
+ if (version_compare($comparePhpVersion, $this->phpVersions['minimum']) >= 0) {
+ $majorMinor = preg_replace('~^(\d+\.\d+).*$~', '\\1', $phpVersion);
+ foreach (['recommended', 'sufficient'] as $type) {
+ foreach ($this->phpVersions[$type] as $version) {
+ if ($majorMinor === $version) {
+ $this->results['php']['version']['result'] = $type;
+ break 2;
+ }
+ }
+ }
+ }
+ else {
+ $this->results['php']['version']['result'] = 'unsupported';
+ }
+
+ $this->results['status']['php'] = $this->results['status']['php'] && ($this->results['php']['version']['result'] !== 'unsupported');
+ }
+
+ protected function validateWritableDirectories() {
+ foreach ($this->directories as $abbreviation => $directories) {
+ $basePath = Application::getDirectory($abbreviation);
+ foreach ($directories as $directory) {
+ $recursive = false;
+ if (preg_match('~(.*)/\*$~', $directory, $matches)) {
+ $recursive = true;
+ $directory = $matches[1];
+ }
+
+ $path = $basePath . FileUtil::removeLeadingSlash(FileUtil::addTrailingSlash($directory));
+ if ($this->checkDirectory($path) && $recursive) {
+ $rdi = new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS);
+ $it = new \RecursiveIteratorIterator($rdi, \RecursiveIteratorIterator::SELF_FIRST);
+ /** @var \SplFileInfo $item */
+ foreach ($it as $item) {
+ if ($item->isDir()) {
+ $this->makeDirectoryWritable($item->getPathname());
+ }
+ }
+ }
+ }
+ }
+
+ $this->results['status']['directories'] = empty($this->results['directories']);
+ }
+
+ protected function checkDirectory($path) {
+ if (!$this->createDirectoryIfNotExists($path)) {
+ $this->results['directories'][] = FileUtil::unifyDirSeparator($path);
+ return false;
+ }
+
+ return $this->makeDirectoryWritable($path);
+ }
+
+ protected function createDirectoryIfNotExists($path) {
+ if (!file_exists($path) && !FileUtil::makePath($path)) {
+ // FileUtil::makePath() returns false if either the directory cannot be created
+ // or if it cannot be made writable.
+ if (!file_exists($path)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected function makeDirectoryWritable($path) {
+ try {
+ FileUtil::makeWritable($path);
+ }
+ catch (SystemException $e) {
+ $this->results['directories'][] = FileUtil::unifyDirSeparator($path);
+ return false;
+ }
+
+ return true;
+ }
+}
use wcf\system\WCF;
/**
- * Parses the [user] bbcode tag.
+ * Parses the [group] bbcode tag.
*
* @author Alexander Ebert
* @copyright 2001-2019 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package WoltLabSuite\Core\System\Bbcode
- * @since 5.0
+ * @since 5.2
*/
class GroupBBCode extends AbstractBBCode {
/**
<item name="wcf.acp.menu.link.reactionType.add"><![CDATA[Reaktions-Typ hinzufügen]]></item>
<item name="wcf.acp.menu.link.reactionType.edit"><![CDATA[Reaktions-Typ bearbeiten]]></item>
<item name="wcf.acp.menu.link.language.item.add"><![CDATA[Text hinzufügen]]></item>
+ <item name="wcf.acp.menu.link.systemCheck"><![CDATA[Systemüberprüfung]]></item>
</category>
<category name="wcf.acp.modificationLog">
<item name="wcf.acp.modificationLog.list"><![CDATA[Globales Veränderungsprotokoll]]></item>
<item name="wcf.acp.stat.category.com.woltlab.wcf.user"><![CDATA[Benutzer-Daten]]></item>
<item name="wcf.acp.stat.noData"><![CDATA[Es liegen keine Daten für den ausgewählten Zeitraum vor.]]></item>
</category>
+ <category name="wcf.acp.systemCheck">
+ <item name="wcf.acp.systemCheck"><![CDATA[Systemüberprüfung]]></item>
+ <item name="wcf.acp.systemCheck.result"><![CDATA[Resultat]]></item>
+ <item name="wcf.acp.systemCheck.pass"><![CDATA[Test bestanden]]></item>
+ <item name="wcf.acp.systemCheck.sufficient"><![CDATA[Ausreichend]]></item>
+ <item name="wcf.acp.systemCheck.insufficient"><![CDATA[Anforderungen nicht erfüllt]]></item>
+ <item name="wcf.acp.systemCheck.notSupported"><![CDATA[Nicht unterstützt]]></item>
+ <item name="wcf.acp.systemCheck.php"><![CDATA[PHP]]></item>
+ <item name="wcf.acp.systemCheck.mysql"><![CDATA[MySQL]]></item>
+ <item name="wcf.acp.systemCheck.directories"><![CDATA[Dateisystem]]></item>
+ <item name="wcf.acp.systemCheck.php.version"><![CDATA[Version]]></item>
+ <item name="wcf.acp.systemCheck.php.version.description"><![CDATA[Es wird mindestens PHP {$phpVersions[minimum]} benötigt, empfohlen werden die folgenden Versionsreihen von PHP: {implode from=$phpVersions[recommended] item=$recommended}{$recommended}{/implode}.]]></item>
+ <item name="wcf.acp.systemCheck.mysql.version"><![CDATA[MySQL]]></item>
+ <item name="wcf.acp.systemCheck.mysql.version.description"><![CDATA[Es wird mindestens MySQL {$mysqlVersions[mysql]} bzw. MariaDB {$mysqlVersions[mariadb][5]} oder MariaDB {$mysqlVersions[mariadb][10]} benötigt, grundsätzlich wird der Einsatz neuerer Version ausdrücklich empfohlen.]]></item>
+ <item name="wcf.acp.systemCheck.php.extension"><![CDATA[Erweiterungen]]></item>
+ <item name="wcf.acp.systemCheck.php.extension.description"><![CDATA[Die offiziellen Erweiterungen von PHP stellen zusätzliche Funktionen bereit, die für den Betrieb der Software notwendig sind.]]></item>
+ <item name="wcf.acp.systemCheck.php.memoryLimit"><![CDATA[Verfügbarer Arbeitsspeicher („memory_limit“)]]></item>
+ <item name="wcf.acp.systemCheck.php.memoryLimit.description"><![CDATA[Einige Prozesse benötigen in Spitzenzeiten eine große Menge Arbeitsspeicher, für den einwandfreien Betrieb werden mindestens {$phpMemoryLimit} MB benötigt.]]></item>
+ <item name="wcf.acp.systemCheck.php.sha256"><![CDATA[Unterstützung für SHA-256]]></item>
+ <item name="wcf.acp.systemCheck.php.sha256.description"><![CDATA[Die kryptographische Funktion SHA-256 wird für den sicheren Betrieb der Software benötigt.]]></item>
+ <item name="wcf.acp.systemCheck.mysql.innodb"><![CDATA[InnoDB verfügbar]]></item>
+ <item name="wcf.acp.systemCheck.mysql.innodb.description"><![CDATA[InnoDB (XtraDB unter MariaDB) ist eine transaktionale Storage-Engine von MySQL und wird zwingend für den Betrieb benötigt. Dies ist eine Standardfunktion von MySQL.]]></item>
+ <item name="wcf.acp.systemCheck.directories.writable"><![CDATA[Beschreibbare Verzeichnisse]]></item>
+ <item name="wcf.acp.systemCheck.directories.writable.description"><![CDATA[Einige Verzeichnisse werden zur Laufzeit durch die Software beschrieben, der PHP-Benutzer muss Schreibrechte haben.]]></item>
+ </category>
<category name="wcf.acp.updateServer">
<item name="wcf.acp.updateServer.add"><![CDATA[Server hinzufügen]]></item>
<item name="wcf.acp.updateServer.delete.sure"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du{else}Wollen Sie{/if} den Server <span class="confirmationObject">{$updateServer->serverURL}</span> wirklich löschen?]]></item>
<item name="wcf.acp.menu.link.reactionType.add"><![CDATA[Add Reaction Type]]></item>
<item name="wcf.acp.menu.link.reactionType.edit"><![CDATA[Edit Reaction Type]]></item>
<item name="wcf.acp.menu.link.language.item.add"><![CDATA[Add Phrase]]></item>
+ <item name="wcf.acp.menu.link.systemCheck"><![CDATA[System Check]]></item>
</category>
<category name="wcf.acp.modificationLog">
<item name="wcf.acp.modificationLog.list"><![CDATA[Global Modification Log]]></item>
<item name="wcf.acp.stat.category.com.woltlab.wcf.user"><![CDATA[User Data]]></item>
<item name="wcf.acp.stat.noData"><![CDATA[There is no data available for the set period.]]></item>
</category>
+ <category name="wcf.acp.systemCheck">
+ <item name="wcf.acp.systemCheck"><![CDATA[System Check]]></item>
+ <item name="wcf.acp.systemCheck.result"><![CDATA[Result]]></item>
+ <item name="wcf.acp.systemCheck.pass"><![CDATA[Test passed]]></item>
+ <item name="wcf.acp.systemCheck.sufficient"><![CDATA[Sufficient]]></item>
+ <item name="wcf.acp.systemCheck.insufficient"><![CDATA[Requirements are not met]]></item>
+ <item name="wcf.acp.systemCheck.notSupported"><![CDATA[Not supported]]></item>
+ <item name="wcf.acp.systemCheck.php"><![CDATA[PHP]]></item>
+ <item name="wcf.acp.systemCheck.mysql"><![CDATA[MySQL]]></item>
+ <item name="wcf.acp.systemCheck.directories"><![CDATA[Filesystem]]></item>
+ <item name="wcf.acp.systemCheck.php.version"><![CDATA[Version]]></item>
+ <item name="wcf.acp.systemCheck.php.version.description"><![CDATA[PHP {$phpVersions[minimum]} or newer is required, the following PHP series are strongly recommended: {implode from=$phpVersions[recommended] item=$recommended}{$recommended}{/implode}.]]></item>
+ <item name="wcf.acp.systemCheck.mysql.version"><![CDATA[MySQL]]></item>
+ <item name="wcf.acp.systemCheck.mysql.version.description"><![CDATA[MySQL {$mysqlVersions[mysql]} or MariaDB {$mysqlVersions[mariadb][5]} or MariaDB {$mysqlVersions[mariadb][10]} are required at minimum, but it’s strongly recommended to always use the latest available version.]]></item>
+ <item name="wcf.acp.systemCheck.php.extension"><![CDATA[Extensions]]></item>
+ <item name="wcf.acp.systemCheck.php.extension.description"><![CDATA[The official PHP extensions provide additional capabilities and features that are required for the software to work.]]></item>
+ <item name="wcf.acp.systemCheck.php.memoryLimit"><![CDATA[Available Memory (“memory_limit”)]]></item>
+ <item name="wcf.acp.systemCheck.php.memoryLimit.description"><![CDATA[Processes may require large amounts of memory at peak, requiring a limit of at least {$phpMemoryLimit} MB.]]></item>
+ <item name="wcf.acp.systemCheck.php.sha256"><![CDATA[Support for SHA-256]]></item>
+ <item name="wcf.acp.systemCheck.php.sha256.description"><![CDATA[The cryptographic function SHA-256 is required for a safe and secure operation of the software.]]></item>
+ <item name="wcf.acp.systemCheck.mysql.innodb"><![CDATA[InnoDB available]]></item>
+ <item name="wcf.acp.systemCheck.mysql.innodb.description"><![CDATA[InnoDB (XtraDB when using MariaDB) is a transaction storage engine for MySQL and is required for the operation of the software. This is a built-in feature of MySQL.]]></item>
+ <item name="wcf.acp.systemCheck.directories.writable"><![CDATA[Writable Directories]]></item>
+ <item name="wcf.acp.systemCheck.directories.writable.description"><![CDATA[Some directories are being written to during the normal operation. The user that runs the PHP process must have write access.]]></item>
+ </category>
<category name="wcf.acp.updateServer">
<item name="wcf.acp.updateServer.add"><![CDATA[Add Server]]></item>
<item name="wcf.acp.updateServer.delete.sure"><![CDATA[Do you really want to delete the server <span class="confirmationObject">{$updateServer->serverURL}</span>?]]></item>