From 837d789a095285a3f0ee57dd84c3d268a3f2b51b Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sat, 1 Jun 2024 13:26:47 +0200 Subject: [PATCH] refactor: migrated setup and update to Twig --- phpmyfaq/.htaccess | 3 + phpmyfaq/assets/src/configuration/update.js | 8 +- .../admin/configuration/upgrade.twig | 258 ++++----- phpmyfaq/assets/templates/setup/base.twig | 49 ++ phpmyfaq/assets/templates/setup/index.twig | 335 ++++++++++++ phpmyfaq/assets/templates/setup/install.twig | 50 ++ phpmyfaq/assets/templates/setup/update.twig | 2 +- .../assets/templates/setup/update/step2.twig | 4 +- phpmyfaq/setup/index.php | 479 +---------------- phpmyfaq/setup/setup.php | 489 ++++++++++++++++++ phpmyfaq/setup/update.php | 72 --- phpmyfaq/src/admin-routes.php | 2 +- phpmyfaq/src/api-routes.php | 2 +- .../Controller/AbstractController.php | 2 + .../{Setup => Api}/SetupController.php | 3 +- .../Controller/Frontend/SetupController.php | 131 +++++ phpmyfaq/src/phpMyFAQ/Language.php | 36 +- phpmyfaq/src/phpMyFAQ/Setup/Installer.php | 51 +- phpmyfaq/src/phpMyFAQ/System.php | 12 +- .../src/phpMyFAQ/Template/TwigWrapper.php | 5 +- phpmyfaq/src/public-routes.php | 35 ++ 21 files changed, 1306 insertions(+), 722 deletions(-) create mode 100644 phpmyfaq/assets/templates/setup/base.twig create mode 100644 phpmyfaq/assets/templates/setup/install.twig create mode 100644 phpmyfaq/setup/setup.php delete mode 100644 phpmyfaq/setup/update.php rename phpmyfaq/src/phpMyFAQ/Controller/{Setup => Api}/SetupController.php (98%) create mode 100644 phpmyfaq/src/phpMyFAQ/Controller/Frontend/SetupController.php create mode 100644 phpmyfaq/src/public-routes.php diff --git a/phpmyfaq/.htaccess b/phpmyfaq/.htaccess index 1d0d7cd5d9..69908b7098 100644 --- a/phpmyfaq/.htaccess +++ b/phpmyfaq/.htaccess @@ -96,6 +96,9 @@ Header set Access-Control-Allow-Headers "Content-Type, Authorization" # User pages RewriteRule ^user/(ucp|bookmarks|request-removal|logout|register) index.php?action=$1 [L,QSA] + # Setup and update pages + RewriteRule ^setup/(.*) setup/index.php [L,QSA] + # Administration API RewriteRule ^admin/api/(.*) admin/api/index.php [L,QSA] diff --git a/phpmyfaq/assets/src/configuration/update.js b/phpmyfaq/assets/src/configuration/update.js index 9d330af518..eb88e525c0 100644 --- a/phpmyfaq/assets/src/configuration/update.js +++ b/phpmyfaq/assets/src/configuration/update.js @@ -20,13 +20,13 @@ export const handleUpdateNextStepButton = () => { if (nextStepButton && nextStep) { nextStepButton.addEventListener('click', (event) => { event.preventDefault(); - window.location.replace(`./update.php?step=${nextStep.value}`); + window.location.replace(`./update?step=${nextStep.value}`); }); } }; export const handleUpdateInformation = async () => { - if (window.location.href.endsWith('update.php')) { + if (window.location.href.endsWith('/update')) { const installedVersion = document.getElementById('phpmyfaq-update-installed-version'); try { @@ -67,7 +67,7 @@ export const handleUpdateInformation = async () => { }; export const handleConfigBackup = async () => { - if (window.location.href.endsWith('update.php?step=2')) { + if (window.location.href.endsWith('/update?step=2')) { const installedVersion = document.getElementById('phpmyfaq-update-installed-version'); try { @@ -96,7 +96,7 @@ export const handleConfigBackup = async () => { }; export const handleDatabaseUpdate = async () => { - if (window.location.href.endsWith('update.php?step=3')) { + if (window.location.href.endsWith('/update?step=3')) { const installedVersion = document.getElementById('phpmyfaq-update-installed-version'); try { diff --git a/phpmyfaq/assets/templates/admin/configuration/upgrade.twig b/phpmyfaq/assets/templates/admin/configuration/upgrade.twig index 7345bef430..63933d3b8d 100644 --- a/phpmyfaq/assets/templates/admin/configuration/upgrade.twig +++ b/phpmyfaq/assets/templates/admin/configuration/upgrade.twig @@ -1,145 +1,151 @@
-

- - {{ adminHeaderUpgrade }} -

+

+ + {{ adminHeaderUpgrade }} +

-
+
-
-
-
- {{ headerCheckHealth }} -
-

- {{ msgHealthCheck }} -

- -
- - -
-
+
+
+
+ {{ headerCheckHealth }} +
+

+ {{ msgHealthCheck }} +

+ +
+ +
+
+
-
-
-
- {{ headerCheckUpdates }} -
-

- {{ msgUpdateCheck }} -

- -
- - -
-
+
+
+
+ {{ headerCheckUpdates }} +
+

+ {{ msgUpdateCheck }} +

+ +
+ +
+
+
-
-
-
- {{ headerDownloadPackage }} -
-

