diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..0931299 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,55 @@ +# Space Profiles Installation Guide + +This guide installs the `space_profiles` module in a reusable way for any HumHub instance. + +## 1. Requirements + +- HumHub `1.14+` +- Module directory access on the target instance +- Optional but recommended: `rescue_foundation` module + +## 2. Clone into HumHub Modules Directory + +The folder name must be exactly `space_profiles`. + +```bash +git clone https://gitea.kelinreij.duckdns.org/humhub-modules/space-profiles.git \ + /var/www/localhost/htdocs/protected/modules/space_profiles +``` + +If the folder already exists: + +```bash +cd /var/www/localhost/htdocs/protected/modules/space_profiles +git pull +``` + +## 3. Enable the Module + +In HumHub UI: + +1. Go to `Administration` -> `Modules`. +2. Enable `Space Profiles`. +3. Enable it per space where needed. + +## 4. Run Migrations + +From the HumHub app host/container: + +```bash +php /var/www/localhost/htdocs/protected/yii migrate/up \ + --include-module-migrations=1 --interactive=0 +``` + +## 5. Verify + +1. Open a space with module enabled. +2. Confirm profile page renders the template sections. +3. Confirm space settings page saves expected profile fields. + +## Docker Example + +```bash +docker exec humhub php /var/www/localhost/htdocs/protected/yii migrate/up \ + --include-module-migrations=1 --interactive=0 +``` diff --git a/controllers/SettingsController.php b/controllers/SettingsController.php index 99d7218..cff9c66 100644 --- a/controllers/SettingsController.php +++ b/controllers/SettingsController.php @@ -7,8 +7,10 @@ use humhub\modules\content\components\ContentContainerControllerAccess; use humhub\modules\rescue_foundation\widgets\RescueSettingsMenu; use humhub\modules\space\models\Space; use humhub\modules\space_profiles\models\forms\SpaceProfileForm; +use humhub\modules\space_profiles\services\ModuleSetupService; use Yii; use yii\web\UploadedFile; +use yii\web\BadRequestHttpException; class SettingsController extends ContentContainerController { @@ -41,4 +43,34 @@ class SettingsController extends ContentContainerController 'subNav' => $subNav, ]); } + + public function actionSetup() + { + if (!Yii::$app->request->isPost) { + throw new BadRequestHttpException('Invalid request method.'); + } + + if (!$this->contentContainer instanceof Space) { + $this->view->error(Yii::t('SpaceProfilesModule.base', 'Setup can only be run inside a space.')); + return $this->redirect($this->contentContainer->createUrl('/space_profiles/settings')); + } + + try { + $result = ModuleSetupService::runForSpace($this->contentContainer); + $appliedCount = count($result['applied'] ?? []); + + if ($appliedCount > 0) { + $this->view->success(Yii::t('SpaceProfilesModule.base', 'Setup completed. Applied {count} migration(s).', [ + 'count' => $appliedCount, + ])); + } else { + $this->view->success(Yii::t('SpaceProfilesModule.base', 'Setup completed. No pending migrations were found.')); + } + } catch (\Throwable $e) { + Yii::error($e, 'space_profiles.setup'); + $this->view->error(Yii::t('SpaceProfilesModule.base', 'Setup failed. Please check logs and try again.')); + } + + return $this->redirect($this->contentContainer->createUrl('/space_profiles/settings')); + } } diff --git a/services/ModuleSetupService.php b/services/ModuleSetupService.php new file mode 100644 index 0000000..e4c5945 --- /dev/null +++ b/services/ModuleSetupService.php @@ -0,0 +1,70 @@ +createUrl('/space_profiles/profile/view'); + $settings = $space->getSettings(); + $settings->set('indexUrl', $defaultUrl); + $settings->set('indexGuestUrl', $defaultUrl); + + $result['defaultHomeUrl'] = $defaultUrl; + return $result; + } + + private static function applyModuleMigrations(): array + { + $migrationDir = dirname(__DIR__) . '/migrations'; + $files = glob($migrationDir . '/m*.php') ?: []; + sort($files, SORT_NATURAL); + + $existingVersions = Yii::$app->db->createCommand('SELECT version FROM migration')->queryColumn(); + $history = array_fill_keys($existingVersions, true); + + $applied = []; + $skipped = []; + + foreach ($files as $file) { + $version = pathinfo($file, PATHINFO_FILENAME); + if (isset($history[$version])) { + $skipped[] = $version; + continue; + } + + if (!class_exists($version, false)) { + require_once $file; + } + + if (!class_exists($version, false)) { + throw new \RuntimeException('Migration class not found: ' . $version); + } + + $migration = new $version(); + $ok = method_exists($migration, 'safeUp') ? $migration->safeUp() : $migration->up(); + if ($ok === false) { + throw new \RuntimeException('Migration failed: ' . $version); + } + + Yii::$app->db->createCommand()->insert('migration', [ + 'version' => $version, + 'apply_time' => time(), + ])->execute(); + + $applied[] = $version; + $history[$version] = true; + } + + return [ + 'applied' => $applied, + 'skipped' => $skipped, + ]; + } +} diff --git a/views/profile/_rescue-info.php b/views/profile/_rescue-info.php new file mode 100644 index 0000000..c06e724 --- /dev/null +++ b/views/profile/_rescue-info.php @@ -0,0 +1,52 @@ + + +