- {{ msgDownloadPackage }} -

- - {% if isOnNightlies %} -

- {{ alertNightlyBuild }} -

-
- - -
- {% endif %} -
-
+
+
+
+ {{ headerDownloadPackage }} +
+

+ {{ msgDownloadPackage }} +

+ + {% if isOnNightlies %} +

+ {{ alertNightlyBuild }} +

+
+ + +
+ {% endif %} +
+
-
-
-
- {{ headerExtractPackage }} -
-

- {{ msgExtractPackage }} -

- -
-
- - -
-
-
+
+
+
+ {{ headerExtractPackage }} +
+

+ {{ msgExtractPackage }} +

+ +
+
+ + +
+
+
-
-
-
- 5. Install downloaded package -
-

- This extracts the downloaded package into your filesystem. -

- -
-
-
- -
-
-
    -
  1. Backup of current installation
  2. -
  3. Installation of new files
  4. -
-
-
-
-
- 0% -
-
-
-
- 0% -
-
-
-
+
+
+
+ 5. Install downloaded package +
+

+ This extracts the downloaded package into your filesystem. +

+ +
+
+
+ +
+
+
    +
  1. Backup of current installation
  2. +
  3. Installation of new files
  4. +
+
+
+
+
+ 0% +
+
+
+
+ 0%
+
+
+
+
+
+
+
+

+ You can still use the manual update process if you prefer. +

-
-
- {{ msgLastCheckDate }} - {{ dateLastChecked | date('Y-m-d H:i:s') }} -
-
- {{ msgLastVersionAvailable }} - n/a -
-
- {{ msgReleaseEnvironment }} {{ releaseEnvironment }} -
+
+ {{ msgLastCheckDate }} + {{ dateLastChecked | date('Y-m-d H:i:s') }} +
+
+ {{ msgLastVersionAvailable }} + n/a +
+
+ {{ msgReleaseEnvironment }} + {{ releaseEnvironment }}
+
diff --git a/phpmyfaq/assets/templates/setup/base.twig b/phpmyfaq/assets/templates/setup/base.twig new file mode 100644 index 0000000000..97d0c08daf --- /dev/null +++ b/phpmyfaq/assets/templates/setup/base.twig @@ -0,0 +1,49 @@ + + + + + phpMyFAQ {{ newVersion }} {{ setupType }} + + + + + + + + + + + +{% block content %}{% endblock %} + + + + + + diff --git a/phpmyfaq/assets/templates/setup/index.twig b/phpmyfaq/assets/templates/setup/index.twig index e69de29bb2..28b92becfa 100644 --- a/phpmyfaq/assets/templates/setup/index.twig +++ b/phpmyfaq/assets/templates/setup/index.twig @@ -0,0 +1,335 @@ +{% extends 'setup/base.twig' %} + +{% block content %} +
+
+ +
+
+ +
+

phpMyFAQ {{ newVersion }}

+
+

+ Did you already read our + documentation + carefully before starting the phpMyFAQ setup? +

+
+
+ +
+ Database Setup + LDAP Setup + Elasticsearch Setup + Admin user account +
+ + {% for hint in nonCriticalSettings %} + + {% endfor %} + + {% if checkBasicError %} + + {% else %} + +
+ +

Step 1/4: Database setup

+ +
+ +
+ + Please select your preferred database type. +
+
+ +
+
+ +
+ + + Please enter the host or path to the socket of your database server. + +
+
+
+ +
+ + Please enter the port your database server. +
+
+
+ +
+ + Please enter your database user. +
+
+
+ +
+
+ + + + +
+ Please enter your database password. +
+
+
+ +
+ + Please enter your existing database name. +
+
+
+ +
+
+ +
+ + + Please enter the full path to your SQLite datafile which should be outside your document root. + +
+
+
+ +
+ +
+ + + Please enter a table prefix here if you want to install more phpMyFAQ installations in one + database. + +
+
+
+ +
+

Step 2/4: LDAP setup

+ {% if isLdapEnabled %} +
+
+ + +
+
+
+ +
+ + Please enter the host of your LDAP server. +
+
+
+ +
+ + Please enter the port of your LDAP server. +
+
+
+ +
+ + Please enter your specified RDN username. +
+
+
+ +
+ + Please enter your LDAP password. +
+
+
+ +
+ + + Please enter your distinguished name, e.g. 'cn=John Doe,ou=Accounts,o=My Company,c=US'. + +
+
+

+ + You can add additional LDAP configurations later in the admin configuration panel. +

+ {% else %} +

+ + LDAP support is not enabled in your PHP installation. +

+ {% endif %} +
+ +
+

Step 3/4: Elasticsearch setup

+ {% if isElasticsearchEnabled %} +
+
+ + +
+
+
+ +
+
+ + + Add another Elasticsearch Host + +
+ + Please enter the host (domain or IP) with port number of your Elasticsearch server. + +
+
+
+ +
+ + Please enter your Elasticsearch index name. +
+
+ {% else %} +

+ + cURL and OpenSSL support are not enabled in your PHP installation. +

+ {% endif %} +
+ +
+

Step 4/4: Admin user setup

+ +
+ +
+ + Please select your default language. +
+
+ +
+ +
+ + + Complexity of rights and permissions. + +
+
+
+ +
+ + Please enter your real name. +
+
+
+ +
+ + Please enter your email address. +
+
+
+ +
+ + Please enter your login name. +
+
+
+ +
+
+ + + + +
+ Please enter your password with at least 8 characters. +
+
+
+ +
+
+ + + + +
+ Please retype your password. +
+
+
+
+

+ + After clicking the "Submit" button, all necessary tables will be created and filled with your data. + Depending on your system, this may take some time. Stay tuned. +

+
+
+
+ + + + + + {% endif %} +
+
+
+
+{% endblock %} diff --git a/phpmyfaq/assets/templates/setup/install.twig b/phpmyfaq/assets/templates/setup/install.twig new file mode 100644 index 0000000000..be6b69a653 --- /dev/null +++ b/phpmyfaq/assets/templates/setup/install.twig @@ -0,0 +1,50 @@ +{% extends 'setup/base.twig' %} + +{% block content %} +
+
+ +
+ +
+

phpMyFAQ {{ newVersion }}

+
+

+ Did you already read our + documentation + carefully before starting the phpMyFAQ setup? +

+
+
+ + {% if checkBasicError %} + + {% elseif installationError %} + + {% else %} +
+
+

Installation

+ + {{ feedbackIndicator }} + +

+ Wow, looks like the installation worked like a charm. This is pretty cool, isn't it? :-) +

+ +

+ You can visit your version of phpMyFAQ or login into your + admin section. +

+
+
+ {% endif %} + +
+
+
+{% endblock %} diff --git a/phpmyfaq/assets/templates/setup/update.twig b/phpmyfaq/assets/templates/setup/update.twig index 345a45bbc2..bd8407d36b 100644 --- a/phpmyfaq/assets/templates/setup/update.twig +++ b/phpmyfaq/assets/templates/setup/update.twig @@ -54,7 +54,7 @@ Database updates
- {{ include('setup/update/step' ~ currentStep ~ '.twig') }} + {{ include('./setup/update/step' ~ currentStep ~ '.twig') }}
diff --git a/phpmyfaq/assets/templates/setup/update/step2.twig b/phpmyfaq/assets/templates/setup/update/step2.twig index 34d0aac70b..8bd21c5e65 100644 --- a/phpmyfaq/assets/templates/setup/update/step2.twig +++ b/phpmyfaq/assets/templates/setup/update/step2.twig @@ -22,8 +22,8 @@
-
diff --git a/phpmyfaq/setup/index.php b/phpmyfaq/setup/index.php index 0ce5c69c38..10c679263d 100644 --- a/phpmyfaq/setup/index.php +++ b/phpmyfaq/setup/index.php @@ -2,6 +2,7 @@ /** * The main phpMyFAQ Setup. + * * This script checks the complete environment, writes the database connection * parameters into the file config/database.php and the configuration into the database. * This Source Code Form is subject to the terms of the Mozilla Public License, @@ -10,480 +11,24 @@ * * @package phpMyFAQ * @author Thorsten Rinne - * @author Tom Rochester - * @author Johannes Schlüter - * @author Uwe Pries - * @author Matteo Scaramuccia - * @author Florian Anderiasch - * @copyright 2002-2024 phpMyFAQ Team + * @copyright 2024 phpMyFAQ Team * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 * @link https://www.phpmyfaq.de - * @since 2002-08-20 + * @since 2024-05-31 */ -use Composer\Autoload\ClassLoader; -use phpMyFAQ\Component\Alert; -use phpMyFAQ\Core\Exception; -use phpMyFAQ\Language\LanguageCodes; -use phpMyFAQ\Setup\Installer; -use phpMyFAQ\Strings; -use phpMyFAQ\System; -use phpMyFAQ\Translation; - -define('PMF_ROOT_DIR', dirname(__FILE__, 2)); -const PMF_SRC_DIR = PMF_ROOT_DIR . '/src'; -const IS_VALID_PHPMYFAQ = null; - -if (version_compare(PHP_VERSION, '8.1.0') < 0) { - die('Sorry, but you need PHP 8.1.0 or later!'); -} - -set_time_limit(0); - -if (!defined('DEBUG')) { - define('DEBUG', true); -} - -if (DEBUG) { - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); - error_reporting(E_ALL | E_STRICT); -} - -session_name('phpmyfaq-setup'); -session_start(); - -require PMF_ROOT_DIR . '/src/libs/autoload.php'; -require PMF_ROOT_DIR . '/src/constants.php'; -require PMF_ROOT_DIR . '/content/core/config/constants.php'; -require PMF_ROOT_DIR . '/content/core/config/constants_elasticsearch.php'; +use phpMyFAQ\Application; +use phpMyFAQ\Configuration; -$loader = new ClassLoader(); -$loader->add('phpMyFAQ', PMF_SRC_DIR); -$loader->register(); -?> - - - - - phpMyFAQ <?= System::getVersion() ?> Setup - - - - - - - - +require '../src/Bootstrap.php'; - +$faqConfig = Configuration::getConfigurationInstance(); -
-
+$routes = include PMF_SRC_DIR . '/public-routes.php'; -
-
- -
-

phpMyFAQ

-
-

- Did you already read our - documentation - carefully before starting the phpMyFAQ setup? -

-
-
- -
- Database Setup - LDAP Setup - Elasticsearch Setup - Admin user account -
- -setLanguagesDir(PMF_LANGUAGE_DIR) - ->setDefaultLanguage('en') - ->setCurrentLanguage('en') - ->setMultiByteLanguage(); -} catch (Exception $e) { - echo 'Error: ' . $e->getMessage(); -} - -$system = new System(); -$installer = new Installer($system); - -try { - $installer->checkBasicStuff(); -} catch (Exception $e) { - echo Alert::danger('ad_entryins_fail', $e->getMessage()); - System::renderFooter(); -} - -$installer->checkFilesystemPermissions(); - -// not yet POSTed -if (!isset($_POST['sql_server']) && !isset($_POST['sql_user']) && !isset($_POST['sql_db'])) { - $installer->checkNoncriticalSettings() - ?> - -
- -

Step 1/4: Database setup

- -
- -
- - Please select your preferred database type. -
-
- -
-
- -
- - - Please enter the host or path to the socket of your database server. - -
-
-
- -
- - Please enter the port your database server. -
-
-
- -
- - Please enter your database user. -
-
-
- -
-
- - - - -
- Please enter your database password. -
-
-
- -
- - Please enter your existing database name. -
-
-
- -
-
- -
- - - Please enter the full path to your SQLite datafile which should be outside your document root. - -
-
-
- -
- -
- - - Please enter a table prefix here if you want to install more phpMyFAQ installations in one - database. - -
-
-
- - -
-

Step 2/4: LDAP setup

- -
-
- - -
-
-
- -
- - Please enter the host of your LDAP server. -
-
-
- -
- - Please enter the port of your LDAP server. -
-
-
- -
- - Please enter your specified RDN username. -
-
-
- -
- - Please enter your LDAP password. -
-
-
- -
- - - Please enter your distinguished name, e.g. 'cn=John Doe,ou=Accounts,o=My Company,c=US'. - -
-
-

- You can add additional LDAP configurations later in the admin configuration panel. -

- -
- - - -
-

Step 3/4: Elasticsearch setup

- -
-
- - -
-
-
- -
-
- - - Add another Elasticsearch Host - -
- - Please enter the host (domain or IP) with port number of your Elasticsearch server. - -
-
-
- -
- - Please enter your Elasticsearch index name. -
-
- -
- - - -
-

Step 4/4: Admin user setup

- -
- -
- - Please select your default language. -
-
- -
- -
- - - Complexity of rights and permissions. - -
-
-
- -
- - Please enter your real name. -
-
-
- -
- - Please enter your email address. -
-
-
- -
- - Please enter your login name. -
-
-
- -
-
- - - - -
- Please enter your password with at least 8 characters. -
-
-
- -
-
- - - - -
- Please retype your password. -
-
-
-
-

- - After clicking the "Submit" button, all necessary tables will be created and filled with your data. - Depending on your system, this may take some time. Stay tuned. -

-
-
-
- - - - - -
-
- - -
-
-

Installation

- startInstall(); - } catch (Exception $e) { - echo $e->getMessage(); - } - ?> -

- Wow, looks like the installation worked like a charm. This is pretty cool, isn't it? :-) -

- -

- You can visit your version of phpMyFAQ or login into your - admin section. -

-
-
- run($routes); +} catch (Exception $exception) { + echo $exception->getMessage(); } - - System::renderFooter(); diff --git a/phpmyfaq/setup/setup.php b/phpmyfaq/setup/setup.php new file mode 100644 index 0000000000..a5214a379d --- /dev/null +++ b/phpmyfaq/setup/setup.php @@ -0,0 +1,489 @@ + + * @author Tom Rochester + * @author Johannes Schlüter + * @author Uwe Pries + * @author Matteo Scaramuccia + * @author Florian Anderiasch + * @copyright 2002-2024 phpMyFAQ Team + * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 + * @link https://www.phpmyfaq.de + * @since 2002-08-20 + */ + +use Composer\Autoload\ClassLoader; +use Elastic\Elasticsearch\Exception\AuthenticationException;use phpMyFAQ\Component\Alert; +use phpMyFAQ\Core\Exception; +use phpMyFAQ\Language\LanguageCodes; +use phpMyFAQ\Setup\Installer; +use phpMyFAQ\Strings; +use phpMyFAQ\System; +use phpMyFAQ\Translation; + +define('PMF_ROOT_DIR', dirname(__FILE__, 2)); +const PMF_SRC_DIR = PMF_ROOT_DIR . '/src'; +const IS_VALID_PHPMYFAQ = null; + +if (version_compare(PHP_VERSION, '8.1.0') < 0) { + die('Sorry, but you need PHP 8.1.0 or later!'); +} + +set_time_limit(0); + +if (!defined('DEBUG')) { + define('DEBUG', true); +} + +if (DEBUG) { + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); + error_reporting(E_ALL | E_STRICT); +} + +session_name('phpmyfaq-setup'); +session_start(); + +require PMF_ROOT_DIR . '/src/libs/autoload.php'; +require PMF_ROOT_DIR . '/src/constants.php'; +require PMF_ROOT_DIR . '/content/core/config/constants.php'; +require PMF_ROOT_DIR . '/content/core/config/constants_elasticsearch.php'; + +$loader = new ClassLoader(); +$loader->add('phpMyFAQ', PMF_SRC_DIR); +$loader->register(); +?> + + + + + phpMyFAQ <?= System::getVersion() ?> Setup + + + + + + + + + + + +
+
+ +
+
+ +
+

phpMyFAQ

+
+

+ Did you already read our + documentation + carefully before starting the phpMyFAQ setup? +

+
+
+ +
+ Database Setup + LDAP Setup + Elasticsearch Setup + Admin user account +
+ +setLanguagesDir(PMF_LANGUAGE_DIR) + ->setDefaultLanguage('en') + ->setCurrentLanguage('en') + ->setMultiByteLanguage(); +} catch (Exception $e) { + echo 'Error: ' . $e->getMessage(); +} + +$system = new System(); +$installer = new Installer($system); + +try { + $installer->checkBasicStuff(); +} catch (Exception $e) { + echo Alert::danger('ad_entryins_fail', $e->getMessage()); + System::renderFooter(); +} + +$installer->checkFilesystemPermissions(); + +// not yet POSTed +if (!isset($_POST['sql_server']) && !isset($_POST['sql_user']) && !isset($_POST['sql_db'])) { + $installer->checkNoncriticalSettings() + ?> + +
+ +

Step 1/4: Database setup

+ +
+ +
+ + Please select your preferred database type. +
+
+ +
+
+ +
+ + + Please enter the host or path to the socket of your database server. + +
+
+
+ +
+ + Please enter the port your database server. +
+
+
+ +
+ + Please enter your database user. +
+
+
+ +
+
+ + + + +
+ Please enter your database password. +
+
+
+ +
+ + Please enter your existing database name. +
+
+
+ +
+
+ +
+ + + Please enter the full path to your SQLite datafile which should be outside your document root. + +
+
+
+ +
+ +
+ + + Please enter a table prefix here if you want to install more phpMyFAQ installations in one + database. + +
+
+
+ + +
+

Step 2/4: LDAP setup

+ +
+
+ + +
+
+
+ +
+ + Please enter the host of your LDAP server. +
+
+
+ +
+ + Please enter the port of your LDAP server. +
+
+
+ +
+ + Please enter your specified RDN username. +
+
+
+ +
+ + Please enter your LDAP password. +
+
+
+ +
+ + + Please enter your distinguished name, e.g. 'cn=John Doe,ou=Accounts,o=My Company,c=US'. + +
+
+

+ You can add additional LDAP configurations later in the admin configuration panel. +

+ +
+ + + +
+

Step 3/4: Elasticsearch setup

+ +
+
+ + +
+
+
+ +
+
+ + + Add another Elasticsearch Host + +
+ + Please enter the host (domain or IP) with port number of your Elasticsearch server. + +
+
+
+ +
+ + Please enter your Elasticsearch index name. +
+
+ +
+ + + +
+

Step 4/4: Admin user setup

+ +
+ +
+ + Please select your default language. +
+
+ +
+ +
+ + + Complexity of rights and permissions. + +
+
+
+ +
+ + Please enter your real name. +
+
+
+ +
+ + Please enter your email address. +
+
+
+ +
+ + Please enter your login name. +
+
+
+ +
+
+ + + + +
+ Please enter your password with at least 8 characters. +
+
+
+ +
+
+ + + + +
+ Please retype your password. +
+
+
+
+

+ + After clicking the "Submit" button, all necessary tables will be created and filled with your data. + Depending on your system, this may take some time. Stay tuned. +

+
+
+
+ + + + + +
+
+ + +
+
+

Installation

+ startInstall(); + } catch (Exception | AuthenticationException $e) { + echo $e->getMessage(); + } + ?> +

+ Wow, looks like the installation worked like a charm. This is pretty cool, isn't it? :-) +

+ +

+ You can visit your version of phpMyFAQ or login into your + admin section. +

+
+
+ - * @author Thomas Melchinger - * @author Matteo Scaramuccia - * @copyright 2002-2024 phpMyFAQ Team - * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 - * @link https://www.phpmyfaq.de - * @since 2002-01-10 - */ - -use phpMyFAQ\Configuration; -use phpMyFAQ\Configuration\DatabaseConfiguration; -use phpMyFAQ\Filter; -use phpMyFAQ\Setup\Update; -use phpMyFAQ\Strings; -use phpMyFAQ\System; -use phpMyFAQ\Template\TwigWrapper; -use Symfony\Component\HttpFoundation\RedirectResponse; - -const COPYRIGHT = '© 2001-2024 phpMyFAQ Team'; -const IS_VALID_PHPMYFAQ = null; - -define('PMF_ROOT_DIR', dirname(__FILE__, 2)); - -if (version_compare(PHP_VERSION, '8.2.0') < 0) { - die('Sorry, but you need PHP 8.2.0 or later!'); -} - -set_time_limit(0); - -require PMF_ROOT_DIR . '/src/Bootstrap.php'; - -Strings::init(); - -$system = new System(); -$faqConfig = Configuration::getConfigurationInstance(); - -$step = Filter::filterInput(INPUT_GET, 'step', FILTER_VALIDATE_INT, 1); -$version = Filter::filterInput(INPUT_POST, 'installed-version', FILTER_SANITIZE_SPECIAL_CHARS); - -$installedVersion = $faqConfig->getVersion(); - -$update = new Update($system, $faqConfig); -$update->setVersion($installedVersion); - -if (!$update->checkDatabaseFile()) { - $redirect = new RedirectResponse('./index.php'); - $redirect->send(); -} - -$twig = new TwigWrapper(PMF_ROOT_DIR . '/assets/templates'); -$template = $twig->loadTemplate('./setup/update.twig'); - -$templateVars = [ - 'newVersion' => System::getVersion(), - 'installedVersion' => $installedVersion, - 'currentYear' => date('Y'), - 'currentStep' => $step, - 'documentationUrl' => System::getDocumentationUrl(), - 'configTableNotAvailable' => $update->isConfigTableNotAvailable($faqConfig->getDb()), -]; - -echo $template->render($templateVars); diff --git a/phpmyfaq/src/admin-routes.php b/phpmyfaq/src/admin-routes.php index 5fb4764874..5c87ad2127 100644 --- a/phpmyfaq/src/admin-routes.php +++ b/phpmyfaq/src/admin-routes.php @@ -30,6 +30,7 @@ use phpMyFAQ\Controller\Administration\ImageController; use phpMyFAQ\Controller\Administration\InstanceController; use phpMyFAQ\Controller\Administration\MarkdownController; +use phpMyFAQ\Controller\Administration\NewsController; use phpMyFAQ\Controller\Administration\QuestionController; use phpMyFAQ\Controller\Administration\SearchController; use phpMyFAQ\Controller\Administration\SessionController; @@ -40,7 +41,6 @@ use phpMyFAQ\Controller\Administration\UserController; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; -use phpMyFAQ\Controller\Administration\NewsController; $routes = new RouteCollection(); diff --git a/phpmyfaq/src/api-routes.php b/phpmyfaq/src/api-routes.php index 5bb42955a5..e58c4d0f2b 100644 --- a/phpmyfaq/src/api-routes.php +++ b/phpmyfaq/src/api-routes.php @@ -29,6 +29,7 @@ use phpMyFAQ\Controller\Api\QuestionController; use phpMyFAQ\Controller\Api\RegistrationController; use phpMyFAQ\Controller\Api\SearchController; +use phpMyFAQ\Controller\Api\SetupController; use phpMyFAQ\Controller\Api\TagController; use phpMyFAQ\Controller\Api\TitleController; use phpMyFAQ\Controller\Api\VersionController; @@ -43,7 +44,6 @@ use phpMyFAQ\Controller\Frontend\ShareController; use phpMyFAQ\Controller\Frontend\UserController; use phpMyFAQ\Controller\Frontend\VotingController; -use phpMyFAQ\Controller\Setup\SetupController; use phpMyFAQ\System; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; diff --git a/phpmyfaq/src/phpMyFAQ/Controller/AbstractController.php b/phpmyfaq/src/phpMyFAQ/Controller/AbstractController.php index cc4d6a9ad2..09b2146d6a 100644 --- a/phpmyfaq/src/phpMyFAQ/Controller/AbstractController.php +++ b/phpmyfaq/src/phpMyFAQ/Controller/AbstractController.php @@ -30,6 +30,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; +use Twig\Extension\DebugExtension; #[OA\Info( version: '3.0', @@ -67,6 +68,7 @@ public function render(string $pathToTwigFile, array $templateVars = [], Respons { $response ??= new Response(); $twigWrapper = new TwigWrapper(PMF_ROOT_DIR . '/assets/templates'); + $twigWrapper->addExtension(new DebugExtension()); $template = $twigWrapper->loadTemplate($pathToTwigFile); $response->setContent($template->render($templateVars)); diff --git a/phpmyfaq/src/phpMyFAQ/Controller/Setup/SetupController.php b/phpmyfaq/src/phpMyFAQ/Controller/Api/SetupController.php similarity index 98% rename from phpmyfaq/src/phpMyFAQ/Controller/Setup/SetupController.php rename to phpmyfaq/src/phpMyFAQ/Controller/Api/SetupController.php index 8a482d21d7..1cc6e6aa08 100644 --- a/phpmyfaq/src/phpMyFAQ/Controller/Setup/SetupController.php +++ b/phpmyfaq/src/phpMyFAQ/Controller/Api/SetupController.php @@ -15,9 +15,8 @@ * @since 2023-10-17 */ -namespace phpMyFAQ\Controller\Setup; +namespace phpMyFAQ\Controller\Api; -use phpMyFAQ\Configuration; use phpMyFAQ\Controller\AbstractController; use phpMyFAQ\Core\Exception; use phpMyFAQ\Database; diff --git a/phpmyfaq/src/phpMyFAQ/Controller/Frontend/SetupController.php b/phpmyfaq/src/phpMyFAQ/Controller/Frontend/SetupController.php new file mode 100644 index 0000000000..b30e3b9291 --- /dev/null +++ b/phpmyfaq/src/phpMyFAQ/Controller/Frontend/SetupController.php @@ -0,0 +1,131 @@ + + * @copyright 2024 phpMyFAQ Team + * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 + * @link https://www.phpmyfaq.de + * @since 2024-06-01 + */ + +namespace phpMyFAQ\Controller\Frontend; + +use Elastic\Elasticsearch\Exception\AuthenticationException; +use phpMyFAQ\Controller\AbstractController; +use phpMyFAQ\Core\Exception; +use phpMyFAQ\Filter; +use phpMyFAQ\Language\LanguageCodes; +use phpMyFAQ\Setup\Installer; +use phpMyFAQ\Setup\Update; +use phpMyFAQ\System; +use phpMyFAQ\Template\TemplateException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; + +class SetupController extends AbstractController +{ + /** + * @throws TemplateException + * @throws \Exception + */ + #[Route('/setup', name: 'public.setup.update')] + public function index(): Response + { + $system = new System(); + $installer = new Installer($system); + + $checkBasicError = ''; + + try { + $installer->checkBasicStuff(); + } catch (Exception $e) { + $checkBasicError = $e->getMessage(); + } + + return $this->render( + 'setup/index.twig', + [ + 'newVersion' => System::getVersion(), + 'setupType' => 'Setup', + 'currentYear' => date('Y'), + 'currentLanguage' => 'en', + 'documentationUrl' => System::getDocumentationUrl(), + 'checkBasicError' => $checkBasicError, + 'nonCriticalSettings' => $installer->checkNoncriticalSettings(), + 'supportedDatabases' => $system->getSupportedSafeDatabases(), + 'currentPath' => dirname(__DIR__, 4), + 'isLdapEnabled' => $installer->hasLdapSupport(), + 'isElasticsearchEnabled' => $installer->hasElasticsearchSupport(), + 'supportedTranslations' => LanguageCodes::getAllSupported(), + ] + ); + } + + /** + * @throws TemplateException + * @throws \Exception + */ + #[Route('/setup/install', name: 'public.setup.install')] + public function install(): Response + { + $system = new System(); + $installer = new Installer($system); + + $checkBasicError = $installationError = ''; + + try { + $installer->checkBasicStuff(); + } catch (Exception $e) { + $checkBasicError = $e->getMessage(); + } + + try { + $installer->startInstall(); + } catch (Exception | AuthenticationException $e) { + $installationError = $e->getMessage(); + } + + return $this->render( + 'setup/install.twig', + [ + 'newVersion' => System::getVersion(), + 'setupType' => 'Setup', + 'currentYear' => date('Y'), + 'documentationUrl' => System::getDocumentationUrl(), + 'checkBasicError' => $checkBasicError, + 'installationError' => $installationError, + ] + ); + } + + /** + * @throws TemplateException + */ + #[Route('/setup/update', name: 'public.setup.update')] + public function update(Request $request): Response + { + $currentStep = Filter::filterVar($request->get('step'), FILTER_VALIDATE_INT); + + $update = new Update(new System(), $this->configuration); + + return $this->render( + 'setup/update.twig', + [ + 'currentStep' => $currentStep ?? 1, + 'installedVersion' => System::getVersion(), + 'newVersion' => System::getVersion(), + 'currentYear' => date('Y'), + 'documentationUrl' => System::getDocumentationUrl(), + 'configTableNotAvailable' => $update->isConfigTableNotAvailable($this->configuration->getDb()), + ] + ); + } +} diff --git a/phpmyfaq/src/phpMyFAQ/Language.php b/phpmyfaq/src/phpMyFAQ/Language.php index 45421d32ac..4d4c4dd6e6 100644 --- a/phpmyfaq/src/phpMyFAQ/Language.php +++ b/phpmyfaq/src/phpMyFAQ/Language.php @@ -165,6 +165,24 @@ public function setLanguageByAcceptLanguage(): string return self::$language = $this->acceptLanguage; } + /** + * True if the language is supported by the current phpMyFAQ installation. + * + * @param string|null $langCode Language code + */ + public static function isASupportedLanguage(?string $langCode): bool + { + return $langCode !== null && LanguageCodes::getSupported($langCode) !== null; + } + + /** + * Returns the current language. + */ + public function getLanguage(): string + { + return self::$language; + } + /** * Gets the accepted language from the user agent. * @@ -193,22 +211,4 @@ private function getUserAgentLanguage(): void } } } - - /** - * True if the language is supported by the current phpMyFAQ installation. - * - * @param string|null $langCode Language code - */ - public static function isASupportedLanguage(?string $langCode): bool - { - return $langCode !== null && LanguageCodes::getSupported($langCode) !== null; - } - - /** - * Returns the current language. - */ - public function getLanguage(): string - { - return self::$language; - } } diff --git a/phpmyfaq/src/phpMyFAQ/Setup/Installer.php b/phpmyfaq/src/phpMyFAQ/Setup/Installer.php index fa39261a80..df57eac76d 100644 --- a/phpmyfaq/src/phpMyFAQ/Setup/Installer.php +++ b/phpmyfaq/src/phpMyFAQ/Setup/Installer.php @@ -621,7 +621,7 @@ public function checkBasicStuff(): void if (!$this->system->checkInstallation()) { throw new Exception( - 'phpMyFAQ is already installed! Please use the update.' + 'phpMyFAQ is already installed! Please use the update.' ); } } @@ -706,43 +706,47 @@ public function checkFilesystemPermissions(): void /** * Checks some non-critical settings and print some hints. * - * @todo We should return an array of messages + * @return string[] */ - public function checkNoncriticalSettings(): void + public function checkNoncriticalSettings(): array { + $hints = []; if (!$this->system->getHttpsStatus()) { - echo '

phpMyFAQ could not find HTTPS support. For security reasons we ' . - 'recommend activating HTTPS.

'; + $hints[] = '

phpMyFAQ could not find HTTPS support. For security reasons ' . + 'we recommend activating HTTPS.

'; } if (!extension_loaded('gd')) { - echo '

You don\'t have GD support enabled in your PHP installation. Please ' . - "enable GD support in your php.ini file otherwise you can't use Captchas for spam protection.

"; + $hints[] = '

You don\'t have GD support enabled in your PHP installation. ' . + "Please enable GD support in your php.ini file otherwise you can't use Captchas for spam protection." . + "

"; } if (!function_exists('imagettftext')) { - echo '

You don\'t have Freetype support enabled in the GD extension of ' . - 'your PHP installation. Please enable Freetype support in GD extension otherwise the Captchas ' . + $hints[] = '

You don\'t have Freetype support enabled in the GD extension ' . + ' ofyour PHP installation. Please enable Freetype support in GD extension otherwise the Captchas ' . 'for spam protection will be quite easy to break.

'; } if (!extension_loaded('curl') || !extension_loaded('openssl')) { - echo '

You don\'t have cURL and/or OpenSSL support enabled in your PHP ' . - "installation. Please enable cURL and/or OpenSSL support in your php.ini file otherwise you can't " . - 'use Elasticsearch.

'; + $hints[] = '

You don\'t have cURL and/or OpenSSL support enabled in your ' . + "PHP installation. Please enable cURL and/or OpenSSL support in your php.ini file otherwise you " . + " can't use Elasticsearch.

"; } if (!extension_loaded('fileinfo')) { - echo '

You don\'t have Fileinfo support enabled in your PHP installation. ' . - "Please enable Fileinfo support in your php.ini file otherwise you can't use our backup/restore " . - 'functionality.

'; + $hints[] = '

You don\'t have Fileinfo support enabled in your PHP ' . + "installation. Please enable Fileinfo support in your php.ini file otherwise you can't use our " . + 'backup/restore functionality.

'; } if (!extension_loaded('sodium')) { - echo '

You don\'t have Sodium support enabled in your PHP installation. ' . - "Please enable Sodium support in your php.ini file otherwise you can't use our backup/restore " . - 'functionality.

'; + $hints[] = '

You don\'t have Sodium support enabled in your PHP ' . + "installation. Please enable Sodium support in your php.ini file otherwise you can't use our " . + 'backup/restore functionality.

'; } + + return $hints; } /** @@ -753,6 +757,7 @@ public function checkNoncriticalSettings(): void */ public function startInstall(array|null $setup = null): void { + $feedbacks = []; $ldapSetup = []; $query = []; $uninstall = []; @@ -1233,4 +1238,14 @@ public function adjustRewriteBaseHtaccess(string $path): bool return file_put_contents($htaccessPath, implode('', $newLines)) !== false; } + + public function hasLdapSupport(): bool + { + return extension_loaded('ldap'); + } + + public function hasElasticsearchSupport(): bool + { + return extension_loaded('curl') && extension_loaded('openssl'); + } } diff --git a/phpmyfaq/src/phpMyFAQ/System.php b/phpmyfaq/src/phpMyFAQ/System.php index 5bebde18a0..bb34f04d24 100644 --- a/phpmyfaq/src/phpMyFAQ/System.php +++ b/phpmyfaq/src/phpMyFAQ/System.php @@ -244,9 +244,9 @@ public function getAvailableTemplates(): array * * @return array */ - public function getSupportedSafeDatabases(bool $returnAsHtml = false): array + public function getSupportedSafeDatabases(): array { - $retVal = []; + $databases = []; foreach ($this->getSupportedDatabases() as $extension => $database) { if (!extension_loaded($extension)) { continue; @@ -254,14 +254,10 @@ public function getSupportedSafeDatabases(bool $returnAsHtml = false): array if (version_compare(PHP_VERSION, $database[0]) < 0) { continue; } - if ($returnAsHtml) { - $retVal[] = sprintf('', $extension, $database[1]); - } else { - $retVal[$extension] = $database; - } + $databases[$extension] = $database[1]; } - return $retVal; + return $databases; } /** diff --git a/phpmyfaq/src/phpMyFAQ/Template/TwigWrapper.php b/phpmyfaq/src/phpMyFAQ/Template/TwigWrapper.php index c1296c1048..ac5ea98501 100644 --- a/phpmyfaq/src/phpMyFAQ/Template/TwigWrapper.php +++ b/phpmyfaq/src/phpMyFAQ/Template/TwigWrapper.php @@ -17,6 +17,7 @@ namespace phpMyFAQ\Template; +use phpMyFAQ\Core\Exception; use phpMyFAQ\System; use Twig\Environment; use Twig\Error\LoaderError; @@ -44,14 +45,14 @@ public function __construct(string $templatePath) } /** - * @throws TemplateException + * @throws Exception */ public function loadTemplate(string $templateFile): TemplateWrapper { try { return $this->twigEnvironment->load($templateFile); } catch (LoaderError | RuntimeError | SyntaxError $exception) { - throw new TemplateException($exception->getMessage()); + throw new Exception($exception->getMessage()); } } diff --git a/phpmyfaq/src/public-routes.php b/phpmyfaq/src/public-routes.php new file mode 100644 index 0000000000..e9587c90a6 --- /dev/null +++ b/phpmyfaq/src/public-routes.php @@ -0,0 +1,35 @@ + + * @copyright 2024 phpMyFAQ Team + * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 + * @link https://www.phpmyfaq.de + * @since 2024-05-31 + */ + +use phpMyFAQ\Controller\Frontend\SetupController; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +$routes = new RouteCollection(); + +$routeDefinitions = [ + // Setup and update + 'public.setup.index' => ['/', SetupController::class, 'index'], + 'public.setup.install' => ['/install', SetupController::class, 'install'], + 'public.setup.update' => ['/update', SetupController::class, 'update'], +]; + +foreach ($routeDefinitions as $name => [$path, $controller, $action]) { + $routes->add($name, new Route($path, ['_controller' => [$controller, $action]])); +} + +return $routes;