From f4dc336c88fd19a27171ac034e724f678dcc8b58 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 2 Jun 2026 20:54:08 +0200 Subject: [PATCH 1/9] Club System --- Api/Controller/EntryController.php | 25 +++++++ ApprovalQueue/ClubRequest.php | 83 +++++++++++++++++++++++ Entity/ClubRequest.php | 75 ++++++++++++++++++++ Pub/Controller/Club.php | 32 +++++++++ Pub/Controller/Webhook.php | 36 ---------- Setup.php | 23 +++++++ XF/Entity/User.php | 18 +++++ _output/navigation/_metadata.json | 4 +- _output/navigation/contact_us.json | 2 +- _output/navigation/submissions_queue.json | 2 +- _output/permissions/_metadata.json | 24 +++++++ _output/phrases/_metadata.json | 72 ++++++++++++++++++++ _output/templates/_metadata.json | 15 ++++ 13 files changed, 371 insertions(+), 40 deletions(-) create mode 100644 Api/Controller/EntryController.php create mode 100644 ApprovalQueue/ClubRequest.php create mode 100644 Entity/ClubRequest.php create mode 100644 Pub/Controller/Club.php delete mode 100644 Pub/Controller/Webhook.php create mode 100644 XF/Entity/User.php diff --git a/Api/Controller/EntryController.php b/Api/Controller/EntryController.php new file mode 100644 index 0000000..1b60457 --- /dev/null +++ b/Api/Controller/EntryController.php @@ -0,0 +1,25 @@ +filter('user_id', 'uint'); + $count = $this->filter('count', 'uint'); + + $user = $this->assertRecordExists('XF:User', $userId); + + $user->rhpz_entry_count = $count; + $user->save(); + + $trophyRepo = $this->repository('XF:Trophy'); + $trophyRepo->updateTrophiesForUser($user); + + return $this->apiSuccess(['success' => true,'user_id' => $user->user_id,'count' => $count]); + } +} \ No newline at end of file diff --git a/ApprovalQueue/ClubRequest.php b/ApprovalQueue/ClubRequest.php new file mode 100644 index 0000000..97c7d2b --- /dev/null +++ b/ApprovalQueue/ClubRequest.php @@ -0,0 +1,83 @@ +canActionContent($content, $error); + } + + protected function canActionContent(Entity $content, &$error = null) + { + return \XF::visitor()->hasAdminPermission('node'); + } + + public function getEntityWith() + { + return ['User']; + } + + public function actionApprove(\RomhackPlaza\Master\Entity\ClubRequest $clubRequest) + { + $clubRequest->request_state = 'visible'; + $clubRequest->save(); + + $node = \XF::em()->create('XF:Node'); + $node->node_type_id = 'Forum'; + $node->title = $clubRequest->title; + $node->description = $clubRequest->description; + $node->parent_node_id = \XF::options()->rhpz_club_node_id ?? 0; + $node->display_order = 1; + $node->save(); + + $forum = \XF::em()->create('XF:Forum'); + $forum->node_id = $node->node_id; + $forum->allow_posting = true; + $forum->save(); + + $user = $clubRequest->User; + if ($user) { + + $modContent = \XF::em()->create('XF:ModeratorContent'); + $modContent->content_type = 'node'; + $modContent->content_id = $node->node_id; + $modContent->user_id = $user->user_id; + $modContent->save(); + + $permissionUpdater = \XF::app()->service('XF:UpdatePermissions'); + $permissionUpdater->setContent('node', $node->node_id); + $permissionUpdater->setUser($user); + + $permissionUpdater->updatePermissions([ + 'forum' => [ + 'editAnyPost' => 'content_allow', + 'deleteAnyPost' => 'content_allow', + 'deleteAnyThread' => 'content_allow', + 'inlineMod' => 'content_allow', + 'lockUnlockThread' => 'content_allow', + 'stickUnstickThread' => 'content_allow' + ] + ]); + + // D. Reconstruction des permissions + \XF::app()->jobManager()->enqueueUnique('permissionRebuild', 'XF:PermissionRebuild'); + } + } + + public function actionReject(\RomhackPlaza\Master\Entity\ClubRequest $clubRequest) + { + $clubRequest->request_state = 'rejected'; + $clubRequest->save(); + } + + public function getTemplateName() + { + return 'public:approval_item_club_request'; + } +} \ No newline at end of file diff --git a/Entity/ClubRequest.php b/Entity/ClubRequest.php new file mode 100644 index 0000000..c0754b0 --- /dev/null +++ b/Entity/ClubRequest.php @@ -0,0 +1,75 @@ +table = 'xf_club_request'; + $structure->shortName = 'RomhackPlaza\Master:ClubRequest'; + $structure->primaryKey = 'request_id'; + $structure->columns = [ + 'request_id' => ['type' => self::UINT, 'autoIncrement' => true], + 'user_id' => ['type' => self::UINT, 'required' => true], + 'title' => ['type' => self::STR, 'maxLength' => 100, 'required' => true], + 'description' => ['type' => self::STR, 'required' => true], + 'request_state' => ['type' => self::STR, 'default' => 'moderated', + 'allowedValues' => ['visible', 'moderated', 'rejected'] + ], + 'request_date' => ['type' => self::UINT, 'default' => \XF::$time] + ]; + $structure->relations = [ + 'User' => [ + 'entity' => 'XF:User', + 'type' => self::TO_ONE, + 'conditions' => 'user_id', + 'primary' => true + ] + ]; + + return $structure; + } + + protected function _postSave() + { + if( $this->isInsert() && $this->request_state == 'moderated' ){ + $this->inQueue(); + } else if( $this->isUpdate() && $this->isChanged('request_state') ){ + if( $this->request_state === 'moderated' ){ + $this->inQueue(); + } else { + $this->removeQueue(); + } + } + } + + protected function _postDelete() + { + if( $this->request_state === 'moderated' ){ + $this->removeQueue(); + } + } + + protected function inQueue() + { + $queue = $this->em()->find('XF:ApprovalQueue', ['club_request', $this->request_id ] ); + if( !$queue ) + { + $newQueue = $this->em()->create('XF:ApprovalQueue'); + $newQueue->content_type = 'club_request'; + $newQueue->content_id = $this->request_id; + $newQueue->save(); + } + } + + protected function removeQueue() + { + $queue = $this->em()->find('XF:ApprovalQueue', ['club_request', $this->request_id ] ); + if( $queue ) + $queue->delete(); + } +} \ No newline at end of file diff --git a/Pub/Controller/Club.php b/Pub/Controller/Club.php new file mode 100644 index 0000000..747c2c3 --- /dev/null +++ b/Pub/Controller/Club.php @@ -0,0 +1,32 @@ +assertRegistrationRequired(); + + return $this->view('RomhackPlaza\Master:Club\Request', 'club_request_form'); + } + + public function actionSave(ParameterBag $params) + { + $this->assertRegistrationRequired(); + $this->assertPostOnly(); + + $entity = $this->em()->create('RomhackPlaza\Master:ClubRequest'); + $entity->user_id = \XF::visitor()->user_id; + $entity->title = $this->filter('title','str'); + $entity->description = $this->filter('description','str'); + $entity->request_state = 'moderated'; + $entity->save(); + + return $this->redirect($this->buildLink('clubs'), "Your club creation request has been submitted and is awaiting approval by a staff member."); + } +} \ No newline at end of file diff --git a/Pub/Controller/Webhook.php b/Pub/Controller/Webhook.php deleted file mode 100644 index 016968d..0000000 --- a/Pub/Controller/Webhook.php +++ /dev/null @@ -1,36 +0,0 @@ -assertPostOnly(); - - $token = $this->filter('_token', 'str'); - $secret = \XF::options()->rhpz_webhook_secret ?? ''; - - if( !$secret || !hash_equals($secret, $token) ){ - return $this->error('Unauthorized', 401); - } - - $userId = $this->filter('user_id', 'uint'); - $count = $this->filter('count', 'uint'); - - $user = \XF::em()->find('XF:User', $userId); - if( !$user ){ - return $this->error('User not found', 404); - } - - $user->rhpz_entry_count = $count; - $user->save(); - - $trophyService = \XF::service('XF:Trophy\Notify', $user); - $trophyService->checkAndAwardTrophies(); - - return $this->apiSuccess(['count' => $count]); - } -} \ No newline at end of file diff --git a/Setup.php b/Setup.php index 3401385..83d1c76 100644 --- a/Setup.php +++ b/Setup.php @@ -6,6 +6,7 @@ use XF\AddOn\AbstractSetup; use XF\AddOn\StepRunnerInstallTrait; use XF\AddOn\StepRunnerUninstallTrait; use XF\AddOn\StepRunnerUpgradeTrait; +use XF\Db\Schema\Create; class Setup extends AbstractSetup { @@ -23,10 +24,32 @@ class Setup extends AbstractSetup }); } + /** + * Create club request table. + * @return void + */ + public function installStep2(): void + { + $this->schemaManager()->createTable('xf_club_request', function(Create $table){ + $table->addColumn('request_id', 'int')->autoIncrement(); + $table->addColumn('user_id', 'int'); + $table->addColumn('title', 'varchar', 100); + $table->addColumn('description', 'text'); + $table->addColumn('request_state', 'enum')->values(['visible','moderated','rejected'])->setDefault('moderated'); + $table->addColumn('request_date','int'); + $table->addKey('request_state'); + }); + } + public function uninstallStep1(): void { $this->schemaManager()->alterTable('xf_user', function($table) { $table->dropColumns(['rhpz_entry_count']); }); } + + public function uninstallStep2(): void + { + $this->schemaManager()->dropTable('xf_club_request'); + } } \ No newline at end of file diff --git a/XF/Entity/User.php b/XF/Entity/User.php new file mode 100644 index 0000000..4037bc6 --- /dev/null +++ b/XF/Entity/User.php @@ -0,0 +1,18 @@ +columns['rhpz_entry_count'] = [ 'type' => self::UINT, 'default' => 0 ]; + + return $structure; + } +} \ No newline at end of file diff --git a/_output/navigation/_metadata.json b/_output/navigation/_metadata.json index f0dcf00..b8b2f6d 100644 --- a/_output/navigation/_metadata.json +++ b/_output/navigation/_metadata.json @@ -6,7 +6,7 @@ "hash": "bddec05ee1acb9cb82ed72155bdd7817" }, "contact_us.json": { - "hash": "2a0528c2bc4338d4541074f90790c127" + "hash": "05d205aee6ac1db9d9ad0f68bdd4f7c2" }, "database.json": { "hash": "7b42b608fad8ab23417a8cc3fcd331c2" @@ -42,7 +42,7 @@ "hash": "73fab3932646c350da9a40102f650d9d" }, "submissions_queue.json": { - "hash": "f603ca2b1de0c4aaf60fadcec9ea85a7" + "hash": "84060a775af4419d44c8dc2c083ef447" }, "tools.json": { "hash": "0221bb27d36511c5dd1feaf697626778" diff --git a/_output/navigation/contact_us.json b/_output/navigation/contact_us.json index 4835439..1fcb8d4 100644 --- a/_output/navigation/contact_us.json +++ b/_output/navigation/contact_us.json @@ -3,7 +3,7 @@ "display_order": 3, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/pages/contact-us", + "link": "{{ link('misc/contact') }}", "display_condition": "", "extra_attributes": { "icon": "at-sign" diff --git a/_output/navigation/submissions_queue.json b/_output/navigation/submissions_queue.json index 77a24c8..9439978 100644 --- a/_output/navigation/submissions_queue.json +++ b/_output/navigation/submissions_queue.json @@ -3,7 +3,7 @@ "display_order": 3, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/submissions-queue", + "link": "{$xf.options.homePageUrl}/queue", "display_condition": "", "extra_attributes": { "icon": "gavel" diff --git a/_output/permissions/_metadata.json b/_output/permissions/_metadata.json index db36751..b22d231 100644 --- a/_output/permissions/_metadata.json +++ b/_output/permissions/_metadata.json @@ -1,7 +1,31 @@ { + "romhackplaza-canEditMyEntries.json": { + "hash": "4fa023f096147e72d0ca94e5ce231228" + }, + "romhackplaza-canEditOthersEntries.json": { + "hash": "c2e1c6213b7266fa56ead62676784a26" + }, + "romhackplaza-canModerateEntries.json": { + "hash": "dfee0d9b78d1833c648d9c5047c29a33" + }, + "romhackplaza-canSeeHiddenEntries.json": { + "hash": "3a71377fae8f064eafaef3ac0f8bed68" + }, + "romhackplaza-canSeeLockedEntries.json": { + "hash": "f0907b5c0da0c465195a19babd671343" + }, + "romhackplaza-canSeeOthersDrafts.json": { + "hash": "fbd94dac811e001e8923ed28da460367" + }, + "romhackplaza-canSeeRejectedEntries.json": { + "hash": "5c015bf4b7012720a4f7bcfdb8eb9521" + }, "romhackplaza-canSubmitEntry.json": { "hash": "6eeb397b6596b6774af70dbbf5454106" }, + "romhackplaza-canSubmitEntryInPublished.json": { + "hash": "39acd4f2cc864663e5978b18cb390a5c" + }, "romhackplaza-canSubmitTempFile.json": { "hash": "d514bba0211dc91897efce276c499131" }, diff --git a/_output/phrases/_metadata.json b/_output/phrases/_metadata.json index 490fb85..7135574 100644 --- a/_output/phrases/_metadata.json +++ b/_output/phrases/_metadata.json @@ -101,12 +101,84 @@ "version_string": "1.0.0", "hash": "15bbb9d0bbf25e8d2978de1168c749dc" }, + "option.rhpz_club_node_id.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "e73496f262c162a1a35bd9e990b36825" + }, + "option_explain.rhpz_club_node_id.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d41d8cd98f00b204e9800998ecf8427e" + }, + "option_group.romhackplaza.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "4b206b2374c877bad80e7cd2303936be" + }, + "option_group_description.romhackplaza.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d41d8cd98f00b204e9800998ecf8427e" + }, + "permission.romhackplaza_canEditMyEntries.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "1a932031ffdf7a07800d30b2d898fc34" + }, + "permission.romhackplaza_canEditOthersEntries.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "83d885098bc54e2afa37b3045c8048f3" + }, + "permission.romhackplaza_canModerateEntries.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "7ab831a3557b53a4a63ac279cd33fc36" + }, + "permission.romhackplaza_canSeeHiddenEntries.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "20fbb37e0be574bb4060c16c1caf6d50" + }, + "permission.romhackplaza_canSeeLockedEntries.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "4738ddb90744d6caf4e46335eeac511a" + }, + "permission.romhackplaza_canSeeOthersDrafts.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "4c2c7800c562085f51a3b486dfb8e5bb" + }, + "permission.romhackplaza_canSeeRejectedEntries.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "827c586329fad5466cccf547f5011bea" + }, "permission.romhackplaza_canSubmitEntry.txt": { "global_cache": false, "version_id": 1000000, "version_string": "1.0.0", "hash": "d62432dfaf4d83315ed838ce10794fa1" }, + "permission.romhackplaza_canSubmitEntryInPublished.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "40e2c757fc3f0056a40aa98dec7d2d25" + }, "permission.romhackplaza_canSubmitTempFile.txt": { "global_cache": false, "version_id": 1000000, diff --git a/_output/templates/_metadata.json b/_output/templates/_metadata.json index 82b0a23..d25982e 100644 --- a/_output/templates/_metadata.json +++ b/_output/templates/_metadata.json @@ -3,5 +3,20 @@ "version_id": 1000000, "version_string": "1.0.0", "hash": "19cd05c4ab254dbad0abfd0c6b8c3456" + }, + "public/approval_item_club_request.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "39492e4fb48e7aa1622a6bb4371a36f4" + }, + "public/club_request_form.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "5e1c397d93134aaa7164301d5a3553ce" + }, + "public/report_content_romhackplaza_entry.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d6c5c25a9af81a7da2bd8e2b9f74229e" } } \ No newline at end of file From 8eb94ff05d07b9a82db691ae64e68d3128e76497 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 2 Jun 2026 20:54:38 +0200 Subject: [PATCH 2/9] Club System --- Entity/Entry.php | 28 +++++++ Helper/Laravel.php | 24 ++++++ Pub/Controller/Entry.php | 50 ++++++++++++ Report/Entry.php | 76 +++++++++++++++++++ ...er_RomhackPlaza-Master-XF-Entity-User.json | 6 ++ _output/class_extensions/_metadata.json | 5 ++ _output/content_type_fields/_metadata.json | 14 ++++ ..._request-approval_queue_handler_class.json | 5 ++ .../club_request-entity.json | 5 ++ .../romhackplaza_entry-entity.json | 5 ++ ...mhackplaza_entry-report_handler_class.json | 5 ++ _output/extension_hint.php | 14 ++++ _output/option_groups/_metadata.json | 5 ++ _output/option_groups/romhackplaza.json | 6 ++ _output/option_hint.php | 18 +++++ _output/options/_metadata.json | 5 ++ _output/options/rhpz_club_node_id.json | 13 ++++ .../romhackplaza-canEditMyEntries.json | 6 ++ .../romhackplaza-canEditOthersEntries.json | 6 ++ .../romhackplaza-canModerateEntries.json | 6 ++ .../romhackplaza-canSeeHiddenEntries.json | 6 ++ .../romhackplaza-canSeeLockedEntries.json | 6 ++ .../romhackplaza-canSeeOthersDrafts.json | 6 ++ .../romhackplaza-canSeeRejectedEntries.json | 6 ++ ...omhackplaza-canSubmitEntryInPublished.json | 6 ++ _output/phrases/option.rhpz_club_node_id.txt | 1 + .../option_explain.rhpz_club_node_id.txt | 0 _output/phrases/option_group.romhackplaza.txt | 1 + .../option_group_description.romhackplaza.txt | 0 ...rmission.romhackplaza_canEditMyEntries.txt | 1 + ...sion.romhackplaza_canEditOthersEntries.txt | 1 + ...ission.romhackplaza_canModerateEntries.txt | 1 + ...ssion.romhackplaza_canSeeHiddenEntries.txt | 1 + ...ssion.romhackplaza_canSeeLockedEntries.txt | 1 + ...ission.romhackplaza_canSeeOthersDrafts.txt | 1 + ...ion.romhackplaza_canSeeRejectedEntries.txt | 1 + ...romhackplaza_canSubmitEntryInPublished.txt | 1 + _output/routes/_metadata.json | 11 +++ _output/routes/api_romhackplaza_entry_.json | 11 +++ _output/routes/public_clubs_.json | 11 +++ .../routes/public_romhackplaza_entry_.json | 11 +++ .../public/approval_item_club_request.html | 11 +++ .../templates/public/club_request_form.html | 11 +++ .../report_content_romhackplaza_entry.html | 4 + 44 files changed, 412 insertions(+) create mode 100644 Entity/Entry.php create mode 100644 Helper/Laravel.php create mode 100644 Pub/Controller/Entry.php create mode 100644 Report/Entry.php create mode 100644 _output/class_extensions/XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json create mode 100644 _output/class_extensions/_metadata.json create mode 100644 _output/content_type_fields/_metadata.json create mode 100644 _output/content_type_fields/club_request-approval_queue_handler_class.json create mode 100644 _output/content_type_fields/club_request-entity.json create mode 100644 _output/content_type_fields/romhackplaza_entry-entity.json create mode 100644 _output/content_type_fields/romhackplaza_entry-report_handler_class.json create mode 100644 _output/extension_hint.php create mode 100644 _output/option_groups/_metadata.json create mode 100644 _output/option_groups/romhackplaza.json create mode 100644 _output/option_hint.php create mode 100644 _output/options/_metadata.json create mode 100644 _output/options/rhpz_club_node_id.json create mode 100644 _output/permissions/romhackplaza-canEditMyEntries.json create mode 100644 _output/permissions/romhackplaza-canEditOthersEntries.json create mode 100644 _output/permissions/romhackplaza-canModerateEntries.json create mode 100644 _output/permissions/romhackplaza-canSeeHiddenEntries.json create mode 100644 _output/permissions/romhackplaza-canSeeLockedEntries.json create mode 100644 _output/permissions/romhackplaza-canSeeOthersDrafts.json create mode 100644 _output/permissions/romhackplaza-canSeeRejectedEntries.json create mode 100644 _output/permissions/romhackplaza-canSubmitEntryInPublished.json create mode 100644 _output/phrases/option.rhpz_club_node_id.txt create mode 100644 _output/phrases/option_explain.rhpz_club_node_id.txt create mode 100644 _output/phrases/option_group.romhackplaza.txt create mode 100644 _output/phrases/option_group_description.romhackplaza.txt create mode 100644 _output/phrases/permission.romhackplaza_canEditMyEntries.txt create mode 100644 _output/phrases/permission.romhackplaza_canEditOthersEntries.txt create mode 100644 _output/phrases/permission.romhackplaza_canModerateEntries.txt create mode 100644 _output/phrases/permission.romhackplaza_canSeeHiddenEntries.txt create mode 100644 _output/phrases/permission.romhackplaza_canSeeLockedEntries.txt create mode 100644 _output/phrases/permission.romhackplaza_canSeeOthersDrafts.txt create mode 100644 _output/phrases/permission.romhackplaza_canSeeRejectedEntries.txt create mode 100644 _output/phrases/permission.romhackplaza_canSubmitEntryInPublished.txt create mode 100644 _output/routes/_metadata.json create mode 100644 _output/routes/api_romhackplaza_entry_.json create mode 100644 _output/routes/public_clubs_.json create mode 100644 _output/routes/public_romhackplaza_entry_.json create mode 100644 _output/templates/public/approval_item_club_request.html create mode 100644 _output/templates/public/club_request_form.html create mode 100644 _output/templates/public/report_content_romhackplaza_entry.html diff --git a/Entity/Entry.php b/Entity/Entry.php new file mode 100644 index 0000000..ef1091f --- /dev/null +++ b/Entity/Entry.php @@ -0,0 +1,28 @@ +shortName = 'RomhackPlaza\Master:Entry'; + $structure->table = 'xf_romhackplaza_entry'; // Unused. + $structure->primaryKey = 'id'; + + $structure->columns = [ + 'id' => ['type' => self::UINT], + 'user_id' => ['type' => self::UINT, 'required' => true], + 'title' => ['type' => self::STR, 'required' => true], + 'slug' => ['type' => self::STR, 'required' => true], + 'type' => ['type' => self::STR, 'required' => true], + ]; + + return $structure; + } +} \ No newline at end of file diff --git a/Helper/Laravel.php b/Helper/Laravel.php new file mode 100644 index 0000000..50cab2d --- /dev/null +++ b/Helper/Laravel.php @@ -0,0 +1,24 @@ +container(); + if( !isset( $container['laravelDb'] ) ){ + $container['laravelDb'] = function(Container $c){ + $config = \XF::config('sitedb'); + if( !$config ) + return null; + + return new \XF\Db\Mysqli\Adapter($config, true); + }; + } + + return $container['laravelDb']; + } +} \ No newline at end of file diff --git a/Pub/Controller/Entry.php b/Pub/Controller/Entry.php new file mode 100644 index 0000000..5a5139e --- /dev/null +++ b/Pub/Controller/Entry.php @@ -0,0 +1,50 @@ +id; + $laravelDb = \RomhackPlaza\Master\Helper\Laravel::db(); + if( !$laravelDb ) + return $this->notFound(); + + $entry = $laravelDb->fetchRow("SELECT id, slug, type FROM entries WHERE id = ?", $entryId); + if( !$entry ) + return $this->notFound(); + + return $this->redirect(\XF::options()->homePageUrl . '/' . $entry['type'] . '/' . $entry['slug']); + } + + public function actionReport(ParameterBag $params): AbstractReply + { + + $this->assertRegistrationRequired(); + + $entryId = $params->id; + $laravelDb = \RomhackPlaza\Master\Helper\Laravel::db(); + if( !$laravelDb ) + return $this->notFound(); + + $entry = $laravelDb->fetchRow("SELECT id, complete_title as title, slug, type, user_id, description FROM entries WHERE id = ?", $entryId); + if( !$entry ) + return $this->notFound(); + + $entity = $this->em()->instantiateEntity('RomhackPlaza\Master:Entry', $entry); + $entity->setReadOnly(true); + + $reportPlugin = $this->plugin('XF:Report'); + return $reportPlugin->actionReport( + 'romhackplaza_entry', $entity, + $this->buildLink('romhackplaza_entry/report', $entity), + \XF::options()->homePageUrl . '/entry/report_redirect?id=' . $entity->id + ); + + } +} \ No newline at end of file diff --git a/Report/Entry.php b/Report/Entry.php new file mode 100644 index 0000000..1b45027 --- /dev/null +++ b/Report/Entry.php @@ -0,0 +1,76 @@ +hasPermission('romhackplaza', 'view'); + } + + #[Override] + protected function canActionContent(Report $report) + { + return \XF::visitor()->hasPermission('romhackplaza', 'canEditOthersEntries'); + } + + #[Override] + public function setupReportEntityContent(Report $report, Entity $content) + { + $report->content_user_id = $content['user_id']; + $report->content_info = [ + 'id' => $content['id'], + 'title' => $content['title'], + 'slug' => $content['slug'], + 'type' => $content['type'], + 'user_id' => $content['user_id'], + 'description' => $content['description'] ?? "", + ]; + } + + public function getContent($id) + { + $laravelDb = \RomhackPlaza\Master\Helper\Laravel::db(); + + if( $laravelDb ){ + $entry = $laravelDb->fetchRow("SELECT id, complete_title as title, slug, type, user_id, description FROM entries WHERE id = ?", $id); + $entity = \XF::em()->instantiateEntity('RomhackPlaza\Master:Entry', $entry); + $entity->setReadOnly(true); + return $entity; + } + + return null; + } + + #[Override] + public function getContentTitle(Report $report) + { + return $report->content_info['title'] ?? 'Unknown'; + } + + #[Override] + public function getContentLink(Report $report) + { + return \XF::options()->homePageUrl . '/' . $report->content_info['type'] . '/' . $report->content_info['slug']; + } + + #[Override] + public function getContentMessage(Report $report) + { + return $report->content_info['message']; + } + + #[Override] + public function getTemplateName() + { + return "public:report_content_romhackplaza_entry"; + } +} \ No newline at end of file diff --git a/_output/class_extensions/XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json b/_output/class_extensions/XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json new file mode 100644 index 0000000..dbc58f0 --- /dev/null +++ b/_output/class_extensions/XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json @@ -0,0 +1,6 @@ +{ + "from_class": "XF\\Entity\\User", + "to_class": "RomhackPlaza\\Master\\XF\\Entity\\User", + "execute_order": 10, + "active": true +} \ No newline at end of file diff --git a/_output/class_extensions/_metadata.json b/_output/class_extensions/_metadata.json new file mode 100644 index 0000000..96c4b77 --- /dev/null +++ b/_output/class_extensions/_metadata.json @@ -0,0 +1,5 @@ +{ + "XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json": { + "hash": "811593d6f012a53b9fa2ced871de96a9" + } +} \ No newline at end of file diff --git a/_output/content_type_fields/_metadata.json b/_output/content_type_fields/_metadata.json new file mode 100644 index 0000000..102b3e5 --- /dev/null +++ b/_output/content_type_fields/_metadata.json @@ -0,0 +1,14 @@ +{ + "club_request-approval_queue_handler_class.json": { + "hash": "e46546c5b569b04e7ad740a672d217cd" + }, + "club_request-entity.json": { + "hash": "547d2af8708a4c569b3b09fdd9308880" + }, + "romhackplaza_entry-entity.json": { + "hash": "8686ffd261eb8c1698a3ec6e31118f02" + }, + "romhackplaza_entry-report_handler_class.json": { + "hash": "3e3d009b1b4671a506accc2e920307b2" + } +} \ No newline at end of file diff --git a/_output/content_type_fields/club_request-approval_queue_handler_class.json b/_output/content_type_fields/club_request-approval_queue_handler_class.json new file mode 100644 index 0000000..3aaaaf2 --- /dev/null +++ b/_output/content_type_fields/club_request-approval_queue_handler_class.json @@ -0,0 +1,5 @@ +{ + "content_type": "club_request", + "field_name": "approval_queue_handler_class", + "field_value": "RomhackPlaza\\Master\\ApprovalQueue\\ClubRequest" +} \ No newline at end of file diff --git a/_output/content_type_fields/club_request-entity.json b/_output/content_type_fields/club_request-entity.json new file mode 100644 index 0000000..17f5bcf --- /dev/null +++ b/_output/content_type_fields/club_request-entity.json @@ -0,0 +1,5 @@ +{ + "content_type": "club_request", + "field_name": "entity", + "field_value": "RomhackPlaza\\Master\\Entity\\ClubRequest" +} \ No newline at end of file diff --git a/_output/content_type_fields/romhackplaza_entry-entity.json b/_output/content_type_fields/romhackplaza_entry-entity.json new file mode 100644 index 0000000..91b1c6a --- /dev/null +++ b/_output/content_type_fields/romhackplaza_entry-entity.json @@ -0,0 +1,5 @@ +{ + "content_type": "romhackplaza_entry", + "field_name": "entity", + "field_value": "RomhackPlaza\\Master\\Entity\\Entry" +} \ No newline at end of file diff --git a/_output/content_type_fields/romhackplaza_entry-report_handler_class.json b/_output/content_type_fields/romhackplaza_entry-report_handler_class.json new file mode 100644 index 0000000..fc2967f --- /dev/null +++ b/_output/content_type_fields/romhackplaza_entry-report_handler_class.json @@ -0,0 +1,5 @@ +{ + "content_type": "romhackplaza_entry", + "field_name": "report_handler_class", + "field_value": "RomhackPlaza\\Master\\Report\\Entry" +} \ No newline at end of file diff --git a/_output/extension_hint.php b/_output/extension_hint.php new file mode 100644 index 0000000..ae897a0 --- /dev/null +++ b/_output/extension_hint.php @@ -0,0 +1,14 @@ +", + "build_class": "", + "build_method": "", + "controller": "RomhackPlaza\\Master:Entry", + "context": "", + "action_prefix": "" +} \ No newline at end of file diff --git a/_output/templates/public/approval_item_club_request.html b/_output/templates/public/approval_item_club_request.html new file mode 100644 index 0000000..ba30adb --- /dev/null +++ b/_output/templates/public/approval_item_club_request.html @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/_output/templates/public/club_request_form.html b/_output/templates/public/club_request_form.html new file mode 100644 index 0000000..8ecd903 --- /dev/null +++ b/_output/templates/public/club_request_form.html @@ -0,0 +1,11 @@ +Submit Club Request + + +
+
+ + +
+ +
+
\ No newline at end of file diff --git a/_output/templates/public/report_content_romhackplaza_entry.html b/_output/templates/public/report_content_romhackplaza_entry.html new file mode 100644 index 0000000..a3c44e4 --- /dev/null +++ b/_output/templates/public/report_content_romhackplaza_entry.html @@ -0,0 +1,4 @@ +
+ {{ phrase('content:') }} + {$report.content_info.description} +
\ No newline at end of file From 4415a2e8c4bcc78744701fb086061e76b8988b5e Mon Sep 17 00:00:00 2001 From: Benjamin Date: Mon, 8 Jun 2026 16:25:52 +0200 Subject: [PATCH 3/9] A lot of things. --- Api/Controller/ThreadController.php | 33 ++++ ApprovalQueue/{ClubRequest.php => Club.php} | 35 ++-- Entity/Club.php | 120 +++++++++++++ Entity/ClubRequest.php | 75 -------- Pub/Controller/Club.php | 164 +++++++++++++++++- Service/Club/ApproverService.php | 64 +++++++ Service/Club/CreatorService.php | 99 +++++++++++ Service/Club/DeleterService.php | 40 +++++ Service/Club/EditorService.php | 73 ++++++++ Service/Club/ModeratorService.php | 106 +++++++++++ Setup.php | 17 +- XF/Entity/Forum.php | 22 +++ ...m_RomhackPlaza-Master-XF-Entity-Forum.json | 6 + _output/class_extensions/_metadata.json | 3 + _output/content_type_fields/_metadata.json | 8 +- .../club-approval_queue_handler_class.json | 5 + _output/content_type_fields/club-entity.json | 5 + ..._request-approval_queue_handler_class.json | 5 - .../club_request-entity.json | 5 - _output/extension_hint.php | 1 + _output/navigation/_metadata.json | 40 +++-- _output/navigation/about.json | 2 +- _output/navigation/clubs.json | 13 ++ _output/navigation/community.json | 2 +- _output/navigation/contact_us.json | 2 +- _output/navigation/database.json | 2 +- _output/navigation/discord.json | 2 +- _output/navigation/drafts.json | 13 ++ _output/navigation/forum.json | 2 +- _output/navigation/home.json | 2 +- _output/navigation/learn_romhacking.json | 2 +- _output/navigation/legal_pages.json | 2 +- _output/navigation/members.json | 2 +- _output/navigation/pages.json | 2 +- _output/navigation/rom_checker.json | 2 +- _output/navigation/rom_hasher.json | 2 +- _output/navigation/rom_patcher.json | 2 +- _output/navigation/submissions_queue.json | 2 +- _output/navigation/tools.json | 2 +- _output/navigation/website.json | 2 +- _output/phrases/_metadata.json | 12 ++ _output/phrases/nav.clubs.txt | 1 + _output/phrases/nav.drafts.txt | 1 + _output/routes/_metadata.json | 5 +- _output/routes/api_threads_undelete.json | 11 ++ _output/routes/public_clubs_.json | 2 +- _output/template_modifications/_metadata.json | 11 ++ .../public/rhpz_above_thread_list_clubs.json | 9 + .../rhpz_above_thread_list_clubs_buttons.json | 9 + ...hpz_category_view_clubs_submit_button.json | 9 + _output/templates/_metadata.json | 14 +- .../public/approval_item_club_request.html | 2 +- .../templates/public/club_delete_confirm.html | 13 ++ _output/templates/public/club_edit_form.html | 72 ++++++++ .../templates/public/club_request_form.html | 1 + 55 files changed, 995 insertions(+), 163 deletions(-) create mode 100644 Api/Controller/ThreadController.php rename ApprovalQueue/{ClubRequest.php => Club.php} (65%) create mode 100644 Entity/Club.php delete mode 100644 Entity/ClubRequest.php create mode 100644 Service/Club/ApproverService.php create mode 100644 Service/Club/CreatorService.php create mode 100644 Service/Club/DeleterService.php create mode 100644 Service/Club/EditorService.php create mode 100644 Service/Club/ModeratorService.php create mode 100644 XF/Entity/Forum.php create mode 100644 _output/class_extensions/XF-Entity-Forum_RomhackPlaza-Master-XF-Entity-Forum.json create mode 100644 _output/content_type_fields/club-approval_queue_handler_class.json create mode 100644 _output/content_type_fields/club-entity.json delete mode 100644 _output/content_type_fields/club_request-approval_queue_handler_class.json delete mode 100644 _output/content_type_fields/club_request-entity.json create mode 100644 _output/navigation/clubs.json create mode 100644 _output/navigation/drafts.json create mode 100644 _output/phrases/nav.clubs.txt create mode 100644 _output/phrases/nav.drafts.txt create mode 100644 _output/routes/api_threads_undelete.json create mode 100644 _output/template_modifications/_metadata.json create mode 100644 _output/template_modifications/public/rhpz_above_thread_list_clubs.json create mode 100644 _output/template_modifications/public/rhpz_above_thread_list_clubs_buttons.json create mode 100644 _output/template_modifications/public/rhpz_category_view_clubs_submit_button.json create mode 100644 _output/templates/public/club_delete_confirm.html create mode 100644 _output/templates/public/club_edit_form.html diff --git a/Api/Controller/ThreadController.php b/Api/Controller/ThreadController.php new file mode 100644 index 0000000..ecde159 --- /dev/null +++ b/Api/Controller/ThreadController.php @@ -0,0 +1,33 @@ +assertApiScope('thread:write'); + + /** @var Thread $thread */ + $thread = $this->assertRecordExists('XF:Thread', $params->thread_id, ['FirstPost'] ); + if( $thread->discussion_state !== 'deleted' ) + return $this->error("This thread is not deleted.", 'not_deleted' ); + + if(!$thread->canUndelete($error)){ + return $this->noPermission($error); + } + + $thread->discussion_state = 'visible'; + $thread->save(); + + return $this->apiSuccess([ + 'thread' => $thread->toApiResult() + ]); + + } +} \ No newline at end of file diff --git a/ApprovalQueue/ClubRequest.php b/ApprovalQueue/Club.php similarity index 65% rename from ApprovalQueue/ClubRequest.php rename to ApprovalQueue/Club.php index 97c7d2b..ba859bb 100644 --- a/ApprovalQueue/ClubRequest.php +++ b/ApprovalQueue/Club.php @@ -5,7 +5,7 @@ namespace RomhackPlaza\Master\ApprovalQueue; use XF\ApprovalQueue\AbstractHandler; use XF\Mvc\Entity\Entity; -class ClubRequest extends AbstractHandler +class Club extends AbstractHandler { protected function canViewContent(Entity $content, &$error = null) @@ -23,15 +23,15 @@ class ClubRequest extends AbstractHandler return ['User']; } - public function actionApprove(\RomhackPlaza\Master\Entity\ClubRequest $clubRequest) + public function actionApprove(\RomhackPlaza\Master\Entity\Club $club) { - $clubRequest->request_state = 'visible'; - $clubRequest->save(); + $club->club_state = 'visible'; + $club->save(); $node = \XF::em()->create('XF:Node'); $node->node_type_id = 'Forum'; - $node->title = $clubRequest->title; - $node->description = $clubRequest->description; + $node->title = $club->title; + $node->description = $club->description; $node->parent_node_id = \XF::options()->rhpz_club_node_id ?? 0; $node->display_order = 1; $node->save(); @@ -41,7 +41,10 @@ class ClubRequest extends AbstractHandler $forum->allow_posting = true; $forum->save(); - $user = $clubRequest->User; + $club->node_id = $node->node_id; + $club->save(); + + $user = $club->User; if ($user) { $modContent = \XF::em()->create('XF:ModeratorContent'); @@ -54,26 +57,16 @@ class ClubRequest extends AbstractHandler $permissionUpdater->setContent('node', $node->node_id); $permissionUpdater->setUser($user); - $permissionUpdater->updatePermissions([ - 'forum' => [ - 'editAnyPost' => 'content_allow', - 'deleteAnyPost' => 'content_allow', - 'deleteAnyThread' => 'content_allow', - 'inlineMod' => 'content_allow', - 'lockUnlockThread' => 'content_allow', - 'stickUnstickThread' => 'content_allow' - ] - ]); + $permissionUpdater->updatePermissions(\RomhackPlaza\Master\Entity\Club::MOD_PERMISSIONS); - // D. Reconstruction des permissions \XF::app()->jobManager()->enqueueUnique('permissionRebuild', 'XF:PermissionRebuild'); } } - public function actionReject(\RomhackPlaza\Master\Entity\ClubRequest $clubRequest) + public function actionReject(\RomhackPlaza\Master\Entity\Club $club) { - $clubRequest->request_state = 'rejected'; - $clubRequest->save(); + $club->club_state = 'rejected'; + $club->save(); } public function getTemplateName() diff --git a/Entity/Club.php b/Entity/Club.php new file mode 100644 index 0000000..d6a090a --- /dev/null +++ b/Entity/Club.php @@ -0,0 +1,120 @@ + [ + 'editAnyPost' => 'content_allow', + 'deleteAnyPost' => 'content_allow', + 'deleteAnyThread' => 'content_allow', + 'inlineMod' => 'content_allow', + 'lockUnlockThread' => 'content_allow', + 'stickUnstickThread' => 'content_allow' + ] + ]; + + public static function getStructure(Structure $structure): Structure + { + $structure->table = 'xf_club'; + $structure->shortName = 'RomhackPlaza\Master:Club'; + $structure->primaryKey = 'club_id'; + $structure->columns = [ + 'club_id' => ['type' => self::UINT, 'autoIncrement' => true], + 'node_id' => ['type' => self::UINT, 'default' => 0], + 'user_id' => ['type' => self::UINT, 'required' => true], + 'title' => ['type' => self::STR, 'maxLength' => 100, 'required' => true], + 'description' => ['type' => self::STR, 'required' => true], + 'club_state' => ['type' => self::STR, 'default' => 'moderated', + 'allowedValues' => ['visible', 'moderated', 'rejected'] + ], + 'club_creation_date' => ['type' => self::UINT, 'default' => \XF::$time], + 'banner_date' => ['type' => self::UINT, 'default' => 0], + ]; + $structure->relations = [ + 'User' => [ + 'entity' => 'XF:User', + 'type' => self::TO_ONE, + 'conditions' => 'user_id', + 'primary' => true + ], + 'Forum' => [ + 'entity' => 'XF:Forum', + 'type' => self::TO_ONE, + 'conditions' => 'node_id', + 'primary' => true + ] + ]; + + return $structure; + } + + public function getBannerUrl(): ?string + { + if( !$this->banner_date ) + return null; + + return \XF::app()->applyExternalDataUrl("club_banners/{$this->club_id}.jpg?{$this->banner_date}"); + } + + protected function _postSave() + { + if( $this->isInsert() && $this->club_state == 'moderated' ){ + $this->inQueue(); + } else if( $this->isUpdate() && $this->isChanged('club_state') ){ + if( $this->club_state === 'moderated' ){ + $this->inQueue(); + } else { + $this->removeQueue(); + } + } + } + + protected function _postDelete() + { + if( $this->club_state === 'moderated' ){ + $this->removeQueue(); + } + } + + protected function inQueue() + { + $queue = $this->em()->find('XF:ApprovalQueue', ['club', $this->club_id ] ); + if( !$queue ) + { + /** @var ApprovalQueue $newQueue */ + $newQueue = $this->em()->create('XF:ApprovalQueue'); + $newQueue->content_type = 'club'; + $newQueue->content_id = $this->club_id; + $newQueue->save(); + } + } + + protected function removeQueue() + { + $queue = $this->em()->find('XF:ApprovalQueue', ['club', $this->club_id ] ); + if( $queue ) + $queue->delete(); + } +} \ No newline at end of file diff --git a/Entity/ClubRequest.php b/Entity/ClubRequest.php deleted file mode 100644 index c0754b0..0000000 --- a/Entity/ClubRequest.php +++ /dev/null @@ -1,75 +0,0 @@ -table = 'xf_club_request'; - $structure->shortName = 'RomhackPlaza\Master:ClubRequest'; - $structure->primaryKey = 'request_id'; - $structure->columns = [ - 'request_id' => ['type' => self::UINT, 'autoIncrement' => true], - 'user_id' => ['type' => self::UINT, 'required' => true], - 'title' => ['type' => self::STR, 'maxLength' => 100, 'required' => true], - 'description' => ['type' => self::STR, 'required' => true], - 'request_state' => ['type' => self::STR, 'default' => 'moderated', - 'allowedValues' => ['visible', 'moderated', 'rejected'] - ], - 'request_date' => ['type' => self::UINT, 'default' => \XF::$time] - ]; - $structure->relations = [ - 'User' => [ - 'entity' => 'XF:User', - 'type' => self::TO_ONE, - 'conditions' => 'user_id', - 'primary' => true - ] - ]; - - return $structure; - } - - protected function _postSave() - { - if( $this->isInsert() && $this->request_state == 'moderated' ){ - $this->inQueue(); - } else if( $this->isUpdate() && $this->isChanged('request_state') ){ - if( $this->request_state === 'moderated' ){ - $this->inQueue(); - } else { - $this->removeQueue(); - } - } - } - - protected function _postDelete() - { - if( $this->request_state === 'moderated' ){ - $this->removeQueue(); - } - } - - protected function inQueue() - { - $queue = $this->em()->find('XF:ApprovalQueue', ['club_request', $this->request_id ] ); - if( !$queue ) - { - $newQueue = $this->em()->create('XF:ApprovalQueue'); - $newQueue->content_type = 'club_request'; - $newQueue->content_id = $this->request_id; - $newQueue->save(); - } - } - - protected function removeQueue() - { - $queue = $this->em()->find('XF:ApprovalQueue', ['club_request', $this->request_id ] ); - if( $queue ) - $queue->delete(); - } -} \ No newline at end of file diff --git a/Pub/Controller/Club.php b/Pub/Controller/Club.php index 747c2c3..44e6569 100644 --- a/Pub/Controller/Club.php +++ b/Pub/Controller/Club.php @@ -2,12 +2,23 @@ namespace RomhackPlaza\Master\Pub\Controller; +use PhpParser\Node\Param; +use RomhackPlaza\Master\Service\Club\CreatorService; +use RomhackPlaza\Master\Service\Club\DeleterService; +use RomhackPlaza\Master\Service\Club\EditorService; +use RomhackPlaza\Master\Service\Club\ModeratorService; use XF\Mvc\ParameterBag; use XF\Pub\Controller\AbstractController; +use XF\Util\File; class Club extends AbstractController { + public function actionIndex(){ + $clubsForum = \XF::options()->rhpz_club_node_id; + return $this->redirect('categories/.' . $clubsForum ); + } + public function actionSubmit(ParameterBag $params) { $this->assertRegistrationRequired(); @@ -15,18 +26,157 @@ class Club extends AbstractController return $this->view('RomhackPlaza\Master:Club\Request', 'club_request_form'); } + public function actionEdit(ParameterBag $params) + { + $this->assertRegistrationRequired(); + + if( !$params->club_id ) + $this->notFound("Club not found"); + + /** @var \RomhackPlaza\Master\Entity\Club $club */ + $club = $this->assertRecordExists( 'RomhackPlaza\Master:Club', $params->club_id ); + if( $club->user_id !== \XF::visitor()->user_id && !\XF::visitor()->hasAdminPermission('node') ){ + $this->noPermission(); + } + + $mods = []; + $modsCount = 0; + + if( $club->node_id ){ + $mods = $this->finder('XF:ModeratorContent') + ->where('content_type', 'node') + ->where('content_id', $club->node_id) + ->with('User') + ->fetch(); + foreach( $mods as $m ){ + if( $m->user_id !== $club->user_id ){ + $modsCount++; + } + } + } + + return $this->view('RomhackPlaza\Master:Club\Edit', 'club_edit_form', [ 'club' => $club, 'moderators' => $mods, 'subModCount' => $modsCount ] ); + } + public function actionSave(ParameterBag $params) { $this->assertRegistrationRequired(); $this->assertPostOnly(); - $entity = $this->em()->create('RomhackPlaza\Master:ClubRequest'); - $entity->user_id = \XF::visitor()->user_id; - $entity->title = $this->filter('title','str'); - $entity->description = $this->filter('description','str'); - $entity->request_state = 'moderated'; - $entity->save(); + $isEdit = (bool) $params->club_id; + if( $isEdit ){ + $club = $this->assertRecordExists('RomhackPlaza\Master:Club', $params->club_id ); + if( $club->user_id !== \XF::visitor()->user_id && !\XF::visitor()->hasAdminPermission('node') ){ + $this->noPermission(); + } - return $this->redirect($this->buildLink('clubs'), "Your club creation request has been submitted and is awaiting approval by a staff member."); + /** @var EditorService $editor */ + $editor = $this->service('RomhackPlaza\Master:Club\Editor', $club); + $editor->setContent($this->filter('title','str'), $this->filter('description','str')); + $editor->setBannerUpload($this->request->getFile('upload_banner', false, false) ); + + if( !$editor->validate($errors) ){ + return $this->error($errors); + } + + $editor->save(); + + return $this->redirect( $this->buildLink('clubs'), "Changes saved successfully" ); + + } else { + + /** @var CreatorService $creator */ + $creator = $this->service('RomhackPlaza\Master:Club\Creator', \XF::visitor()); + $creator->setContent($this->filter('title','str'), $this->filter('description','str')); + $creator->setBannerUpload($this->request->getFile('upload_banner', false, false)); + + if( !$creator->validate($errors) ){ + return $this->error($errors); + } + $creator->save(); + return $this->redirect( $this->buildLink('clubs'), "Your club creation request has been submitted and is awaiting approval by a staff member." ); + } } + + public function actionDelete(ParameterBag $params) + { + $this->assertRegistrationRequired(); + + /** @var \RomhackPlaza\Master\Entity\Club $club */ + $club = $this->assertRecordExists('RomhackPlaza\Master:Club', $params->club_id); + if( $club->user_id !== \XF::visitor()->user_id && !\XF::visitor()->hasAdminPermission('node') ){ + $this->noPermission(); + } + + if( $this->isPost() ){ + /** @var DeleterService $deleter */ + $deleter = $this->service('RomhackPlaza\Master:Club\Deleter', $club); + $deleter->delete(); + + return $this->redirect( $this->buildLink('clubs'), "Club deleted successfully." ); + } + + return $this->view('RomhackPlaza\Master:Club\Delete', 'club_delete_confirm', [ 'club' => $club ] ); + } + + public function actionAddModerator(ParameterBag $params) + { + $this->assertRegistrationRequired(); + $this->assertPostOnly(); + + /** @var \RomhackPlaza\Master\Entity\Club $club */ + $club = $this->assertRecordExists('RomhackPlaza\Master:Club', $params->club_id); + if( $club->user_id !== \XF::visitor()->user_id && !\XF::visitor()->hasAdminPermission('node') ){ + return $this->noPermission(); + } + + $username = $this->filter('username','str'); + $user = $this->em()->findOne('XF:User', ['username' => $username]); + + if( !$user ){ + return $this->error("This user doesn't exist"); + } + + /** @var ModeratorService $modManage */ + $modManage = \XF::app()->service('RomhackPlaza\Master:Club\Moderator', $club, $user ); + $error = ""; + $modManage->addModerator( $error ); + + if( $error && $error !== "" ){ + return $this->error($error); + } + + return $this->redirect( $this->buildLink('clubs/edit', $club), "Moderator added successfully." ); + } + + public function actionRemoveModerator(ParameterBag $params) + { + $this->assertRegistrationRequired(); + $this->assertPostOnly(); + + /** @var \RomhackPlaza\Master\Entity\Club $club */ + $club = $this->assertRecordExists('RomhackPlaza\Master:Club', $params->club_id); + if( $club->user_id !== \XF::visitor()->user_id && !\XF::visitor()->hasAdminPermission('node') ){ + $this->noPermission(); + } + + $userId = $this->filter('user_id','uint'); + $user = $this->em()->findOne('XF:User', ['user_id' => $userId]); + + if( !$user ){ + $this->error("This user doesn't exist"); + } + + /** @var ModeratorService $modManage */ + $modManage = \XF::app()->service('RomhackPlaza\Master:Club\Moderator', $club, $user ); + $error = ""; + $modManage->deleteModerator( $error ); + + if( $error && $error !== "" ){ + return $this->error($error); + } + + return $this->redirect( $this->buildLink('clubs/edit', $club), "Moderator deleted successfully." ); + } + } \ No newline at end of file diff --git a/Service/Club/ApproverService.php b/Service/Club/ApproverService.php new file mode 100644 index 0000000..c44f5f1 --- /dev/null +++ b/Service/Club/ApproverService.php @@ -0,0 +1,64 @@ +club = $club; + } + + public function approve(): bool + { + if( $this->club->club_state !== 'moderated' ) { + return false; + } + + $this->club->club_state = 'visible'; + $this->club->save(); + + /** @var Node $node */ + $node = $this->em()->create('XF:Node'); + + $node->node_type_id = 'Forum'; + $node->title = $this->club->title; + $node->description = $this->club->description; + $node->parent_node_id = \XF::options()->rhpz_club_node_id ?? 0; + $node->display_order = 1; + $node->save(); + + /** @var Forum $forum */ + $forum = $this->em()->create('XF:Forum'); + $forum->node_id = $node->node_id; + $forum->allow_posting = true; + $forum->save(); + + $this->club->node_id = $node->node_id; + $this->club->save(); + + $user = $this->club->User; + if( $user ){ + /** @var ModeratorService $modManage */ + $modManage = \XF::app()->service('RomhackPlaza\Master:Club\Moderator', $this->club, $user ); + $modManage->addModerator( $error ); + } + + return true; + } +} \ No newline at end of file diff --git a/Service/Club/CreatorService.php b/Service/Club/CreatorService.php new file mode 100644 index 0000000..2c3e772 --- /dev/null +++ b/Service/Club/CreatorService.php @@ -0,0 +1,99 @@ +club = $this->em()->create('RomhackPlaza\Master:Club'); + $this->setUser($creator); + $this->setupDefaults(); + } + + protected function setupDefaults() + { + $this->club->club_state = 'moderated'; + } + + public function getClub() + { + return $this->club; + } + + public function getUser() + { + return $this->user; + } + + public function setUser(User $user) + { + $this->user = $user; + $this->club->user_id = $this->user->user_id; + } + + public function setContent(string $title, string $description ) + { + $this->club->title = $title; + $this->club->description = $description; + } + + public function setBannerUpload(?Upload $upload = null) + { + if ($upload) { + $upload->requireImage(); + if($upload->isValid()){ + $this->bannerUpload = $upload; + } + } + } + + protected function _validate() + { + $this->club->preSave(); + return $this->club->getErrors(); + } + + protected function _save() + { + $this->club->save(); + + if( $this->bannerUpload ){ + $path = 'data://club_banners/' . $this->club->club_id . '.jpg'; + if( File::copyFileToAbstractedPath($this->bannerUpload->getFileWrapper()->getFilePath(), $path) ){ + $this->club->banner_date = \XF::$time; + $this->club->save(); + } + } + + return $this->club; + } +} \ No newline at end of file diff --git a/Service/Club/DeleterService.php b/Service/Club/DeleterService.php new file mode 100644 index 0000000..045c668 --- /dev/null +++ b/Service/Club/DeleterService.php @@ -0,0 +1,40 @@ +club = $club; + } + + public function delete() + { + if( $this->club->Forum && $this->club->Forum->Node ){ + $this->club->Forum->Node->delete(); + } + + $path = 'data://club_banners/' . $this->club->club_id . '.jpg'; + File::deleteFromAbstractedPath($path); + + $this->club->delete(); + } +} \ No newline at end of file diff --git a/Service/Club/EditorService.php b/Service/Club/EditorService.php new file mode 100644 index 0000000..bccc35f --- /dev/null +++ b/Service/Club/EditorService.php @@ -0,0 +1,73 @@ +club = $club; + } + + public function setContent(string $title, string $description) + { + $this->club->title = $title; + $this->club->description = $description; + } + + public function setBannerUpload(?Upload $upload = null) + { + if( $upload ){ + $upload->requireImage(); + if( $upload->isValid() ){ + $path = 'data://club_banners/' . $this->club->club_id . '.jpg'; + if(File::copyFileToAbstractedPath($upload->getFileWrapper()->getFilePath(), $path)){ + $this->club->banner_date = \XF::$time; + } + } + } + } + + protected function syncForumNode() + { + if( $this->club->Forum && $this->club->Forum->Node ) + { + $node = $this->club->Forum->Node; + $node->title = $this->club->title; + $node->description = $this->club->description; + $node->save(); + } + } + + protected function _validate() + { + $this->club->preSave(); + return $this->club->getErrors(); + } + + protected function _save() + { + $this->club->save(); + $this->syncForumNode(); + + return $this->club; + } +} \ No newline at end of file diff --git a/Service/Club/ModeratorService.php b/Service/Club/ModeratorService.php new file mode 100644 index 0000000..e8be63e --- /dev/null +++ b/Service/Club/ModeratorService.php @@ -0,0 +1,106 @@ +club = $club; + $this->user = $moderator; + } + + protected function countMods( int $nodeId, int $excludeUserId = 0 ) + { + return $this->finder('XF:ModeratorContent') + ->where('content_type', 'node') + ->where('content_id', $nodeId) + ->where('user_id', '!=', $excludeUserId) + ->total(); + } + + public function addModerator( string &$error ): bool + { + if( !$this->club->Forum || !$this->club->Forum->Node ) { + $error = "No node linked to this club."; + return false; + } + + if( $this->countMods( $this->club->node_id, $this->club->user_id ) > self::MAX_MODS ) { + $error = "The limit of 5 moderators has been reached."; + return false; + } + + $existingMod = $this->em()->findOne('XF:ModeratorContent', [ + 'content_type' => 'node', + 'content_id' => $this->club->node_id, + 'user_id' => $this->user->user_id + ]); + if( $existingMod ){ + $error = "This user is already a moderator."; + return false; + } + + $modContent = $this->em()->create('XF:ModeratorContent'); + $modContent->content_type = 'node'; + $modContent->content_id = $this->club->node_id; + $modContent->user_id = $this->user->user_id; + $modContent->save(); + + $permissionUpdater = \XF::app()->service('XF:UpdatePermissions'); + $permissionUpdater->setContent('node', $this->club->node_id); + $permissionUpdater->setUser($this->user); + $permissionUpdater->updatePermissions(Club::MOD_PERMISSIONS); + + \XF::app()->jobManager()->enqueueUnique('permissionRebuild', 'XF:PermissionRebuild'); + return true; + } + + public function deleteModerator( string &$error ): bool + { + if( !$this->club->Forum || !$this->club->Forum->Node ) { + $error = "No node linked to this club."; + return false; + } + + if( $this->user->user_id === $this->club->user_id ){ + $error = "You cannot delete yourself."; + return false; + } + + $mod = $this->em()->findOne('XF:ModeratorContent', [ + 'content_type' => 'node', + 'content_id' => $this->club->node_id, + 'user_id' => $this->user->user_id + ]); + + if( $mod ){ + $mod->delete(); + + \XF::db()->delete('xf_permission_entry_content', 'content_type = ? AND content_id = ? AND user_id = ?', ['node', $this->club->node_id, $this->user->user_id]); + + \XF::app()->jobManager()->enqueueUnique('permissionRebuild', 'XF:PermissionRebuild'); + } + + return true; + } +} \ No newline at end of file diff --git a/Setup.php b/Setup.php index 83d1c76..3e075ac 100644 --- a/Setup.php +++ b/Setup.php @@ -25,19 +25,22 @@ class Setup extends AbstractSetup } /** - * Create club request table. + * Create club table. * @return void */ public function installStep2(): void { - $this->schemaManager()->createTable('xf_club_request', function(Create $table){ - $table->addColumn('request_id', 'int')->autoIncrement(); + $this->schemaManager()->createTable('xf_club', function(Create $table){ + $table->addColumn('club_id', 'int')->autoIncrement(); + $table->addColumn( 'node_id', 'int' ); $table->addColumn('user_id', 'int'); $table->addColumn('title', 'varchar', 100); $table->addColumn('description', 'text'); - $table->addColumn('request_state', 'enum')->values(['visible','moderated','rejected'])->setDefault('moderated'); - $table->addColumn('request_date','int'); - $table->addKey('request_state'); + $table->addColumn('club_state', 'enum')->values(['visible','moderated','rejected'])->setDefault('moderated'); + $table->addColumn('club_creation_date','int'); + $table->addColumn('banner_date', 'int')->setDefault(0); + $table->addPrimaryKey('club_id'); + $table->addKey('club_state'); }); } @@ -50,6 +53,6 @@ class Setup extends AbstractSetup public function uninstallStep2(): void { - $this->schemaManager()->dropTable('xf_club_request'); + $this->schemaManager()->dropTable('xf_club'); } } \ No newline at end of file diff --git a/XF/Entity/Forum.php b/XF/Entity/Forum.php new file mode 100644 index 0000000..7654a5d --- /dev/null +++ b/XF/Entity/Forum.php @@ -0,0 +1,22 @@ +relations['Club'] = [ + 'entity' => 'RomhackPlaza\Master:Club', + 'type' => self::TO_ONE, + 'conditions' => 'node_id', + 'primary' => false + ]; + + return $structure; + } +} \ No newline at end of file diff --git a/_output/class_extensions/XF-Entity-Forum_RomhackPlaza-Master-XF-Entity-Forum.json b/_output/class_extensions/XF-Entity-Forum_RomhackPlaza-Master-XF-Entity-Forum.json new file mode 100644 index 0000000..def4609 --- /dev/null +++ b/_output/class_extensions/XF-Entity-Forum_RomhackPlaza-Master-XF-Entity-Forum.json @@ -0,0 +1,6 @@ +{ + "from_class": "XF\\Entity\\Forum", + "to_class": "RomhackPlaza\\Master\\XF\\Entity\\Forum", + "execute_order": 10, + "active": true +} \ No newline at end of file diff --git a/_output/class_extensions/_metadata.json b/_output/class_extensions/_metadata.json index 96c4b77..12689a8 100644 --- a/_output/class_extensions/_metadata.json +++ b/_output/class_extensions/_metadata.json @@ -1,4 +1,7 @@ { + "XF-Entity-Forum_RomhackPlaza-Master-XF-Entity-Forum.json": { + "hash": "c7747b6ea6bd924d2d02e82917ff0df3" + }, "XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json": { "hash": "811593d6f012a53b9fa2ced871de96a9" } diff --git a/_output/content_type_fields/_metadata.json b/_output/content_type_fields/_metadata.json index 102b3e5..8381f54 100644 --- a/_output/content_type_fields/_metadata.json +++ b/_output/content_type_fields/_metadata.json @@ -1,9 +1,9 @@ { - "club_request-approval_queue_handler_class.json": { - "hash": "e46546c5b569b04e7ad740a672d217cd" + "club-approval_queue_handler_class.json": { + "hash": "468464999ab50b9de400a6eae27625ac" }, - "club_request-entity.json": { - "hash": "547d2af8708a4c569b3b09fdd9308880" + "club-entity.json": { + "hash": "ed572323131987e295051165e4ec3c5e" }, "romhackplaza_entry-entity.json": { "hash": "8686ffd261eb8c1698a3ec6e31118f02" diff --git a/_output/content_type_fields/club-approval_queue_handler_class.json b/_output/content_type_fields/club-approval_queue_handler_class.json new file mode 100644 index 0000000..fc196f3 --- /dev/null +++ b/_output/content_type_fields/club-approval_queue_handler_class.json @@ -0,0 +1,5 @@ +{ + "content_type": "club", + "field_name": "approval_queue_handler_class", + "field_value": "RomhackPlaza\\Master\\ApprovalQueue\\Club" +} \ No newline at end of file diff --git a/_output/content_type_fields/club-entity.json b/_output/content_type_fields/club-entity.json new file mode 100644 index 0000000..0fb334d --- /dev/null +++ b/_output/content_type_fields/club-entity.json @@ -0,0 +1,5 @@ +{ + "content_type": "club", + "field_name": "entity", + "field_value": "RomhackPlaza\\Master\\Entity\\Club" +} \ No newline at end of file diff --git a/_output/content_type_fields/club_request-approval_queue_handler_class.json b/_output/content_type_fields/club_request-approval_queue_handler_class.json deleted file mode 100644 index 3aaaaf2..0000000 --- a/_output/content_type_fields/club_request-approval_queue_handler_class.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "content_type": "club_request", - "field_name": "approval_queue_handler_class", - "field_value": "RomhackPlaza\\Master\\ApprovalQueue\\ClubRequest" -} \ No newline at end of file diff --git a/_output/content_type_fields/club_request-entity.json b/_output/content_type_fields/club_request-entity.json deleted file mode 100644 index 17f5bcf..0000000 --- a/_output/content_type_fields/club_request-entity.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "content_type": "club_request", - "field_name": "entity", - "field_value": "RomhackPlaza\\Master\\Entity\\ClubRequest" -} \ No newline at end of file diff --git a/_output/extension_hint.php b/_output/extension_hint.php index ae897a0..f542957 100644 --- a/_output/extension_hint.php +++ b/_output/extension_hint.php @@ -10,5 +10,6 @@ namespace RomhackPlaza\Master\XF\Entity { + class XFCP_Forum extends \XF\Entity\Forum {} class XFCP_User extends \XF\Entity\User {} } diff --git a/_output/navigation/_metadata.json b/_output/navigation/_metadata.json index b8b2f6d..087d264 100644 --- a/_output/navigation/_metadata.json +++ b/_output/navigation/_metadata.json @@ -1,53 +1,59 @@ { "about.json": { - "hash": "96e3aa134dd14f5d43ca9ca1d5c55113" + "hash": "362cdca71eb4d21d7b9290ffc8f0df57" + }, + "clubs.json": { + "hash": "e7ddced6269072f7db774f09424d671c" }, "community.json": { - "hash": "bddec05ee1acb9cb82ed72155bdd7817" + "hash": "b3b5bb7146a8eb66e2830c48c4714456" }, "contact_us.json": { - "hash": "05d205aee6ac1db9d9ad0f68bdd4f7c2" + "hash": "59453e1b06c296c777987d0fae0eb3a5" }, "database.json": { - "hash": "7b42b608fad8ab23417a8cc3fcd331c2" + "hash": "604cabbdf4fb4fd941dc6123eb119165" }, "discord.json": { - "hash": "d20860e95b3f4a96622733ef9ef4cfa0" + "hash": "37b3a139a26e30bd558de47b9e364d41" + }, + "drafts.json": { + "hash": "bea14e944290aeb07659374fa487d61c" }, "forum.json": { - "hash": "4a2e65ba6b553ed68dd5b6f7fd6d71d8" + "hash": "ca20fad278aeab93ccbc3c3a20a743d2" }, "home.json": { - "hash": "6bf83f1a17528a3c075addfbc8fca830" + "hash": "4f55ee2e4a49e82c18e9beab428ab0ee" }, "learn_romhacking.json": { - "hash": "dc98809d9e310f450123400bf106d2e5" + "hash": "3da66fadac2c1aa805e639d727e36223" }, "legal_pages.json": { - "hash": "d379ad33a85a4387888d90fd75380b8a" + "hash": "34ae35915e620f1f0b5d88dcd25a5b59" }, "members.json": { - "hash": "d625548b0c17df789d595691931732a3" + "hash": "cad1568d161bea1a7dd1f286b8788e2d" }, "pages.json": { - "hash": "fe3fa7929ab20e981dd2f03d6d81f5d2" + "hash": "8d75bf99b2fb6528f84433f4519d4da3" }, "rom_checker.json": { - "hash": "d23131981318ff9afa142b6512225cc3" + "hash": "c9349db6120520e82d02b793a30e67ce" }, "rom_hasher.json": { - "hash": "5f7ab5a76ff0060ac7854ca2c53ea245" + "hash": "e14613a1bd0f1e1fadc084a009801570" }, "rom_patcher.json": { - "hash": "73fab3932646c350da9a40102f650d9d" + "hash": "2a2af404aa6395b02c711867a7287a6f" }, "submissions_queue.json": { - "hash": "84060a775af4419d44c8dc2c083ef447" + "hash": "071c745afd8f28cf9505702496f72a18" }, "tools.json": { - "hash": "0221bb27d36511c5dd1feaf697626778" + "hash": "3d56ca10d6cf3ff772e9ce92d200f2f8" }, "website.json": { - "hash": "e2f7d3d0102894eb09ecb359712d0fed" + "hash": "9ca169f049cffa2cf82f395617e2b897" } } \ No newline at end of file diff --git a/_output/navigation/about.json b/_output/navigation/about.json index 80027db..836d989 100644 --- a/_output/navigation/about.json +++ b/_output/navigation/about.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "pages", - "display_order": 2, + "display_order": 200, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/pages/about", diff --git a/_output/navigation/clubs.json b/_output/navigation/clubs.json new file mode 100644 index 0000000..379bda0 --- /dev/null +++ b/_output/navigation/clubs.json @@ -0,0 +1,13 @@ +{ + "parent_navigation_id": "community", + "display_order": 200, + "navigation_type_id": "basic", + "type_config": { + "link": "{{ link('clubs') }}", + "display_condition": "", + "extra_attributes": { + "icon": "balloon" + } + }, + "enabled": true +} \ No newline at end of file diff --git a/_output/navigation/community.json b/_output/navigation/community.json index 4f4a42b..b968752 100644 --- a/_output/navigation/community.json +++ b/_output/navigation/community.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "", - "display_order": 50, + "display_order": 300, "navigation_type_id": "basic", "type_config": { "link": "", diff --git a/_output/navigation/contact_us.json b/_output/navigation/contact_us.json index 1fcb8d4..035b412 100644 --- a/_output/navigation/contact_us.json +++ b/_output/navigation/contact_us.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "pages", - "display_order": 3, + "display_order": 300, "navigation_type_id": "basic", "type_config": { "link": "{{ link('misc/contact') }}", diff --git a/_output/navigation/database.json b/_output/navigation/database.json index e9bff33..5b1c83a 100644 --- a/_output/navigation/database.json +++ b/_output/navigation/database.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "website", - "display_order": 2, + "display_order": 200, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/database", diff --git a/_output/navigation/discord.json b/_output/navigation/discord.json index b04c7a6..4a141f0 100644 --- a/_output/navigation/discord.json +++ b/_output/navigation/discord.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "community", - "display_order": 2, + "display_order": 300, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/discord", diff --git a/_output/navigation/drafts.json b/_output/navigation/drafts.json new file mode 100644 index 0000000..b039b4c --- /dev/null +++ b/_output/navigation/drafts.json @@ -0,0 +1,13 @@ +{ + "parent_navigation_id": "website", + "display_order": 400, + "navigation_type_id": "basic", + "type_config": { + "link": "{$xf.options.homePageUrl}/my-drafts", + "display_condition": "{$xf.visitor.user_id}", + "extra_attributes": { + "icon": "scissors" + } + }, + "enabled": true +} \ No newline at end of file diff --git a/_output/navigation/forum.json b/_output/navigation/forum.json index 8ae83fb..0552b5f 100644 --- a/_output/navigation/forum.json +++ b/_output/navigation/forum.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "community", - "display_order": 1, + "display_order": 100, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.boardUrl}", diff --git a/_output/navigation/home.json b/_output/navigation/home.json index da3bf4d..3527312 100644 --- a/_output/navigation/home.json +++ b/_output/navigation/home.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "website", - "display_order": 1, + "display_order": 100, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}", diff --git a/_output/navigation/learn_romhacking.json b/_output/navigation/learn_romhacking.json index b940efe..b91b196 100644 --- a/_output/navigation/learn_romhacking.json +++ b/_output/navigation/learn_romhacking.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "pages", - "display_order": 1, + "display_order": 100, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/pages/learn", diff --git a/_output/navigation/legal_pages.json b/_output/navigation/legal_pages.json index 10b8bbf..9ce4d49 100644 --- a/_output/navigation/legal_pages.json +++ b/_output/navigation/legal_pages.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "pages", - "display_order": 4, + "display_order": 400, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/pages/legal-pages", diff --git a/_output/navigation/members.json b/_output/navigation/members.json index 7963fb6..7bc2626 100644 --- a/_output/navigation/members.json +++ b/_output/navigation/members.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "community", - "display_order": 3, + "display_order": 400, "navigation_type_id": "basic", "type_config": { "link": "{{ link('members') }}", diff --git a/_output/navigation/pages.json b/_output/navigation/pages.json index bb72a97..cdd5606 100644 --- a/_output/navigation/pages.json +++ b/_output/navigation/pages.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "", - "display_order": 150, + "display_order": 500, "navigation_type_id": "basic", "type_config": { "link": "", diff --git a/_output/navigation/rom_checker.json b/_output/navigation/rom_checker.json index d186479..da65b88 100644 --- a/_output/navigation/rom_checker.json +++ b/_output/navigation/rom_checker.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "tools", - "display_order": 3, + "display_order": 300, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/tools/rom-checker", diff --git a/_output/navigation/rom_hasher.json b/_output/navigation/rom_hasher.json index 7f1a7c9..cb7554f 100644 --- a/_output/navigation/rom_hasher.json +++ b/_output/navigation/rom_hasher.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "tools", - "display_order": 2, + "display_order": 200, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/tools/rom-hasher", diff --git a/_output/navigation/rom_patcher.json b/_output/navigation/rom_patcher.json index e35e6e1..680ba5d 100644 --- a/_output/navigation/rom_patcher.json +++ b/_output/navigation/rom_patcher.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "tools", - "display_order": 1, + "display_order": 100, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/tools/rom-patcher", diff --git a/_output/navigation/submissions_queue.json b/_output/navigation/submissions_queue.json index 9439978..f5f7fb4 100644 --- a/_output/navigation/submissions_queue.json +++ b/_output/navigation/submissions_queue.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "website", - "display_order": 3, + "display_order": 300, "navigation_type_id": "basic", "type_config": { "link": "{$xf.options.homePageUrl}/queue", diff --git a/_output/navigation/tools.json b/_output/navigation/tools.json index 123cd59..388d844 100644 --- a/_output/navigation/tools.json +++ b/_output/navigation/tools.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "", - "display_order": 100, + "display_order": 400, "navigation_type_id": "basic", "type_config": { "link": "", diff --git a/_output/navigation/website.json b/_output/navigation/website.json index 00ea74b..fcf7af0 100644 --- a/_output/navigation/website.json +++ b/_output/navigation/website.json @@ -1,6 +1,6 @@ { "parent_navigation_id": "", - "display_order": 1, + "display_order": 200, "navigation_type_id": "basic", "type_config": { "link": "", diff --git a/_output/phrases/_metadata.json b/_output/phrases/_metadata.json index 7135574..74be088 100644 --- a/_output/phrases/_metadata.json +++ b/_output/phrases/_metadata.json @@ -5,6 +5,12 @@ "version_string": "1.0.0", "hash": "8f7f4c1ce7a4f933663d10543562b096" }, + "nav.clubs.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "bc56e1ae1e30e7123ffc5030f108f2a0" + }, "nav.community.txt": { "global_cache": false, "version_id": 1000000, @@ -29,6 +35,12 @@ "version_string": "1.0.0", "hash": "8f5cc6430613f1c12f36965050bb7197" }, + "nav.drafts.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "bc67af65fab4a8b1848ccedf29c3b733" + }, "nav.forum.txt": { "global_cache": false, "version_id": 1000000, diff --git a/_output/phrases/nav.clubs.txt b/_output/phrases/nav.clubs.txt new file mode 100644 index 0000000..18aaf16 --- /dev/null +++ b/_output/phrases/nav.clubs.txt @@ -0,0 +1 @@ +Clubs \ No newline at end of file diff --git a/_output/phrases/nav.drafts.txt b/_output/phrases/nav.drafts.txt new file mode 100644 index 0000000..c27ba2c --- /dev/null +++ b/_output/phrases/nav.drafts.txt @@ -0,0 +1 @@ +My drafts \ No newline at end of file diff --git a/_output/routes/_metadata.json b/_output/routes/_metadata.json index c3ee973..0c6bcac 100644 --- a/_output/routes/_metadata.json +++ b/_output/routes/_metadata.json @@ -2,8 +2,11 @@ "api_romhackplaza_entry_.json": { "hash": "5f1609f559980b44af09fd85c3b34a30" }, + "api_threads_undelete.json": { + "hash": "3376251e185807693e0fb7dc6dcc9ee0" + }, "public_clubs_.json": { - "hash": "a10d34d7ce33cb577dc85906353d1bb2" + "hash": "4fbb4a364e108ff5b30dfd57692205aa" }, "public_romhackplaza_entry_.json": { "hash": "2c40d7266fcc22a5727830a69af2360c" diff --git a/_output/routes/api_threads_undelete.json b/_output/routes/api_threads_undelete.json new file mode 100644 index 0000000..207ccb2 --- /dev/null +++ b/_output/routes/api_threads_undelete.json @@ -0,0 +1,11 @@ +{ + "route_type": "api", + "route_prefix": "threads", + "sub_name": "undelete", + "format": ":int/undelete", + "build_class": "", + "build_method": "", + "controller": "RomhackPlaza\\Master:Thread", + "context": "", + "action_prefix": "" +} \ No newline at end of file diff --git a/_output/routes/public_clubs_.json b/_output/routes/public_clubs_.json index 1cd0ec9..7efbdae 100644 --- a/_output/routes/public_clubs_.json +++ b/_output/routes/public_clubs_.json @@ -2,7 +2,7 @@ "route_type": "public", "route_prefix": "clubs", "sub_name": "", - "format": "", + "format": ":int/", "build_class": "", "build_method": "", "controller": "RomhackPlaza\\Master:Club", diff --git a/_output/template_modifications/_metadata.json b/_output/template_modifications/_metadata.json new file mode 100644 index 0000000..1a3032e --- /dev/null +++ b/_output/template_modifications/_metadata.json @@ -0,0 +1,11 @@ +{ + "public/rhpz_above_thread_list_clubs.json": { + "hash": "c261ea6e33cf5eb7ab0a7f6fe934de7c" + }, + "public/rhpz_above_thread_list_clubs_buttons.json": { + "hash": "c783001e00f7a63389c9ae988012f5fe" + }, + "public/rhpz_category_view_clubs_submit_button.json": { + "hash": "a24a5a4b130b6198de7ef37610aa1a7d" + } +} \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_above_thread_list_clubs.json b/_output/template_modifications/public/rhpz_above_thread_list_clubs.json new file mode 100644 index 0000000..05e3bd4 --- /dev/null +++ b/_output/template_modifications/public/rhpz_above_thread_list_clubs.json @@ -0,0 +1,9 @@ +{ + "template": "forum_view", + "description": "Add the club banner above the threads list.", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "$0\n\n
\n \n \"Banner\n \n
\n
" +} \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_above_thread_list_clubs_buttons.json b/_output/template_modifications/public/rhpz_above_thread_list_clubs_buttons.json new file mode 100644 index 0000000..b5d3caf --- /dev/null +++ b/_output/template_modifications/public/rhpz_above_thread_list_clubs_buttons.json @@ -0,0 +1,9 @@ +{ + "template": "forum_view", + "description": "Add Owner edit/delete buttons.", + "execution_order": 5, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "$0\n\n
\n
\n Edit\n Delete\n
\n
\n
" +} \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_category_view_clubs_submit_button.json b/_output/template_modifications/public/rhpz_category_view_clubs_submit_button.json new file mode 100644 index 0000000..2cf57ba --- /dev/null +++ b/_output/template_modifications/public/rhpz_category_view_clubs_submit_button.json @@ -0,0 +1,9 @@ +{ + "template": "category_view", + "description": "Add Club Submit button", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "\t\t\t\t\t\t\t", + "replace": "\n\t\n\t\tRequest a club\n\t\n\n$0" +} \ No newline at end of file diff --git a/_output/templates/_metadata.json b/_output/templates/_metadata.json index d25982e..68e17fb 100644 --- a/_output/templates/_metadata.json +++ b/_output/templates/_metadata.json @@ -7,12 +7,22 @@ "public/approval_item_club_request.html": { "version_id": 1000000, "version_string": "1.0.0", - "hash": "39492e4fb48e7aa1622a6bb4371a36f4" + "hash": "da1f9c78c4e33597062258c0bba3cb4d" + }, + "public/club_delete_confirm.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "c84c3878a0aee370e2080427405fe920" + }, + "public/club_edit_form.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d83cbfd477fc14de26b72aed00c866c3" }, "public/club_request_form.html": { "version_id": 1000000, "version_string": "1.0.0", - "hash": "5e1c397d93134aaa7164301d5a3553ce" + "hash": "443b696b5c7ae6bc4b1ef36d170ac7e7" }, "public/report_content_romhackplaza_entry.html": { "version_id": 1000000, diff --git a/_output/templates/public/approval_item_club_request.html b/_output/templates/public/approval_item_club_request.html index ba30adb..b2a55e9 100644 --- a/_output/templates/public/approval_item_club_request.html +++ b/_output/templates/public/approval_item_club_request.html @@ -2,7 +2,7 @@ arg-content="{$content}" arg-user="{$content.User}" arg-messageHtml="{$content.description}" - arg-contentDate="{$content.request_date}" + arg-contentDate="{$content.club_creation_date}" arg-typePhraseHtml="Club Request" arg-headerPhrase="{$content.title}" arg-spamDetails="{$spamDetails}" diff --git a/_output/templates/public/club_delete_confirm.html b/_output/templates/public/club_delete_confirm.html new file mode 100644 index 0000000..ebe8edc --- /dev/null +++ b/_output/templates/public/club_delete_confirm.html @@ -0,0 +1,13 @@ +Delete club : {$club.title} + + +
+
+ + Are you sure you want to delete this club ? {$club.title} ?
+ Deleting this will also delete all threads and posts. +
+
+ +
+
\ No newline at end of file diff --git a/_output/templates/public/club_edit_form.html b/_output/templates/public/club_edit_form.html new file mode 100644 index 0000000..29f6538 --- /dev/null +++ b/_output/templates/public/club_edit_form.html @@ -0,0 +1,72 @@ +
+ +
+ + + + + + + + + + +
+ +
+
+ + + +
+
+

Club Moderators ({$subModCount}/5)

+
+ +
+ +
+
+ {$mod.User.username} + + Owner + +
+
+ + + + Remove + + + - + +
+
+
+
+ +
No moderators for this club.
+
+
+
+
+ +
+ + +

Add a moderator

+
+ +
+ +
+ +
+
+ Limit reached: You have reached the maximum number of 5 moderators for your club. You must remove one before you can add a new one. +
+
+
+
+
\ No newline at end of file diff --git a/_output/templates/public/club_request_form.html b/_output/templates/public/club_request_form.html index 8ecd903..e175484 100644 --- a/_output/templates/public/club_request_form.html +++ b/_output/templates/public/club_request_form.html @@ -5,6 +5,7 @@
+
From 73471162bf224ad3813bdea47c67cc8cd63e9067 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 16 Jun 2026 16:21:43 +0200 Subject: [PATCH 4/9] A lot of things --- Api/Controller/EntryController.php | 20 ++++ ApprovalQueue/Club.php | 2 +- ApprovalQueue/EntryFeaturedRequest.php | 61 +++++++++++++ Entity/EntryFeaturedRequest.php | 91 +++++++++++++++++++ Entity/News.php | 26 ++++++ Helper/Helpers.php | 25 +++++ Pub/Controller/News.php | 50 ++++++++++ Report/Entry.php | 2 +- Report/News.php | 75 +++++++++++++++ Service/Discord/BotService.php | 44 +++++++++ Setup.php | 17 ++++ XF/Entity/ApprovalQueue.php | 41 +++++++++ XF/Entity/User.php | 5 + XF/Pub/Controller/MiscController.php | 13 +++ XF/Service/Report/CreatorService.php | 38 ++++++++ ...kPlaza-Master-XF-Entity-ApprovalQueue.json | 6 ++ ...ster-XF-Pub-Controller-MiscController.json | 6 ++ ...ster-XF-Service-Report-CreatorService.json | 6 ++ _output/class_extensions/_metadata.json | 9 ++ _output/content_type_fields/_metadata.json | 12 +++ ...erequest-approval_queue_handler_class.json | 5 + .../rhpz_entry_featurerequest-entity.json | 5 + .../romhackplaza_news-entity.json | 5 + ...omhackplaza_news-report_handler_class.json | 5 + _output/extension_hint.php | 11 +++ _output/navigation/_metadata.json | 5 +- _output/navigation/news.json | 13 +++ _output/navigation/rom_patcher.json | 2 +- _output/phrases/_metadata.json | 6 ++ _output/phrases/nav.news.txt | 1 + _output/routes/_metadata.json | 3 + _output/routes/public_romhackplaza_news_.json | 11 +++ _output/template_modifications/_metadata.json | 3 + ..._forum_overview_wrapper_search_button.json | 9 ++ _output/templates/_metadata.json | 10 ++ .../approval_item_entry_featured_request.html | 11 +++ .../report_content_romhackplaza_news.html | 4 + 37 files changed, 654 insertions(+), 4 deletions(-) create mode 100644 ApprovalQueue/EntryFeaturedRequest.php create mode 100644 Entity/EntryFeaturedRequest.php create mode 100644 Entity/News.php create mode 100644 Helper/Helpers.php create mode 100644 Pub/Controller/News.php create mode 100644 Report/News.php create mode 100644 Service/Discord/BotService.php create mode 100644 XF/Entity/ApprovalQueue.php create mode 100644 XF/Pub/Controller/MiscController.php create mode 100644 XF/Service/Report/CreatorService.php create mode 100644 _output/class_extensions/XF-Entity-ApprovalQueue_RomhackPlaza-Master-XF-Entity-ApprovalQueue.json create mode 100644 _output/class_extensions/XF-Pub-Controller-MiscController_RomhackPlaza-Master-XF-Pub-Controller-MiscController.json create mode 100644 _output/class_extensions/XF-Service-Report-CreatorService_RomhackPlaza-Master-XF-Service-Report-CreatorService.json create mode 100644 _output/content_type_fields/rhpz_entry_featurerequest-approval_queue_handler_class.json create mode 100644 _output/content_type_fields/rhpz_entry_featurerequest-entity.json create mode 100644 _output/content_type_fields/romhackplaza_news-entity.json create mode 100644 _output/content_type_fields/romhackplaza_news-report_handler_class.json create mode 100644 _output/navigation/news.json create mode 100644 _output/phrases/nav.news.txt create mode 100644 _output/routes/public_romhackplaza_news_.json create mode 100644 _output/template_modifications/public/rhpz_forum_overview_wrapper_search_button.json create mode 100644 _output/templates/public/approval_item_entry_featured_request.html create mode 100644 _output/templates/public/report_content_romhackplaza_news.html diff --git a/Api/Controller/EntryController.php b/Api/Controller/EntryController.php index 1b60457..9e9bc7b 100644 --- a/Api/Controller/EntryController.php +++ b/Api/Controller/EntryController.php @@ -1,6 +1,7 @@ apiSuccess(['success' => true,'user_id' => $user->user_id,'count' => $count]); } + + public function actionPostFeatured(): AbstractReply + { + + $entryId = $this->filter('entry_id', 'uint'); + $userId = $this->filter('user_id', 'uint'); + $entryTitle = $this->filter('entry_title', 'string'); + + /** @var EntryFeaturedRequest $entryFeaturedRequest */ + $entryFeaturedRequest = $this->em()->create('RomhackPlaza\Master:EntryFeaturedRequest'); + $entryFeaturedRequest->entry_id = $entryId; + $entryFeaturedRequest->user_id = $userId; + $entryFeaturedRequest->entry_title = $entryTitle; + $entryFeaturedRequest->featured_request_state = 'moderated'; + $entryFeaturedRequest->save(); + + return $this->apiSuccess(['success' => true]); + + } } \ No newline at end of file diff --git a/ApprovalQueue/Club.php b/ApprovalQueue/Club.php index ba859bb..c859275 100644 --- a/ApprovalQueue/Club.php +++ b/ApprovalQueue/Club.php @@ -63,7 +63,7 @@ class Club extends AbstractHandler } } - public function actionReject(\RomhackPlaza\Master\Entity\Club $club) + public function actionDelete(\RomhackPlaza\Master\Entity\Club $club) { $club->club_state = 'rejected'; $club->save(); diff --git a/ApprovalQueue/EntryFeaturedRequest.php b/ApprovalQueue/EntryFeaturedRequest.php new file mode 100644 index 0000000..e49b63f --- /dev/null +++ b/ApprovalQueue/EntryFeaturedRequest.php @@ -0,0 +1,61 @@ +canActionContent($content, $error ); + } + + protected function canActionContent(Entity $content, &$error = null) + { + return \XF::visitor()->hasPermission('romhackplaza', 'canModerateEntries'); + } + + public function getEntityWith() + { + return ['User']; + } + + public function actionApprove(\RomhackPlaza\Master\Entity\EntryFeaturedRequest $entryFeaturedRequest) + { + + try { + + $db = Laravel::db(); + + $db->update('entries', [ + 'featured' => 1, + 'featured_at' => date('Y-m-d H:i:s', \XF::$time), + ], 'id = ?', + [$entryFeaturedRequest->entry_id] + ); + + $entryFeaturedRequest->featured_request_state = 'visible'; + $entryFeaturedRequest->save(); + + + } catch ( \Exception $e ) { + \XF::logException($e, messagePrefix: "EntryFeaturedRequest error: " ); + } + + } + + public function actionDelete(\RomhackPlaza\Master\Entity\EntryFeaturedRequest $entryFeaturedRequest) + { + $entryFeaturedRequest->featured_request_state = 'rejected'; + $entryFeaturedRequest->save(); + } + + public function getTemplateName() + { + return 'public:approval_item_entry_featured_request'; + } + +} \ No newline at end of file diff --git a/Entity/EntryFeaturedRequest.php b/Entity/EntryFeaturedRequest.php new file mode 100644 index 0000000..20191e6 --- /dev/null +++ b/Entity/EntryFeaturedRequest.php @@ -0,0 +1,91 @@ +shortName = 'RomhackPlaza\Master:EntryFeaturedRequest'; + $structure->table = 'xf_romhackplaza_entry_featured_request'; + $structure->primaryKey = 'featured_request_id'; + + $structure->columns = [ + 'featured_request_id' => ['type' => self::UINT, 'autoIncrement' => true], + 'entry_id' => ['type' => self::UINT, 'required' => true], + 'user_id' => ['type' => self::UINT], + 'entry_title' => ['type' => self::STR, 'maxLength' => 255], + 'featured_request_state' => ['type' => self::STR, 'default' => 'moderated', + 'allowedValues' => ['visible', 'moderated', 'rejected'] + ], + 'featured_request_date' => ['type' => self::UINT, 'default' => \XF::$time] + ]; + + $structure->relations = [ + 'User' => [ + 'entity' => 'XF:User', + 'type' => self::TO_ONE, + 'conditions' => 'user_id', + 'primary' => true + ], + ]; + + return $structure; + + } + + protected function _postSave() + { + if( $this->isInsert() && $this->featured_request_state === 'moderated' ) { + $this->inQueue(); + } else if( $this->isUpdate() && $this->isChanged('featured_request_state') ) { + if( $this->featured_request_state === 'moderated' ) { + $this->inQueue(); + } else { + $this->removeQueue(); + } + } + } + + protected function _postDelete() + { + if( $this->featured_request_state === 'moderated' ) { + $this->removeQueue(); + } + } + + protected function inQueue() + { + $queue = $this->em()->find('XF:ApprovalQueue', ['rhpz_entry_featurerequest', $this->featured_request_id ] ); + if( !$queue ) + { + /** @var ApprovalQueue $newQueue */ + $newQueue = $this->em()->create('XF:ApprovalQueue'); + $newQueue->content_type = 'rhpz_entry_featurerequest'; + $newQueue->content_id = $this->featured_request_id; + $newQueue->save(); + } + } + + protected function removeQueue() + { + $queue = $this->em()->find('XF:ApprovalQueue', ['rhpz_entry_featurerequest', $this->featured_request_id ] ); + if( $queue ) + $queue->delete(); + } +} \ No newline at end of file diff --git a/Entity/News.php b/Entity/News.php new file mode 100644 index 0000000..5beaadd --- /dev/null +++ b/Entity/News.php @@ -0,0 +1,26 @@ +shortName = 'RomhackPlaza\Master:News'; + $structure->table = 'xf_romhackplaza_news'; // Unused. + $structure->primaryKey = 'id'; + + $structure->columns = [ + 'id' => ['type' => self::UINT], + 'user_id' => ['type' => self::UINT, 'required' => true], + 'title' => ['type' => self::STR, 'required' => true], + 'slug' => ['type' => self::STR, 'required' => true], + ]; + + return $structure; + } +} \ No newline at end of file diff --git a/Helper/Helpers.php b/Helper/Helpers.php new file mode 100644 index 0000000..47405d6 --- /dev/null +++ b/Helper/Helpers.php @@ -0,0 +1,25 @@ + $content->title ?? '', + 'post' => $content->Thread?->title ?? '', + 'user' => $content->username ?? '', + 'profile_post' => \XF\Util\Str::substr($content->content ?? '', 0, 50), + 'profile_post_comment' => \XF\Util\Str::substr($content->content ?? '', 0, 50), + + // Custom + 'club' => $content->title ?? '', + 'rhpz_entry_featurerequest' => $content->entry_title ?? '', + + default => $content->title ?? $content->username ?? $content->content ?? "#{$content->getEntityId()}", + }; + } +} \ No newline at end of file diff --git a/Pub/Controller/News.php b/Pub/Controller/News.php new file mode 100644 index 0000000..6be0277 --- /dev/null +++ b/Pub/Controller/News.php @@ -0,0 +1,50 @@ +id; + $laravelDb = \RomhackPlaza\Master\Helper\Laravel::db(); + if( !$laravelDb ) + return $this->notFound(); + + $entry = $laravelDb->fetchRow("SELECT id, slugFROM news WHERE id = ?", $entryId); + if( !$entry ) + return $this->notFound(); + + return $this->redirect(\XF::options()->homePageUrl . '/news/' . $entry['slug']); + } + + public function actionReport(ParameterBag $params): AbstractReply + { + + $this->assertRegistrationRequired(); + + $entryId = $params->id; + $laravelDb = \RomhackPlaza\Master\Helper\Laravel::db(); + if( !$laravelDb ) + return $this->notFound(); + + $entry = $laravelDb->fetchRow("SELECT id, title, slug, user_id, description FROM news WHERE id = ?", $entryId); + if( !$entry ) + return $this->notFound(); + + $entity = $this->em()->instantiateEntity('RomhackPlaza\Master:News', $entry); + $entity->setReadOnly(true); + + $reportPlugin = $this->plugin('XF:Report'); + return $reportPlugin->actionReport( + 'romhackplaza_news', $entity, + $this->buildLink('romhackplaza_news/report', $entity), + \XF::options()->homePageUrl . '/news/report_redirect?id=' . $entity->id + ); + + } +} \ No newline at end of file diff --git a/Report/Entry.php b/Report/Entry.php index 1b45027..2d8e008 100644 --- a/Report/Entry.php +++ b/Report/Entry.php @@ -65,7 +65,7 @@ class Entry extends AbstractHandler #[Override] public function getContentMessage(Report $report) { - return $report->content_info['message']; + return $report->content_info['description']; } #[Override] diff --git a/Report/News.php b/Report/News.php new file mode 100644 index 0000000..b099bbd --- /dev/null +++ b/Report/News.php @@ -0,0 +1,75 @@ +hasPermission('romhackplaza', 'view'); + } + + #[Override] + protected function canActionContent(Report $report) + { + return \XF::visitor()->hasPermission('romhackplaza', 'canEditOthersEntries'); + } + + #[Override] + public function setupReportEntityContent(Report $report, Entity $content) + { + $report->content_user_id = $content['user_id']; + $report->content_info = [ + 'id' => $content['id'], + 'title' => $content['title'], + 'slug' => $content['slug'], + 'user_id' => $content['user_id'], + 'description' => $content['description'] ?? "", + ]; + } + + public function getContent($id) + { + $laravelDb = \RomhackPlaza\Master\Helper\Laravel::db(); + + if( $laravelDb ){ + $entry = $laravelDb->fetchRow("SELECT id, title, slug, user_id, description FROM news WHERE id = ?", $id); + $entity = \XF::em()->instantiateEntity('RomhackPlaza\Master:News', $entry); + $entity->setReadOnly(true); + return $entity; + } + + return null; + } + + #[Override] + public function getContentTitle(Report $report) + { + return $report->content_info['title'] ?? 'Unknown'; + } + + #[Override] + public function getContentLink(Report $report) + { + return \XF::options()->homePageUrl . '/news/' . $report->content_info['slug']; + } + + #[Override] + public function getContentMessage(Report $report) + { + return $report->content_info['description']; + } + + #[Override] + public function getTemplateName() + { + return "public:report_content_romhackplaza_news"; + } +} \ No newline at end of file diff --git a/Service/Discord/BotService.php b/Service/Discord/BotService.php new file mode 100644 index 0000000..b0f6a9e --- /dev/null +++ b/Service/Discord/BotService.php @@ -0,0 +1,44 @@ +dbPath = \XF::config('discord_db_path'); + } + + protected function getDb(): \PDO + { + if (!$this->pdo) { + $this->pdo = new \PDO("sqlite:" . $this->dbPath); + $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + $this->pdo->exec('PRAGMA journal_mode=WAL;'); + $this->pdo->exec('PRAGMA busy_timeout=5000;'); + } + return $this->pdo; + } + + public function createAction( string $action, array $data ): bool + { + try { + $db = $this->getDb(); + + $stmt = $db->prepare("INSERT INTO actions (action, data) VALUES (:action, :data)"); + return $stmt->execute([ + ':action' => $action, + ':data' => json_encode($data) + ]); + + } catch (\PDOException $e) { + \XF::logException($e, messagePrefix: "BotService error: "); + return false; + } + } +} \ No newline at end of file diff --git a/Setup.php b/Setup.php index 3e075ac..f38e2e7 100644 --- a/Setup.php +++ b/Setup.php @@ -44,6 +44,18 @@ class Setup extends AbstractSetup }); } + public function installStep3(): void + { + $this->schemaManager()->createTable('xf_romhackplaza_entry_featured_request', function(Create $table){ + $table->addColumn('featured_request_id', 'int')->autoIncrement(); + $table->addColumn('entry_id', 'int'); + $table->addColumn('user_id', 'int'); + $table->addColumn('entry_title', 'varchar', 255); + $table->addColumn('featured_request_state', 'enum')->values(['visible','moderated','rejected'])->setDefault('moderated'); + $table->addColumn('featured_request_date', 'int'); + }); + } + public function uninstallStep1(): void { $this->schemaManager()->alterTable('xf_user', function($table) { @@ -55,4 +67,9 @@ class Setup extends AbstractSetup { $this->schemaManager()->dropTable('xf_club'); } + + public function uninstallStep3(): void + { + $this->schemaManager()->dropTable('xf_romhackplaza_entry_featured_request'); + } } \ No newline at end of file diff --git a/XF/Entity/ApprovalQueue.php b/XF/Entity/ApprovalQueue.php new file mode 100644 index 0000000..c66bba3 --- /dev/null +++ b/XF/Entity/ApprovalQueue.php @@ -0,0 +1,41 @@ +isInsert() ){ + + $contentId = $this->content_id; + $contentType = $this->content_type; + + \XF::runLater(function () use ($contentId, $contentType) { + + $entity = \XF::app()->getContentTypeFieldValue($contentType, 'entity'); + if( !$entity ){ + return; + } + + $content = \XF::em()->find($entity, $contentId); + + $user = $contentType === 'user' ? $content : $content->User; + + $service = \XF::service('RomhackPlaza\Master:Discord\BotService'); + $service->createAction( 'approval_queue', [ + 'content_title' => Helpers::getContentTitle( $content, $contentType ), + 'approval_item_url' => \XF::app()->router('public')->buildLink('canonical:approval-queue' ), + 'approval_username' => $user?->username ?? '', + 'approval_user_url' => $user?->user_id ? \XF::app()->router('public')->buildLink('canonical:members', $user ) : '', + 'content_type' => $contentType, + ]); + + }); + } + } +} \ No newline at end of file diff --git a/XF/Entity/User.php b/XF/Entity/User.php index 4037bc6..bd4ef44 100644 --- a/XF/Entity/User.php +++ b/XF/Entity/User.php @@ -15,4 +15,9 @@ class User extends XFCP_User return $structure; } + + public function canCreateEntry() + { + return \XF::visitor()->hasPermission('romhackplaza', 'canSubmitEntry'); + } } \ No newline at end of file diff --git a/XF/Pub/Controller/MiscController.php b/XF/Pub/Controller/MiscController.php new file mode 100644 index 0000000..b08f0bc --- /dev/null +++ b/XF/Pub/Controller/MiscController.php @@ -0,0 +1,13 @@ +view('RomhackPlaza\Master:Misc\PreferencesPopup', 'misc_preferences_popup'); + } +} \ No newline at end of file diff --git a/XF/Service/Report/CreatorService.php b/XF/Service/Report/CreatorService.php new file mode 100644 index 0000000..f45a0da --- /dev/null +++ b/XF/Service/Report/CreatorService.php @@ -0,0 +1,38 @@ +repository(ReportRepository::class); + $handler = $reportRepo->getReportHandler($report->content_type, true); + $service = \XF::service('RomhackPlaza\Master:Discord\BotService'); + + $service->createAction('report_message', [ + 'content_title' => $handler->getContentTitle( $report ), + 'report_message' => $report->Comments->last()->message, + 'report_manage_url' => \XF::app()->router('public')->buildLink('canonical:reports', $report ), + 'report_username' => $report->User?->username ?? "Unknown user", + 'report_user_url' => \XF::app()->router('public')->buildLink('canonical:members', $report->User ), + 'content_type' => $report->content_type, + 'content_link' => $handler->getContentLink( $report ) + ]); + }); + + } + + return $report; + } + +} \ No newline at end of file diff --git a/_output/class_extensions/XF-Entity-ApprovalQueue_RomhackPlaza-Master-XF-Entity-ApprovalQueue.json b/_output/class_extensions/XF-Entity-ApprovalQueue_RomhackPlaza-Master-XF-Entity-ApprovalQueue.json new file mode 100644 index 0000000..a682761 --- /dev/null +++ b/_output/class_extensions/XF-Entity-ApprovalQueue_RomhackPlaza-Master-XF-Entity-ApprovalQueue.json @@ -0,0 +1,6 @@ +{ + "from_class": "XF\\Entity\\ApprovalQueue", + "to_class": "RomhackPlaza\\Master\\XF\\Entity\\ApprovalQueue", + "execute_order": 10, + "active": true +} \ No newline at end of file diff --git a/_output/class_extensions/XF-Pub-Controller-MiscController_RomhackPlaza-Master-XF-Pub-Controller-MiscController.json b/_output/class_extensions/XF-Pub-Controller-MiscController_RomhackPlaza-Master-XF-Pub-Controller-MiscController.json new file mode 100644 index 0000000..9b7309e --- /dev/null +++ b/_output/class_extensions/XF-Pub-Controller-MiscController_RomhackPlaza-Master-XF-Pub-Controller-MiscController.json @@ -0,0 +1,6 @@ +{ + "from_class": "XF\\Pub\\Controller\\MiscController", + "to_class": "RomhackPlaza\\Master\\XF\\Pub\\Controller\\MiscController", + "execute_order": 10, + "active": true +} \ No newline at end of file diff --git a/_output/class_extensions/XF-Service-Report-CreatorService_RomhackPlaza-Master-XF-Service-Report-CreatorService.json b/_output/class_extensions/XF-Service-Report-CreatorService_RomhackPlaza-Master-XF-Service-Report-CreatorService.json new file mode 100644 index 0000000..2042723 --- /dev/null +++ b/_output/class_extensions/XF-Service-Report-CreatorService_RomhackPlaza-Master-XF-Service-Report-CreatorService.json @@ -0,0 +1,6 @@ +{ + "from_class": "XF\\Service\\Report\\CreatorService", + "to_class": "RomhackPlaza\\Master\\XF\\Service\\Report\\CreatorService", + "execute_order": 10, + "active": true +} \ No newline at end of file diff --git a/_output/class_extensions/_metadata.json b/_output/class_extensions/_metadata.json index 12689a8..e4bd700 100644 --- a/_output/class_extensions/_metadata.json +++ b/_output/class_extensions/_metadata.json @@ -1,8 +1,17 @@ { + "XF-Entity-ApprovalQueue_RomhackPlaza-Master-XF-Entity-ApprovalQueue.json": { + "hash": "f4364e1ec74dfa80ff24368486e66ffb" + }, "XF-Entity-Forum_RomhackPlaza-Master-XF-Entity-Forum.json": { "hash": "c7747b6ea6bd924d2d02e82917ff0df3" }, "XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json": { "hash": "811593d6f012a53b9fa2ced871de96a9" + }, + "XF-Pub-Controller-MiscController_RomhackPlaza-Master-XF-Pub-Controller-MiscController.json": { + "hash": "1071fd498b2958031153de55eb4ca66a" + }, + "XF-Service-Report-CreatorService_RomhackPlaza-Master-XF-Service-Report-CreatorService.json": { + "hash": "2def6639766241a5f2ff3c10fc168731" } } \ No newline at end of file diff --git a/_output/content_type_fields/_metadata.json b/_output/content_type_fields/_metadata.json index 8381f54..dcab9a0 100644 --- a/_output/content_type_fields/_metadata.json +++ b/_output/content_type_fields/_metadata.json @@ -5,10 +5,22 @@ "club-entity.json": { "hash": "ed572323131987e295051165e4ec3c5e" }, + "rhpz_entry_featurerequest-approval_queue_handler_class.json": { + "hash": "0452fab1abce77fa92858ee46c615d8a" + }, + "rhpz_entry_featurerequest-entity.json": { + "hash": "62ab52f94cdc49ced9c18dd31eaf7f8c" + }, "romhackplaza_entry-entity.json": { "hash": "8686ffd261eb8c1698a3ec6e31118f02" }, "romhackplaza_entry-report_handler_class.json": { "hash": "3e3d009b1b4671a506accc2e920307b2" + }, + "romhackplaza_news-entity.json": { + "hash": "97f9641ceb338c2fdd489e2eed7fb7d1" + }, + "romhackplaza_news-report_handler_class.json": { + "hash": "8af48d739b42b8794fd802eaf72e2025" } } \ No newline at end of file diff --git a/_output/content_type_fields/rhpz_entry_featurerequest-approval_queue_handler_class.json b/_output/content_type_fields/rhpz_entry_featurerequest-approval_queue_handler_class.json new file mode 100644 index 0000000..5ffd0ef --- /dev/null +++ b/_output/content_type_fields/rhpz_entry_featurerequest-approval_queue_handler_class.json @@ -0,0 +1,5 @@ +{ + "content_type": "rhpz_entry_featurerequest", + "field_name": "approval_queue_handler_class", + "field_value": "RomhackPlaza\\Master\\ApprovalQueue\\EntryFeaturedRequest" +} \ No newline at end of file diff --git a/_output/content_type_fields/rhpz_entry_featurerequest-entity.json b/_output/content_type_fields/rhpz_entry_featurerequest-entity.json new file mode 100644 index 0000000..137e8a8 --- /dev/null +++ b/_output/content_type_fields/rhpz_entry_featurerequest-entity.json @@ -0,0 +1,5 @@ +{ + "content_type": "rhpz_entry_featurerequest", + "field_name": "entity", + "field_value": "RomhackPlaza\\Master\\Entity\\EntryFeaturedRequest" +} \ No newline at end of file diff --git a/_output/content_type_fields/romhackplaza_news-entity.json b/_output/content_type_fields/romhackplaza_news-entity.json new file mode 100644 index 0000000..ef647bb --- /dev/null +++ b/_output/content_type_fields/romhackplaza_news-entity.json @@ -0,0 +1,5 @@ +{ + "content_type": "romhackplaza_news", + "field_name": "entity", + "field_value": "RomhackPlaza\\Master\\Entity\\News" +} \ No newline at end of file diff --git a/_output/content_type_fields/romhackplaza_news-report_handler_class.json b/_output/content_type_fields/romhackplaza_news-report_handler_class.json new file mode 100644 index 0000000..f4eb744 --- /dev/null +++ b/_output/content_type_fields/romhackplaza_news-report_handler_class.json @@ -0,0 +1,5 @@ +{ + "content_type": "romhackplaza_news", + "field_name": "report_handler_class", + "field_value": "RomhackPlaza\\Master\\Report\\News" +} \ No newline at end of file diff --git a/_output/extension_hint.php b/_output/extension_hint.php index f542957..e06e77a 100644 --- a/_output/extension_hint.php +++ b/_output/extension_hint.php @@ -10,6 +10,17 @@ namespace RomhackPlaza\Master\XF\Entity { + class XFCP_ApprovalQueue extends \XF\Entity\ApprovalQueue {} class XFCP_Forum extends \XF\Entity\Forum {} class XFCP_User extends \XF\Entity\User {} } + +namespace RomhackPlaza\Master\XF\Pub\Controller +{ + class XFCP_MiscController extends \XF\Pub\Controller\MiscController {} +} + +namespace RomhackPlaza\Master\XF\Service\Report +{ + class XFCP_CreatorService extends \XF\Service\Report\CreatorService {} +} diff --git a/_output/navigation/_metadata.json b/_output/navigation/_metadata.json index 087d264..761cae1 100644 --- a/_output/navigation/_metadata.json +++ b/_output/navigation/_metadata.json @@ -35,6 +35,9 @@ "members.json": { "hash": "cad1568d161bea1a7dd1f286b8788e2d" }, + "news.json": { + "hash": "c42353e9a510b365d09f2b64af401e55" + }, "pages.json": { "hash": "8d75bf99b2fb6528f84433f4519d4da3" }, @@ -45,7 +48,7 @@ "hash": "e14613a1bd0f1e1fadc084a009801570" }, "rom_patcher.json": { - "hash": "2a2af404aa6395b02c711867a7287a6f" + "hash": "dff75392eea1fdffdaec193913d5d8a0" }, "submissions_queue.json": { "hash": "071c745afd8f28cf9505702496f72a18" diff --git a/_output/navigation/news.json b/_output/navigation/news.json new file mode 100644 index 0000000..828a4a1 --- /dev/null +++ b/_output/navigation/news.json @@ -0,0 +1,13 @@ +{ + "parent_navigation_id": "website", + "display_order": 250, + "navigation_type_id": "basic", + "type_config": { + "link": "{$xf.options.homePageUrl}/news", + "display_condition": "", + "extra_attributes": { + "icon": "newspaper" + } + }, + "enabled": true +} \ No newline at end of file diff --git a/_output/navigation/rom_patcher.json b/_output/navigation/rom_patcher.json index 680ba5d..cc02ad8 100644 --- a/_output/navigation/rom_patcher.json +++ b/_output/navigation/rom_patcher.json @@ -3,7 +3,7 @@ "display_order": 100, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/tools/rom-patcher", + "link": "{$xf.options.homePageUrl}/patch", "display_condition": "", "extra_attributes": { "icon": "stamp" diff --git a/_output/phrases/_metadata.json b/_output/phrases/_metadata.json index 74be088..c0e887c 100644 --- a/_output/phrases/_metadata.json +++ b/_output/phrases/_metadata.json @@ -71,6 +71,12 @@ "version_string": "1.0.0", "hash": "ef53538ae41a651c7f72ab6cb1135d8c" }, + "nav.news.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "dd1ba1872df91985ed1ca4cde2dfe669" + }, "nav.pages.txt": { "global_cache": false, "version_id": 1000000, diff --git a/_output/phrases/nav.news.txt b/_output/phrases/nav.news.txt new file mode 100644 index 0000000..da26bbe --- /dev/null +++ b/_output/phrases/nav.news.txt @@ -0,0 +1 @@ +News \ No newline at end of file diff --git a/_output/routes/_metadata.json b/_output/routes/_metadata.json index 0c6bcac..f24d27b 100644 --- a/_output/routes/_metadata.json +++ b/_output/routes/_metadata.json @@ -10,5 +10,8 @@ }, "public_romhackplaza_entry_.json": { "hash": "2c40d7266fcc22a5727830a69af2360c" + }, + "public_romhackplaza_news_.json": { + "hash": "a012e23a91029aead56b061747d0334a" } } \ No newline at end of file diff --git a/_output/routes/public_romhackplaza_news_.json b/_output/routes/public_romhackplaza_news_.json new file mode 100644 index 0000000..2fad54f --- /dev/null +++ b/_output/routes/public_romhackplaza_news_.json @@ -0,0 +1,11 @@ +{ + "route_type": "public", + "route_prefix": "romhackplaza_news", + "sub_name": "", + "format": ":int", + "build_class": "", + "build_method": "", + "controller": "RomhackPlaza\\Master:News", + "context": "", + "action_prefix": "" +} \ No newline at end of file diff --git a/_output/template_modifications/_metadata.json b/_output/template_modifications/_metadata.json index 1a3032e..879129b 100644 --- a/_output/template_modifications/_metadata.json +++ b/_output/template_modifications/_metadata.json @@ -7,5 +7,8 @@ }, "public/rhpz_category_view_clubs_submit_button.json": { "hash": "a24a5a4b130b6198de7ef37610aa1a7d" + }, + "public/rhpz_forum_overview_wrapper_search_button.json": { + "hash": "af109f16aca8a12c4f8496fc4431f4b8" } } \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_forum_overview_wrapper_search_button.json b/_output/template_modifications/public/rhpz_forum_overview_wrapper_search_button.json new file mode 100644 index 0000000..a75f7d5 --- /dev/null +++ b/_output/template_modifications/public/rhpz_forum_overview_wrapper_search_button.json @@ -0,0 +1,9 @@ +{ + "template": "forum_overview_wrapper", + "description": "Add Search button", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "\t\t\n\t\t\t{{ phrase('new_posts') }}\n\t\t", + "replace": "\t\t$0\n\t\t\n\t\t\t{{ phrase('search') }}\n\t\t" +} \ No newline at end of file diff --git a/_output/templates/_metadata.json b/_output/templates/_metadata.json index 68e17fb..fd31b1b 100644 --- a/_output/templates/_metadata.json +++ b/_output/templates/_metadata.json @@ -9,6 +9,11 @@ "version_string": "1.0.0", "hash": "da1f9c78c4e33597062258c0bba3cb4d" }, + "public/approval_item_entry_featured_request.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "1383f7fa1680c2da22cfc08aa1ad55f5" + }, "public/club_delete_confirm.html": { "version_id": 1000000, "version_string": "1.0.0", @@ -28,5 +33,10 @@ "version_id": 1000000, "version_string": "1.0.0", "hash": "d6c5c25a9af81a7da2bd8e2b9f74229e" + }, + "public/report_content_romhackplaza_news.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d6c5c25a9af81a7da2bd8e2b9f74229e" } } \ No newline at end of file diff --git a/_output/templates/public/approval_item_entry_featured_request.html b/_output/templates/public/approval_item_entry_featured_request.html new file mode 100644 index 0000000..bce9d13 --- /dev/null +++ b/_output/templates/public/approval_item_entry_featured_request.html @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/_output/templates/public/report_content_romhackplaza_news.html b/_output/templates/public/report_content_romhackplaza_news.html new file mode 100644 index 0000000..a3c44e4 --- /dev/null +++ b/_output/templates/public/report_content_romhackplaza_news.html @@ -0,0 +1,4 @@ +
+ {{ phrase('content:') }} + {$report.content_info.description} +
\ No newline at end of file From 0436a99a7c55adfc453eecde97dd6589a2f3a21a Mon Sep 17 00:00:00 2001 From: Benjamin Date: Wed, 17 Jun 2026 13:43:17 +0200 Subject: [PATCH 5/9] Added delete account options --- Service/DeleteAccount/CodeService.php | 30 +++++++++++++++ XF/Admin/Controller/UserController.php | 25 ++++++++++++ XF/Pub/Controller/AccountController.php | 25 ++++++++++++ ...er-XF-Admin-Controller-UserController.json | 6 +++ ...r-XF-Pub-Controller-AccountController.json | 6 +++ _output/class_extensions/_metadata.json | 6 +++ _output/extension_hint.php | 6 +++ _output/option_groups/_metadata.json | 2 +- _output/option_groups/romhackplaza.json | 2 +- _output/option_hint.php | 1 + _output/options/_metadata.json | 3 ++ .../rhpz_delete_account_master_key.json | 13 +++++++ _output/phrases/_metadata.json | 38 ++++++++++++++++++- _output/phrases/delete_account.txt | 1 + _output/phrases/delete_account_code.txt | 1 + _output/phrases/delete_account_codes.txt | 1 + _output/phrases/delete_all_data_code.txt | 1 + .../option.rhpz_delete_account_master_key.txt | 1 + ...explain.rhpz_delete_account_master_key.txt | 0 .../option_group_description.romhackplaza.txt | 1 + _output/template_modifications/_metadata.json | 12 ++++++ .../rhpz_helper_criteria_entry_count.json | 9 +++++ ...pz_user_edit_delete_account_codes_tab.json | 9 +++++ ...r_edit_delete_account_codes_tab_panes.json | 9 +++++ .../rhpz_account_wrapper_delete_account.json | 9 +++++ _output/templates/_metadata.json | 7 +++- _output/templates/admin/helper_criteria.html | 4 -- .../admin/user_delete_account_codes.html | 15 ++++++++ 28 files changed, 235 insertions(+), 8 deletions(-) create mode 100644 Service/DeleteAccount/CodeService.php create mode 100644 XF/Admin/Controller/UserController.php create mode 100644 XF/Pub/Controller/AccountController.php create mode 100644 _output/class_extensions/XF-Admin-Controller-UserController_RomhackPlaza-Master-XF-Admin-Controller-UserController.json create mode 100644 _output/class_extensions/XF-Pub-Controller-AccountController_RomhackPlaza-Master-XF-Pub-Controller-AccountController.json create mode 100644 _output/options/rhpz_delete_account_master_key.json create mode 100644 _output/phrases/delete_account.txt create mode 100644 _output/phrases/delete_account_code.txt create mode 100644 _output/phrases/delete_account_codes.txt create mode 100644 _output/phrases/delete_all_data_code.txt create mode 100644 _output/phrases/option.rhpz_delete_account_master_key.txt create mode 100644 _output/phrases/option_explain.rhpz_delete_account_master_key.txt create mode 100644 _output/template_modifications/admin/rhpz_helper_criteria_entry_count.json create mode 100644 _output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab.json create mode 100644 _output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab_panes.json create mode 100644 _output/template_modifications/public/rhpz_account_wrapper_delete_account.json create mode 100644 _output/templates/admin/user_delete_account_codes.html diff --git a/Service/DeleteAccount/CodeService.php b/Service/DeleteAccount/CodeService.php new file mode 100644 index 0000000..86edf48 --- /dev/null +++ b/Service/DeleteAccount/CodeService.php @@ -0,0 +1,30 @@ +masterKey = \XF::options()->rhpz_delete_account_master_key; + } + + public function generateDeleteAllDataKey( User $user ) + { + $dataString = "delete_data_{$user->user_id}"; + return hash_hmac('md5', $dataString, $this->masterKey ); + } + + public function generateDeleteAccountKey( User $user ) + { + $dataString = "delete_account_{$user->user_id}"; + return hash_hmac('md5', $dataString, $this->masterKey ); + } + +} \ No newline at end of file diff --git a/XF/Admin/Controller/UserController.php b/XF/Admin/Controller/UserController.php new file mode 100644 index 0000000..ad947c8 --- /dev/null +++ b/XF/Admin/Controller/UserController.php @@ -0,0 +1,25 @@ +assertUserExists($params->user_id); + + /** @var CodeService $service */ + $service = \XF::service('RomhackPlaza\Master:DeleteAccount\CodeService'); + + $viewParams = [ + 'user' => $user, + 'deleteAllDataCode' => $service->generateDeleteAllDataKey( $user ), + 'deleteAccountCode' => $service->generateDeleteAccountKey( $user ), + ]; + + return $this->view('XF:User\DeleteAccountCodes', 'user_delete_account_codes', $viewParams); + } +} \ No newline at end of file diff --git a/XF/Pub/Controller/AccountController.php b/XF/Pub/Controller/AccountController.php new file mode 100644 index 0000000..ac78034 --- /dev/null +++ b/XF/Pub/Controller/AccountController.php @@ -0,0 +1,25 @@ + $service->generateDeleteAllDataKey( $visitor ), + 'deleteAccountCode' => $service->generateDeleteAccountKey( $visitor ), + ]; + + $view = $this->view('XF:Account\DeleteAccount', 'delete_account', $viewParams); + return $this->addAccountWrapperParams($view, 'delete_account'); + } + +} \ No newline at end of file diff --git a/_output/class_extensions/XF-Admin-Controller-UserController_RomhackPlaza-Master-XF-Admin-Controller-UserController.json b/_output/class_extensions/XF-Admin-Controller-UserController_RomhackPlaza-Master-XF-Admin-Controller-UserController.json new file mode 100644 index 0000000..0572061 --- /dev/null +++ b/_output/class_extensions/XF-Admin-Controller-UserController_RomhackPlaza-Master-XF-Admin-Controller-UserController.json @@ -0,0 +1,6 @@ +{ + "from_class": "XF\\Admin\\Controller\\UserController", + "to_class": "RomhackPlaza\\Master\\XF\\Admin\\Controller\\UserController", + "execute_order": 10, + "active": true +} \ No newline at end of file diff --git a/_output/class_extensions/XF-Pub-Controller-AccountController_RomhackPlaza-Master-XF-Pub-Controller-AccountController.json b/_output/class_extensions/XF-Pub-Controller-AccountController_RomhackPlaza-Master-XF-Pub-Controller-AccountController.json new file mode 100644 index 0000000..547489b --- /dev/null +++ b/_output/class_extensions/XF-Pub-Controller-AccountController_RomhackPlaza-Master-XF-Pub-Controller-AccountController.json @@ -0,0 +1,6 @@ +{ + "from_class": "XF\\Pub\\Controller\\AccountController", + "to_class": "RomhackPlaza\\Master\\XF\\Pub\\Controller\\AccountController", + "execute_order": 10, + "active": true +} \ No newline at end of file diff --git a/_output/class_extensions/_metadata.json b/_output/class_extensions/_metadata.json index e4bd700..87997b2 100644 --- a/_output/class_extensions/_metadata.json +++ b/_output/class_extensions/_metadata.json @@ -1,4 +1,7 @@ { + "XF-Admin-Controller-UserController_RomhackPlaza-Master-XF-Admin-Controller-UserController.json": { + "hash": "542c5dd275e5e26446a9e4a19b3c47b6" + }, "XF-Entity-ApprovalQueue_RomhackPlaza-Master-XF-Entity-ApprovalQueue.json": { "hash": "f4364e1ec74dfa80ff24368486e66ffb" }, @@ -8,6 +11,9 @@ "XF-Entity-User_RomhackPlaza-Master-XF-Entity-User.json": { "hash": "811593d6f012a53b9fa2ced871de96a9" }, + "XF-Pub-Controller-AccountController_RomhackPlaza-Master-XF-Pub-Controller-AccountController.json": { + "hash": "b34f519ca78e8977c98e0307125537bc" + }, "XF-Pub-Controller-MiscController_RomhackPlaza-Master-XF-Pub-Controller-MiscController.json": { "hash": "1071fd498b2958031153de55eb4ca66a" }, diff --git a/_output/extension_hint.php b/_output/extension_hint.php index e06e77a..1599256 100644 --- a/_output/extension_hint.php +++ b/_output/extension_hint.php @@ -8,6 +8,11 @@ * @noinspection PhpMultipleClassesDeclarationsInOneFile */ +namespace RomhackPlaza\Master\XF\Admin\Controller +{ + class XFCP_UserController extends \XF\Admin\Controller\UserController {} +} + namespace RomhackPlaza\Master\XF\Entity { class XFCP_ApprovalQueue extends \XF\Entity\ApprovalQueue {} @@ -17,6 +22,7 @@ namespace RomhackPlaza\Master\XF\Entity namespace RomhackPlaza\Master\XF\Pub\Controller { + class XFCP_AccountController extends \XF\Pub\Controller\AccountController {} class XFCP_MiscController extends \XF\Pub\Controller\MiscController {} } diff --git a/_output/option_groups/_metadata.json b/_output/option_groups/_metadata.json index 4cc733d..d79526a 100644 --- a/_output/option_groups/_metadata.json +++ b/_output/option_groups/_metadata.json @@ -1,5 +1,5 @@ { "romhackplaza.json": { - "hash": "02d554f377cebf4d2532162b1c223e64" + "hash": "e21c9e1387c95754e243002eaed87e18" } } \ No newline at end of file diff --git a/_output/option_groups/romhackplaza.json b/_output/option_groups/romhackplaza.json index eb2cfb4..af6b1e9 100644 --- a/_output/option_groups/romhackplaza.json +++ b/_output/option_groups/romhackplaza.json @@ -1,5 +1,5 @@ { - "icon": "", + "icon": "fa-umbrella-beach", "display_order": 500, "advanced": false, "debug_only": false diff --git a/_output/option_hint.php b/_output/option_hint.php index feb0449..8fee43d 100644 --- a/_output/option_hint.php +++ b/_output/option_hint.php @@ -12,6 +12,7 @@ namespace XF; /** * @property non-negative-int|null $rhpz_club_node_id Club Parent Node ID + * @property string|null $rhpz_delete_account_master_key Delete account Master key */ class Options { diff --git a/_output/options/_metadata.json b/_output/options/_metadata.json index e2eebbc..d4f4f29 100644 --- a/_output/options/_metadata.json +++ b/_output/options/_metadata.json @@ -1,5 +1,8 @@ { "rhpz_club_node_id.json": { "hash": "96114ee498a669ab50a1bc32768d3969" + }, + "rhpz_delete_account_master_key.json": { + "hash": "d649af68f404568ba3c06cc0a7121649" } } \ No newline at end of file diff --git a/_output/options/rhpz_delete_account_master_key.json b/_output/options/rhpz_delete_account_master_key.json new file mode 100644 index 0000000..e9f3f03 --- /dev/null +++ b/_output/options/rhpz_delete_account_master_key.json @@ -0,0 +1,13 @@ +{ + "edit_format": "textbox", + "edit_format_params": "", + "data_type": "string", + "sub_options": [], + "validation_class": "", + "validation_method": "", + "advanced": false, + "default_value": "", + "relations": { + "romhackplaza": 1 + } +} \ No newline at end of file diff --git a/_output/phrases/_metadata.json b/_output/phrases/_metadata.json index c0e887c..13925ba 100644 --- a/_output/phrases/_metadata.json +++ b/_output/phrases/_metadata.json @@ -1,4 +1,28 @@ { + "delete_account.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "e6e049c44a797fda2a175d07df838e49" + }, + "delete_account_code.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "9290d474fd3f2bdde27a87d03b99c8d0" + }, + "delete_account_codes.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d5fb1c03e7384236ebd589b23155b0c2" + }, + "delete_all_data_code.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "15d96c48f857b975c051d7c98b13a385" + }, "nav.about.txt": { "global_cache": false, "version_id": 1000000, @@ -125,12 +149,24 @@ "version_string": "1.0.0", "hash": "e73496f262c162a1a35bd9e990b36825" }, + "option.rhpz_delete_account_master_key.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "8b275759f2215b3b242de29110f05a4c" + }, "option_explain.rhpz_club_node_id.txt": { "global_cache": false, "version_id": 1000000, "version_string": "1.0.0", "hash": "d41d8cd98f00b204e9800998ecf8427e" }, + "option_explain.rhpz_delete_account_master_key.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d41d8cd98f00b204e9800998ecf8427e" + }, "option_group.romhackplaza.txt": { "global_cache": false, "version_id": 1000000, @@ -141,7 +177,7 @@ "global_cache": false, "version_id": 1000000, "version_string": "1.0.0", - "hash": "d41d8cd98f00b204e9800998ecf8427e" + "hash": "11821c85ed03034c1bba4294e357d089" }, "permission.romhackplaza_canEditMyEntries.txt": { "global_cache": false, diff --git a/_output/phrases/delete_account.txt b/_output/phrases/delete_account.txt new file mode 100644 index 0000000..bded51e --- /dev/null +++ b/_output/phrases/delete_account.txt @@ -0,0 +1 @@ +Delete account \ No newline at end of file diff --git a/_output/phrases/delete_account_code.txt b/_output/phrases/delete_account_code.txt new file mode 100644 index 0000000..1b717da --- /dev/null +++ b/_output/phrases/delete_account_code.txt @@ -0,0 +1 @@ +Delete account code \ No newline at end of file diff --git a/_output/phrases/delete_account_codes.txt b/_output/phrases/delete_account_codes.txt new file mode 100644 index 0000000..1955950 --- /dev/null +++ b/_output/phrases/delete_account_codes.txt @@ -0,0 +1 @@ +Delete account codes \ No newline at end of file diff --git a/_output/phrases/delete_all_data_code.txt b/_output/phrases/delete_all_data_code.txt new file mode 100644 index 0000000..07752ff --- /dev/null +++ b/_output/phrases/delete_all_data_code.txt @@ -0,0 +1 @@ +Delete all data code \ No newline at end of file diff --git a/_output/phrases/option.rhpz_delete_account_master_key.txt b/_output/phrases/option.rhpz_delete_account_master_key.txt new file mode 100644 index 0000000..749ca74 --- /dev/null +++ b/_output/phrases/option.rhpz_delete_account_master_key.txt @@ -0,0 +1 @@ +Delete account Master key \ No newline at end of file diff --git a/_output/phrases/option_explain.rhpz_delete_account_master_key.txt b/_output/phrases/option_explain.rhpz_delete_account_master_key.txt new file mode 100644 index 0000000..e69de29 diff --git a/_output/phrases/option_group_description.romhackplaza.txt b/_output/phrases/option_group_description.romhackplaza.txt index e69de29..b33d3bc 100644 --- a/_output/phrases/option_group_description.romhackplaza.txt +++ b/_output/phrases/option_group_description.romhackplaza.txt @@ -0,0 +1 @@ +These options are specific to Romhack Plaza \ No newline at end of file diff --git a/_output/template_modifications/_metadata.json b/_output/template_modifications/_metadata.json index 879129b..310ec3c 100644 --- a/_output/template_modifications/_metadata.json +++ b/_output/template_modifications/_metadata.json @@ -1,10 +1,22 @@ { + "admin/rhpz_helper_criteria_entry_count.json": { + "hash": "d94d8b880e79d281df49117a84ae62d7" + }, + "admin/rhpz_user_edit_delete_account_codes_tab.json": { + "hash": "16b7ae6dac8dbb6846df3e6eb9cd53b6" + }, + "admin/rhpz_user_edit_delete_account_codes_tab_panes.json": { + "hash": "d4f793cfd5ba4b6841bd819a12e596e9" + }, "public/rhpz_above_thread_list_clubs.json": { "hash": "c261ea6e33cf5eb7ab0a7f6fe934de7c" }, "public/rhpz_above_thread_list_clubs_buttons.json": { "hash": "c783001e00f7a63389c9ae988012f5fe" }, + "public/rhpz_account_wrapper_delete_account.json": { + "hash": "6594c0474a9b3e737a10dbd9c531521e" + }, "public/rhpz_category_view_clubs_submit_button.json": { "hash": "a24a5a4b130b6198de7ef37610aa1a7d" }, diff --git a/_output/template_modifications/admin/rhpz_helper_criteria_entry_count.json b/_output/template_modifications/admin/rhpz_helper_criteria_entry_count.json new file mode 100644 index 0000000..fcc6b11 --- /dev/null +++ b/_output/template_modifications/admin/rhpz_helper_criteria_entry_count.json @@ -0,0 +1,9 @@ +{ + "template": "helper_criteria", + "description": "", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "\n\t\n" +} \ No newline at end of file diff --git a/_output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab.json b/_output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab.json new file mode 100644 index 0000000..a7577ce --- /dev/null +++ b/_output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab.json @@ -0,0 +1,9 @@ +{ + "template": "user_edit", + "description": "Add Tab for listing delete account codes in User edit", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "\n\t{{ phrase('delete_account_codes') }}\n\n$0" +} \ No newline at end of file diff --git a/_output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab_panes.json b/_output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab_panes.json new file mode 100644 index 0000000..ef7be2e --- /dev/null +++ b/_output/template_modifications/admin/rhpz_user_edit_delete_account_codes_tab_panes.json @@ -0,0 +1,9 @@ +{ + "template": "user_edit", + "description": "Add Tab panes in User edit page for account deletion codes.", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "\n\n\t
  • \n\t\t
    {{ phrase('loading...') }}
    \n\t
  • \n
    \n$0" +} \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_account_wrapper_delete_account.json b/_output/template_modifications/public/rhpz_account_wrapper_delete_account.json new file mode 100644 index 0000000..5f8b32d --- /dev/null +++ b/_output/template_modifications/public/rhpz_account_wrapper_delete_account.json @@ -0,0 +1,9 @@ +{ + "template": "account_wrapper", + "description": "Add Delete account page URL to account details", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "\n\t{{ phrase('delete_account') }}\n\n$0" +} \ No newline at end of file diff --git a/_output/templates/_metadata.json b/_output/templates/_metadata.json index fd31b1b..a94f191 100644 --- a/_output/templates/_metadata.json +++ b/_output/templates/_metadata.json @@ -2,7 +2,12 @@ "admin/helper_criteria.html": { "version_id": 1000000, "version_string": "1.0.0", - "hash": "19cd05c4ab254dbad0abfd0c6b8c3456" + "hash": "0d8327297612e3e8eeb17e204e33694d" + }, + "admin/user_delete_account_codes.html": { + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "cf9c69eb1bfa0821778f60e9866626a4" }, "public/approval_item_club_request.html": { "version_id": 1000000, diff --git a/_output/templates/admin/helper_criteria.html b/_output/templates/admin/helper_criteria.html index 6e8dd08..4184eab 100644 --- a/_output/templates/admin/helper_criteria.html +++ b/_output/templates/admin/helper_criteria.html @@ -187,10 +187,6 @@ - - - - diff --git a/_output/templates/admin/user_delete_account_codes.html b/_output/templates/admin/user_delete_account_codes.html new file mode 100644 index 0000000..747f2fe --- /dev/null +++ b/_output/templates/admin/user_delete_account_codes.html @@ -0,0 +1,15 @@ +{$user.username} + +
    +
    +

    {{ phrase('delete_account_code') }}

    +
    +
    {$deleteAccountCode}
    +
    + +

    {{ phrase('delete_all_data_code') }}

    +
    +
    {$deleteAllDataCode}
    +
    +
    +
    \ No newline at end of file From 39adc2171c61ac3a43d148f709d2cd3b365eb317 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Tue, 23 Jun 2026 19:24:37 +0200 Subject: [PATCH 6/9] Migration complete --- Api/Controller/MigrateController.php | 79 +++++++++++++++ Authentication/WordPress.php | 91 +++++++++++++++++ Helper/Migration.php | 86 ++++++++++++++++ Import/Importer/RHPZForums.php | 97 +++++++++++++++++++ Listener.php | 50 ++++++++++ _output/code_event_listeners/_metadata.json | 6 ++ ...page_c6149e27cfdc21a20c8047e0e5cd5503.json | 9 ++ ...sses_64d8f27f58ba02af52958c1d4f94f812.json | 9 ++ _output/navigation/_metadata.json | 5 +- _output/navigation/rom_checker.json | 13 --- _output/navigation/rom_hasher.json | 2 +- _output/option_hint.php | 1 + _output/options/_metadata.json | 3 + _output/options/rhpz_enable_migration.json | 13 +++ _output/phrases/_metadata.json | 24 +++-- _output/phrases/entries.txt | 1 + _output/phrases/nav.rom_checker.txt | 1 - .../phrases/option.rhpz_enable_migration.txt | 1 + .../option_explain.rhpz_enable_migration.txt | 1 + _output/routes/_metadata.json | 3 + _output/routes/api_migrate_.json | 11 +++ _output/template_modifications/_metadata.json | 9 ++ ..._macros_member_stat_pairs_entry_count.json | 9 ++ .../rhpz_member_view_add_entry_tab.json | 9 ++ .../rhpz_member_view_add_entry_tabpanel.json | 9 ++ 25 files changed, 517 insertions(+), 25 deletions(-) create mode 100644 Api/Controller/MigrateController.php create mode 100644 Authentication/WordPress.php create mode 100644 Helper/Migration.php create mode 100644 Import/Importer/RHPZForums.php create mode 100644 _output/code_event_listeners/app_pub_render_page_c6149e27cfdc21a20c8047e0e5cd5503.json create mode 100644 _output/code_event_listeners/import_importer_classes_64d8f27f58ba02af52958c1d4f94f812.json delete mode 100644 _output/navigation/rom_checker.json create mode 100644 _output/options/rhpz_enable_migration.json create mode 100644 _output/phrases/entries.txt delete mode 100644 _output/phrases/nav.rom_checker.txt create mode 100644 _output/phrases/option.rhpz_enable_migration.txt create mode 100644 _output/phrases/option_explain.rhpz_enable_migration.txt create mode 100644 _output/routes/api_migrate_.json create mode 100644 _output/template_modifications/public/rhpz_member_macros_member_stat_pairs_entry_count.json create mode 100644 _output/template_modifications/public/rhpz_member_view_add_entry_tab.json create mode 100644 _output/template_modifications/public/rhpz_member_view_add_entry_tabpanel.json diff --git a/Api/Controller/MigrateController.php b/Api/Controller/MigrateController.php new file mode 100644 index 0000000..435eb2a --- /dev/null +++ b/Api/Controller/MigrateController.php @@ -0,0 +1,79 @@ +rhpz_enable_migration; + if( !$rhpz_enable_migration ){ + $this->error("Migration not enabled"); + } + + } + + public function actionPostUser(): AbstractReply + { + $input = $this->filter([ + 'username' => 'str', + 'email' => 'str', + 'profile[about]' => 'str', + 'profile[website]' => 'str', + 'register_date' => 'uint', + 'user_group_id' => 'uint', + 'xf_user_id' => 'uint', + 'avatar_path' => 'str', + 'banner_path' => 'str', + 'source_real_password' => 'str', + 'wp_password' => 'str', + 'xf_scheme_class' => 'str', + 'xf_password_data' => 'str', + ]); + + $this->assertAdminPermission('user'); + $this->assertRequiredApiInput(['username','email','user_group_id']); + + /** @var UserRepository $userRepository */ + $userRepository = \XF::repository(UserRepository::class); + $user = $userRepository->setupBaseUser(null); + + $userPlugin = $this->plugin(UserPlugin::class); + $userPlugin->userSaveProcessAdmin($user)->run(); + + /** @var UserAuth $authUser */ + $authUser = $user->getExistingRelation('Auth'); + if( $input['source_real_password'] === 'wp' ){ + $authUser->scheme_class = 'RomhackPlaza\Master:WordPress'; + $authUser->data = ['hash' => $input['wp_password']]; + $authUser->save(); + } elseif( $input['source_real_password'] === 'xf' ){ + $authUser->scheme_class = $input['xf_scheme_class']; + $authUser->data = @unserialize($input['xf_password_data']); + $authUser->save(); + } + + if( $input['avatar_path'] !== "" ){ + Migration::setAvatarFromPath($input['avatar_path'], $user); + } + if( $input['banner_path'] !== "" ){ + Migration::setBannerFromPath($input['banner_path'], $user); + } + if( $input['register_date'] != 0 ){ + $user->register_date = $input['register_date']; + $user->save(); + } + + return $this->apiSuccess(['success' => true, 'user_id' => $user->user_id, 'password_set' => true ]); + + } +} diff --git a/Authentication/WordPress.php b/Authentication/WordPress.php new file mode 100644 index 0000000..6616504 --- /dev/null +++ b/Authentication/WordPress.php @@ -0,0 +1,91 @@ +data) ) { + return false; + } + + return $this->verifyPassword($password, $this->data['hash']); + + } + + private function verifyPassword($password, $storedHash): bool + { + if( str_starts_with($storedHash, '$wp') ){ + $passwordToVerify = base64_encode( hash_hmac( 'sha384', $password, 'wp-sha384', true ) ); + return password_verify( $passwordToVerify, substr($storedHash, 3) ); + } + + if (str_starts_with($storedHash, '$2y$') || str_starts_with($storedHash, '$2a$') || str_starts_with($storedHash, '$2b$')) { + return password_verify($password, $storedHash); + } + + if (strlen($storedHash) === 34 && (str_starts_with($storedHash, '$P$') || str_starts_with($storedHash, '$H$'))) { + return $this->verifyPhpass($password, $storedHash); + } + + if (strlen($storedHash) <= 32) { + return hash_equals($storedHash, md5($password)); + } + + return false; + } + + private function verifyPhpass(string $password, string $storedHash): bool + { + $itoa64 = self::ITOA64; + $countLog2 = strpos($itoa64, $storedHash[3]); + if ($countLog2 < 7 || $countLog2 > 30) return false; + + $count = 1 << $countLog2; + $salt = substr($storedHash, 4, 8); + if (strlen($salt) !== 8) return false; + + $hash = md5($salt . $password, true); + do { + $hash = md5($hash . $password, true); + } while (--$count); + + $output = substr($storedHash, 0, 12) . self::encode64($hash, $itoa64); + return hash_equals($storedHash, $output); + } + + private function encode64(string $input, string $itoa64): string + { + $output = ''; + $i = 0; + $count = strlen($input); + do { + $value = ord($input[$i++]); + $output .= $itoa64[$value & 0x3f]; + if ($i < $count) $value |= ord($input[$i]) << 8; + $output .= $itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) break; + if ($i < $count) $value |= ord($input[$i]) << 16; + $output .= $itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) break; + $output .= $itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + return $output; + } + + public function getAuthenticationName() + { + return 'RomhackPlaza\Master:WordPress'; + } +} \ No newline at end of file diff --git a/Helper/Migration.php b/Helper/Migration.php new file mode 100644 index 0000000..f8963f1 --- /dev/null +++ b/Helper/Migration.php @@ -0,0 +1,86 @@ +container(); + if( !isset( $container['oldXfDb'] ) ){ + $container['oldXfDb'] = function(Container $c){ + $config = \XF::config('oldxfdb'); + if( !$config ) + return null; + + return new \XF\Db\Mysqli\Adapter($config, true); + }; + } + + return $container['oldXfDb']; + } + + public static function uniqueUsername(string $username): string + { + $u = $username; + $i = 1; + while(\XF::em()->findOne('XF:User', ['username' => $u])){ + $u = $username . '_' . $i++; + } + + return $u; + } + + public static function copyUserPassword(int $xf_user_id, User $user): bool + { + $oldDb = self::oldXfDb(); + if( !$oldDb ){ + return false; + } + + $row = $oldDb->fetchRow( + 'SELECT scheme_class, data FROM xf_user_authenticate WHERE user_id = ?', + [$xf_user_id] + ); + if( !$row ){ + return false; + } + + $user->Auth->scheme_class = $row['scheme_class']; + $user->Auth->data = $row['data']; + return $user->Auth->save(); + } + + public static function setAvatarFromPath(string $avatar_path, User $user): bool + { + if(!is_readable($avatar_path)) + return false; + + $avatarService = \XF::service(AvatarService::class, $user); + + if (!$avatarService->setImage($avatar_path)) + return false; + + return $avatarService->updateAvatar(); + } + + public static function setBannerFromPath(mixed $banner_path, User $user) + { + if( !is_readable($banner_path) ) + return false; + + $bannerService = \XF::service(ProfileBannerService::class, $user); + if( !$bannerService->setImage($banner_path) ) + return false; + + return $bannerService->updateBanner(); + } + + +} \ No newline at end of file diff --git a/Import/Importer/RHPZForums.php b/Import/Importer/RHPZForums.php new file mode 100644 index 0000000..f0d2282 --- /dev/null +++ b/Import/Importer/RHPZForums.php @@ -0,0 +1,97 @@ + 'XenForo', + 'source' => 'RHPZ Forums (XF)' + ]; + } + + public function stepUserGroups(StepState $state) + { + $map = $this->getMigrationSetting('old_xf_group_to_xf_group'); + foreach( $map as $oldId => $newId ){ + $this->log('user_group', $oldId, $newId); + $state->imported++; + } + + return $state->complete(); + } + + public function stepUserFields(StepState $state) + { + return $state->complete(); + } + + public function stepUsers(StepState $state, array $stepConfig, $maxTime) + { + $rows = $this->sourceDb->fetchAll("SELECT user_id FROM xf_user ORDER BY user_id" ); + + foreach ( $rows as $row ) { + $oldId = $row['user_id']; + $newId = $this->getNewUserId($oldId); + + if( $newId ){ + $this->log('user', $oldId, $newId); + $state->imported++; + } + } + + return $state->complete(); + } + + public function stepAvatars(StepState $state, array $stepConfig, $maxTime) + { + return $state->complete(); + } + + public function stepNodes(StepState $state) + { + $map = $this->getMigrationSetting('old_xf_node_to_new_xf_node'); + foreach( $map as $oldId => $newId ){ + $this->log('node', $oldId, $newId); + $state->imported++; + } + + return $state->complete(); + } + + public function stepNodePermissions(StepState $state) + { + return $state->complete(); + } + + public function stepModerators(StepState $state) + { + return $state->complete(); + } + + private function getMigrationSetting(string $key): mixed + { + $db = Laravel::db(); + if( !$db ) + return null; + + $row = $db->fetchOne("SELECT value FROM migration_settings WHERE `key` = ? ", [$key]); + return $row ? json_decode( $row, true ) : []; + } + + private function getNewUserId(int $oldId): ?int + { + $db = Laravel::db(); + if( !$db ) + return null; + + $row = $db->fetchOne("SELECT user_id FROM migration_user_plan WHERE xf_user_id = ?", [$oldId]); + return $row ? (int) $row : null; + } +} \ No newline at end of file diff --git a/Listener.php b/Listener.php index 0413895..f18a76a 100644 --- a/Listener.php +++ b/Listener.php @@ -2,8 +2,24 @@ namespace RomhackPlaza\Master; +use XF\Container; +use XF\Import\Manager; +use XF\Mvc\Renderer\AbstractRenderer; +use XF\Mvc\Reply\AbstractReply; +use XF\SubContainer\Import; + class Listener { + + public static function importImporterClasses(Import $container, Container $parentContainer, array &$importers) + { + if( \XF::isAddOnActive('XFI') ) + $importers = array_merge( + $importers, + Manager::getImporterShortNamesForType('RomhackPlaza/Master') + ); + } + public static function criteriaUser(string $rule, array $data, \XF\Entity\User $user, bool &$returnValue ){ switch( $rule ){ case 'rhpz_entry_count': @@ -20,4 +36,38 @@ class Listener break; } } + + /** + * Credits to Kirby for the guest part. + * @link https://xenforo.com/community/resources/style-variation-default.9504/ + * + * @param \XF\App $app + * @param array $params + * @param AbstractReply $reply + * @param AbstractRenderer $renderer + * + * @return void + * @throws \XF\PrintableException + */ + public static function checkStyleVariation( \XF\App $app, array &$params, AbstractReply $reply, AbstractRenderer $renderer ) + { + $user = \XF::visitor(); + if( $user->user_id !== 0 ){ // Logged in. + if( $user->style_variation !== 'default' && $user->style_variation !== 'alternate' ){ + $user->style_variation = 'default'; + $user->save(); + } + } else { + $cookie = $app->request()->getCookie('style_variation'); + if( $cookie !== 'default' && $cookie !== 'alternate' ){ + $app->response()->setCookie('style_variation', 'default', 86400 * 365); + } + if( $user->style_variation === '' ){ + $style = $app->templater()->getStyle(); + if( $style->isVariationsEnabled() ){ + $user->setAsSaved('style_variation', 'default'); + } + } + } + } } \ No newline at end of file diff --git a/_output/code_event_listeners/_metadata.json b/_output/code_event_listeners/_metadata.json index 765d1ea..c5e6508 100644 --- a/_output/code_event_listeners/_metadata.json +++ b/_output/code_event_listeners/_metadata.json @@ -1,5 +1,11 @@ { + "app_pub_render_page_c6149e27cfdc21a20c8047e0e5cd5503.json": { + "hash": "95a8be583623f99ff47eef23a658e459" + }, "criteria_user_0cfa5d0143e6477a6bc20b11e255e850.json": { "hash": "f29b40ef7a5b420b212848744fd9b7db" + }, + "import_importer_classes_64d8f27f58ba02af52958c1d4f94f812.json": { + "hash": "2ff08f9036890eb77d7bc1c7fc02fc4c" } } \ No newline at end of file diff --git a/_output/code_event_listeners/app_pub_render_page_c6149e27cfdc21a20c8047e0e5cd5503.json b/_output/code_event_listeners/app_pub_render_page_c6149e27cfdc21a20c8047e0e5cd5503.json new file mode 100644 index 0000000..dcb2a2c --- /dev/null +++ b/_output/code_event_listeners/app_pub_render_page_c6149e27cfdc21a20c8047e0e5cd5503.json @@ -0,0 +1,9 @@ +{ + "event_id": "app_pub_render_page", + "execute_order": 10, + "callback_class": "RomhackPlaza\\Master\\Listener", + "callback_method": "checkStyleVariation", + "active": true, + "hint": "", + "description": "" +} \ No newline at end of file diff --git a/_output/code_event_listeners/import_importer_classes_64d8f27f58ba02af52958c1d4f94f812.json b/_output/code_event_listeners/import_importer_classes_64d8f27f58ba02af52958c1d4f94f812.json new file mode 100644 index 0000000..7723f3c --- /dev/null +++ b/_output/code_event_listeners/import_importer_classes_64d8f27f58ba02af52958c1d4f94f812.json @@ -0,0 +1,9 @@ +{ + "event_id": "import_importer_classes", + "execute_order": 15, + "callback_class": "RomhackPlaza\\Master\\Listener", + "callback_method": "importImporterClasses", + "active": true, + "hint": "", + "description": "" +} \ No newline at end of file diff --git a/_output/navigation/_metadata.json b/_output/navigation/_metadata.json index 761cae1..445a2d9 100644 --- a/_output/navigation/_metadata.json +++ b/_output/navigation/_metadata.json @@ -41,11 +41,8 @@ "pages.json": { "hash": "8d75bf99b2fb6528f84433f4519d4da3" }, - "rom_checker.json": { - "hash": "c9349db6120520e82d02b793a30e67ce" - }, "rom_hasher.json": { - "hash": "e14613a1bd0f1e1fadc084a009801570" + "hash": "f322c39dd3ea03343ab626a1da796c55" }, "rom_patcher.json": { "hash": "dff75392eea1fdffdaec193913d5d8a0" diff --git a/_output/navigation/rom_checker.json b/_output/navigation/rom_checker.json deleted file mode 100644 index da65b88..0000000 --- a/_output/navigation/rom_checker.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent_navigation_id": "tools", - "display_order": 300, - "navigation_type_id": "basic", - "type_config": { - "link": "{$xf.options.homePageUrl}/tools/rom-checker", - "display_condition": "", - "extra_attributes": { - "icon": "check" - } - }, - "enabled": true -} \ No newline at end of file diff --git a/_output/navigation/rom_hasher.json b/_output/navigation/rom_hasher.json index cb7554f..3cd079c 100644 --- a/_output/navigation/rom_hasher.json +++ b/_output/navigation/rom_hasher.json @@ -3,7 +3,7 @@ "display_order": 200, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/tools/rom-hasher", + "link": "{$xf.options.homePageUrl}/hash", "display_condition": "", "extra_attributes": { "icon": "hash" diff --git a/_output/option_hint.php b/_output/option_hint.php index 8fee43d..f3bb474 100644 --- a/_output/option_hint.php +++ b/_output/option_hint.php @@ -13,6 +13,7 @@ namespace XF; /** * @property non-negative-int|null $rhpz_club_node_id Club Parent Node ID * @property string|null $rhpz_delete_account_master_key Delete account Master key + * @property bool|null $rhpz_enable_migration Enable Migration functions */ class Options { diff --git a/_output/options/_metadata.json b/_output/options/_metadata.json index d4f4f29..24f0207 100644 --- a/_output/options/_metadata.json +++ b/_output/options/_metadata.json @@ -4,5 +4,8 @@ }, "rhpz_delete_account_master_key.json": { "hash": "d649af68f404568ba3c06cc0a7121649" + }, + "rhpz_enable_migration.json": { + "hash": "6a3f9a6223e06f02636e434bae26cc93" } } \ No newline at end of file diff --git a/_output/options/rhpz_enable_migration.json b/_output/options/rhpz_enable_migration.json new file mode 100644 index 0000000..549b4c9 --- /dev/null +++ b/_output/options/rhpz_enable_migration.json @@ -0,0 +1,13 @@ +{ + "edit_format": "onoff", + "edit_format_params": "", + "data_type": "boolean", + "sub_options": [], + "validation_class": "", + "validation_method": "", + "advanced": true, + "default_value": "0", + "relations": { + "romhackplaza": 500 + } +} \ No newline at end of file diff --git a/_output/phrases/_metadata.json b/_output/phrases/_metadata.json index 13925ba..301278a 100644 --- a/_output/phrases/_metadata.json +++ b/_output/phrases/_metadata.json @@ -23,6 +23,12 @@ "version_string": "1.0.0", "hash": "15d96c48f857b975c051d7c98b13a385" }, + "entries.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "bc14b0a9c516310fc195a778937cc0a0" + }, "nav.about.txt": { "global_cache": false, "version_id": 1000000, @@ -107,12 +113,6 @@ "version_string": "1.0.0", "hash": "453aceb005ceaf54a47da15fee8b2a26" }, - "nav.rom_checker.txt": { - "global_cache": false, - "version_id": 1000000, - "version_string": "1.0.0", - "hash": "f5e8c49f0487c68231a8804df2379cc5" - }, "nav.rom_hasher.txt": { "global_cache": false, "version_id": 1000000, @@ -155,6 +155,12 @@ "version_string": "1.0.0", "hash": "8b275759f2215b3b242de29110f05a4c" }, + "option.rhpz_enable_migration.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "5c647f124187d520df70e6c1610fb041" + }, "option_explain.rhpz_club_node_id.txt": { "global_cache": false, "version_id": 1000000, @@ -167,6 +173,12 @@ "version_string": "1.0.0", "hash": "d41d8cd98f00b204e9800998ecf8427e" }, + "option_explain.rhpz_enable_migration.txt": { + "global_cache": false, + "version_id": 1000000, + "version_string": "1.0.0", + "hash": "d98b161589c31532e68fe26daa70dc32" + }, "option_group.romhackplaza.txt": { "global_cache": false, "version_id": 1000000, diff --git a/_output/phrases/entries.txt b/_output/phrases/entries.txt new file mode 100644 index 0000000..771ee94 --- /dev/null +++ b/_output/phrases/entries.txt @@ -0,0 +1 @@ +Entries \ No newline at end of file diff --git a/_output/phrases/nav.rom_checker.txt b/_output/phrases/nav.rom_checker.txt deleted file mode 100644 index ffb5df8..0000000 --- a/_output/phrases/nav.rom_checker.txt +++ /dev/null @@ -1 +0,0 @@ -ROM Checker \ No newline at end of file diff --git a/_output/phrases/option.rhpz_enable_migration.txt b/_output/phrases/option.rhpz_enable_migration.txt new file mode 100644 index 0000000..fc35068 --- /dev/null +++ b/_output/phrases/option.rhpz_enable_migration.txt @@ -0,0 +1 @@ +Enable Migration functions \ No newline at end of file diff --git a/_output/phrases/option_explain.rhpz_enable_migration.txt b/_output/phrases/option_explain.rhpz_enable_migration.txt new file mode 100644 index 0000000..0f58791 --- /dev/null +++ b/_output/phrases/option_explain.rhpz_enable_migration.txt @@ -0,0 +1 @@ +Enable migration endpoints and other things. \ No newline at end of file diff --git a/_output/routes/_metadata.json b/_output/routes/_metadata.json index f24d27b..803415d 100644 --- a/_output/routes/_metadata.json +++ b/_output/routes/_metadata.json @@ -1,4 +1,7 @@ { + "api_migrate_.json": { + "hash": "df6fcab95396a546b48a38eb9561b68f" + }, "api_romhackplaza_entry_.json": { "hash": "5f1609f559980b44af09fd85c3b34a30" }, diff --git a/_output/routes/api_migrate_.json b/_output/routes/api_migrate_.json new file mode 100644 index 0000000..70006e4 --- /dev/null +++ b/_output/routes/api_migrate_.json @@ -0,0 +1,11 @@ +{ + "route_type": "api", + "route_prefix": "migrate", + "sub_name": "", + "format": "", + "build_class": "", + "build_method": "", + "controller": "RomhackPlaza\\Master:Migrate", + "context": "", + "action_prefix": "" +} \ No newline at end of file diff --git a/_output/template_modifications/_metadata.json b/_output/template_modifications/_metadata.json index 310ec3c..04696b7 100644 --- a/_output/template_modifications/_metadata.json +++ b/_output/template_modifications/_metadata.json @@ -22,5 +22,14 @@ }, "public/rhpz_forum_overview_wrapper_search_button.json": { "hash": "af109f16aca8a12c4f8496fc4431f4b8" + }, + "public/rhpz_member_macros_member_stat_pairs_entry_count.json": { + "hash": "3d744e57f81abeb7f2d8291404f1e5b3" + }, + "public/rhpz_member_view_add_entry_tab.json": { + "hash": "35151043dca0be7987a72ee8b1cffc6f" + }, + "public/rhpz_member_view_add_entry_tabpanel.json": { + "hash": "5fcc29178d06fc924bdb604734cc9c59" } } \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_member_macros_member_stat_pairs_entry_count.json b/_output/template_modifications/public/rhpz_member_macros_member_stat_pairs_entry_count.json new file mode 100644 index 0000000..9a5d02b --- /dev/null +++ b/_output/template_modifications/public/rhpz_member_macros_member_stat_pairs_entry_count.json @@ -0,0 +1,9 @@ +{ + "template": "member_macros", + "description": "Add RHPZ Entry count on member profile page", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "
    \n\t
    {{ phrase('entries') }}
    \n\t
    \n\t\t{$user.rhpz_entry_count|number}\n\t
    \n
    " +} \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_member_view_add_entry_tab.json b/_output/template_modifications/public/rhpz_member_view_add_entry_tab.json new file mode 100644 index 0000000..da13520 --- /dev/null +++ b/_output/template_modifications/public/rhpz_member_view_add_entry_tab.json @@ -0,0 +1,9 @@ +{ + "template": "member_view", + "description": "Add entry tab on members page", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "{{ phrase('entries') }}\n$0" +} \ No newline at end of file diff --git a/_output/template_modifications/public/rhpz_member_view_add_entry_tabpanel.json b/_output/template_modifications/public/rhpz_member_view_add_entry_tabpanel.json new file mode 100644 index 0000000..6653e31 --- /dev/null +++ b/_output/template_modifications/public/rhpz_member_view_add_entry_tabpanel.json @@ -0,0 +1,9 @@ +{ + "template": "member_view", + "description": "Add Entry tab panel", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "
  • \n\tGo to this page\n
  • \n$0" +} \ No newline at end of file From 2222d88b1dbda40fb83816e7950ea6f7bbeea514 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Wed, 24 Jun 2026 12:39:01 +0200 Subject: [PATCH 7/9] Fix migration problems --- _data/activity_summary_definitions.xml | 2 + _data/admin_navigation.xml | 2 + _data/admin_permission.xml | 2 + _data/advertising_positions.xml | 2 + _data/api_scopes.xml | 2 + _data/bb_code_media_sites.xml | 2 + _data/bb_codes.xml | 2 + _data/class_extensions.xml | 10 + _data/code_event_listeners.xml | 6 + _data/code_events.xml | 2 + _data/content_type_fields.xml | 11 + _data/cron.xml | 2 + _data/help_pages.xml | 2 + _data/member_stats.xml | 2 + _data/navigation.xml | 22 + _data/option_groups.xml | 4 + _data/options.xml | 15 + _data/permission_interface_groups.xml | 4 + _data/permissions.xml | 14 + _data/phrases.xml | 47 ++ _data/routes.xml | 9 + _data/style_properties.xml | 2 + _data/style_property_groups.xml | 2 + _data/template_modifications.xml | 102 ++++ _data/templates.xml | 666 +++++++++++++++++++++++++ _data/widget_definitions.xml | 2 + _data/widget_positions.xml | 2 + 27 files changed, 940 insertions(+) create mode 100644 _data/activity_summary_definitions.xml create mode 100644 _data/admin_navigation.xml create mode 100644 _data/admin_permission.xml create mode 100644 _data/advertising_positions.xml create mode 100644 _data/api_scopes.xml create mode 100644 _data/bb_code_media_sites.xml create mode 100644 _data/bb_codes.xml create mode 100644 _data/class_extensions.xml create mode 100644 _data/code_event_listeners.xml create mode 100644 _data/code_events.xml create mode 100644 _data/content_type_fields.xml create mode 100644 _data/cron.xml create mode 100644 _data/help_pages.xml create mode 100644 _data/member_stats.xml create mode 100644 _data/navigation.xml create mode 100644 _data/option_groups.xml create mode 100644 _data/options.xml create mode 100644 _data/permission_interface_groups.xml create mode 100644 _data/permissions.xml create mode 100644 _data/phrases.xml create mode 100644 _data/routes.xml create mode 100644 _data/style_properties.xml create mode 100644 _data/style_property_groups.xml create mode 100644 _data/template_modifications.xml create mode 100644 _data/templates.xml create mode 100644 _data/widget_definitions.xml create mode 100644 _data/widget_positions.xml diff --git a/_data/activity_summary_definitions.xml b/_data/activity_summary_definitions.xml new file mode 100644 index 0000000..a55af11 --- /dev/null +++ b/_data/activity_summary_definitions.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/admin_navigation.xml b/_data/admin_navigation.xml new file mode 100644 index 0000000..8aa506b --- /dev/null +++ b/_data/admin_navigation.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/admin_permission.xml b/_data/admin_permission.xml new file mode 100644 index 0000000..67760e7 --- /dev/null +++ b/_data/admin_permission.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/advertising_positions.xml b/_data/advertising_positions.xml new file mode 100644 index 0000000..32059fa --- /dev/null +++ b/_data/advertising_positions.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/api_scopes.xml b/_data/api_scopes.xml new file mode 100644 index 0000000..3510b36 --- /dev/null +++ b/_data/api_scopes.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/bb_code_media_sites.xml b/_data/bb_code_media_sites.xml new file mode 100644 index 0000000..bdf7d27 --- /dev/null +++ b/_data/bb_code_media_sites.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/bb_codes.xml b/_data/bb_codes.xml new file mode 100644 index 0000000..8c337bf --- /dev/null +++ b/_data/bb_codes.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/class_extensions.xml b/_data/class_extensions.xml new file mode 100644 index 0000000..0c507eb --- /dev/null +++ b/_data/class_extensions.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/_data/code_event_listeners.xml b/_data/code_event_listeners.xml new file mode 100644 index 0000000..c501f76 --- /dev/null +++ b/_data/code_event_listeners.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/_data/code_events.xml b/_data/code_events.xml new file mode 100644 index 0000000..7752d3e --- /dev/null +++ b/_data/code_events.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/content_type_fields.xml b/_data/content_type_fields.xml new file mode 100644 index 0000000..8e94d77 --- /dev/null +++ b/_data/content_type_fields.xml @@ -0,0 +1,11 @@ + + + RomhackPlaza\Master\ApprovalQueue\Club + RomhackPlaza\Master\Entity\Club + RomhackPlaza\Master\ApprovalQueue\EntryFeaturedRequest + RomhackPlaza\Master\Entity\EntryFeaturedRequest + RomhackPlaza\Master\Entity\Entry + RomhackPlaza\Master\Report\Entry + RomhackPlaza\Master\Entity\News + RomhackPlaza\Master\Report\News + diff --git a/_data/cron.xml b/_data/cron.xml new file mode 100644 index 0000000..b45f056 --- /dev/null +++ b/_data/cron.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/help_pages.xml b/_data/help_pages.xml new file mode 100644 index 0000000..31828b1 --- /dev/null +++ b/_data/help_pages.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/member_stats.xml b/_data/member_stats.xml new file mode 100644 index 0000000..a80a38b --- /dev/null +++ b/_data/member_stats.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/navigation.xml b/_data/navigation.xml new file mode 100644 index 0000000..7d2bc0f --- /dev/null +++ b/_data/navigation.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/_data/option_groups.xml b/_data/option_groups.xml new file mode 100644 index 0000000..58b0f88 --- /dev/null +++ b/_data/option_groups.xml @@ -0,0 +1,4 @@ + + + + diff --git a/_data/options.xml b/_data/options.xml new file mode 100644 index 0000000..726cef0 --- /dev/null +++ b/_data/options.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/_data/permission_interface_groups.xml b/_data/permission_interface_groups.xml new file mode 100644 index 0000000..8e7533e --- /dev/null +++ b/_data/permission_interface_groups.xml @@ -0,0 +1,4 @@ + + + + diff --git a/_data/permissions.xml b/_data/permissions.xml new file mode 100644 index 0000000..4f7ab5a --- /dev/null +++ b/_data/permissions.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/_data/phrases.xml b/_data/phrases.xml new file mode 100644 index 0000000..9ab7f1b --- /dev/null +++ b/_data/phrases.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_data/routes.xml b/_data/routes.xml new file mode 100644 index 0000000..59306d6 --- /dev/null +++ b/_data/routes.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/_data/style_properties.xml b/_data/style_properties.xml new file mode 100644 index 0000000..231b9f0 --- /dev/null +++ b/_data/style_properties.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/style_property_groups.xml b/_data/style_property_groups.xml new file mode 100644 index 0000000..563c56d --- /dev/null +++ b/_data/style_property_groups.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/template_modifications.xml b/_data/template_modifications.xml new file mode 100644 index 0000000..9b05279 --- /dev/null +++ b/_data/template_modifications.xml @@ -0,0 +1,102 @@ + + + + ]]> + + {{ phrase('delete_account') }} + +$0]]> + + + ]]> + + + Request a club + + +$0]]> + + + + {{ phrase('new_posts') }} +
    ]]> + + {{ phrase('search') }} + ]]> + + + ]]> + +
    + + Banner {$forum.title} + +
    +]]>
    +
    + + ]]> + +
    +
    + Edit + Delete +
    +
    +]]>
    +
    + + ]]> + + +]]> + + + ]]> + +
    {{ phrase('entries') }}
    +
    + {$user.rhpz_entry_count|number} +
    +]]>
    +
    + + ]]> + {{ phrase('entries') }} +$0]]> + + + ]]> + + Go to this page + +$0]]> + + + ]]> + + {{ phrase('delete_account_codes') }} + +$0]]> + + + ]]> + +
  • +
    {{ phrase('loading...') }}
    +
  • + +$0]]>
    +
    + diff --git a/_data/templates.xml b/_data/templates.xml new file mode 100644 index 0000000..607890b --- /dev/null +++ b/_data/templates.xml @@ -0,0 +1,666 @@ + + + + + + + + + + + + diff --git a/_data/widget_definitions.xml b/_data/widget_definitions.xml new file mode 100644 index 0000000..fbdae64 --- /dev/null +++ b/_data/widget_definitions.xml @@ -0,0 +1,2 @@ + + diff --git a/_data/widget_positions.xml b/_data/widget_positions.xml new file mode 100644 index 0000000..65d80ac --- /dev/null +++ b/_data/widget_positions.xml @@ -0,0 +1,2 @@ + + From bb0658b0e54a57aa5048db483f1a2904e42845c3 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sat, 27 Jun 2026 18:57:26 +0200 Subject: [PATCH 8/9] Added NSFW compatibility --- Setup.php | 10 +++++++++- XF/Entity/User.php | 1 + XF/Pub/Controller/AccountController.php | 15 +++++++++++++++ _output/phrases/_metadata.json | 12 ++++++++++++ _output/phrases/enable_nsfw_entries.txt | 1 + _output/phrases/entries_options.txt | 1 + _output/template_modifications/_metadata.json | 3 +++ .../rhpz_account_preferences_nsfw_content.json | 9 +++++++++ addon.json | 4 ++-- 9 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 _output/phrases/enable_nsfw_entries.txt create mode 100644 _output/phrases/entries_options.txt create mode 100644 _output/template_modifications/public/rhpz_account_preferences_nsfw_content.json diff --git a/Setup.php b/Setup.php index f38e2e7..2a80881 100644 --- a/Setup.php +++ b/Setup.php @@ -21,6 +21,7 @@ class Setup extends AbstractSetup { $this->schemaManager()->alterTable('xf_user', function (\XF\Db\Schema\Alter $table) { $table->addColumn('rhpz_entry_count', 'int')->setDefault(0); + $table->addColumn('nsfw_content', 'int')->setDefault(0); }); } @@ -56,10 +57,17 @@ class Setup extends AbstractSetup }); } + public function upgrade1010070Step1(): void + { + $this->schemaManager()->alterTable('xf_user', function (\XF\Db\Schema\Alter $table) { + $table->addColumn('nsfw_content', 'int')->setDefault(0); + }); + } + public function uninstallStep1(): void { $this->schemaManager()->alterTable('xf_user', function($table) { - $table->dropColumns(['rhpz_entry_count']); + $table->dropColumns(['rhpz_entry_count', 'nsfw_content']); }); } diff --git a/XF/Entity/User.php b/XF/Entity/User.php index bd4ef44..ec069d1 100644 --- a/XF/Entity/User.php +++ b/XF/Entity/User.php @@ -12,6 +12,7 @@ class User extends XFCP_User $structure = parent::getStructure($structure); $structure->columns['rhpz_entry_count'] = [ 'type' => self::UINT, 'default' => 0 ]; + $structure->columns['nsfw_content'] = [ 'type' => self::BOOL, 'default' => 0 ]; return $structure; } diff --git a/XF/Pub/Controller/AccountController.php b/XF/Pub/Controller/AccountController.php index ac78034..ce6187c 100644 --- a/XF/Pub/Controller/AccountController.php +++ b/XF/Pub/Controller/AccountController.php @@ -3,6 +3,7 @@ namespace RomhackPlaza\Master\XF\Pub\Controller; use RomhackPlaza\Master\Service\DeleteAccount\CodeService; +use XF\Entity\User; class AccountController extends XFCP_AccountController { @@ -22,4 +23,18 @@ class AccountController extends XFCP_AccountController return $this->addAccountWrapperParams($view, 'delete_account'); } + protected function preferencesSaveProcess(User $visitor) + { + $form = parent::preferencesSaveProcess($visitor); + + $input = $this->filter([ + 'user' => [ + 'nsfw_content' => 'bool', + ] + ]); + + $form->basicEntitySave($visitor, $input['user'] ); + return $form; + } + } \ No newline at end of file diff --git a/_output/phrases/_metadata.json b/_output/phrases/_metadata.json index 301278a..f604db3 100644 --- a/_output/phrases/_metadata.json +++ b/_output/phrases/_metadata.json @@ -23,12 +23,24 @@ "version_string": "1.0.0", "hash": "15d96c48f857b975c051d7c98b13a385" }, + "enable_nsfw_entries.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "5fe4c9ee5afb3f3b3125508f27c245b6" + }, "entries.txt": { "global_cache": false, "version_id": 1000000, "version_string": "1.0.0", "hash": "bc14b0a9c516310fc195a778937cc0a0" }, + "entries_options.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "7c72b58cc8011ac1c23376fffb33f0da" + }, "nav.about.txt": { "global_cache": false, "version_id": 1000000, diff --git a/_output/phrases/enable_nsfw_entries.txt b/_output/phrases/enable_nsfw_entries.txt new file mode 100644 index 0000000..1453e68 --- /dev/null +++ b/_output/phrases/enable_nsfw_entries.txt @@ -0,0 +1 @@ +Enable NSFW Entries \ No newline at end of file diff --git a/_output/phrases/entries_options.txt b/_output/phrases/entries_options.txt new file mode 100644 index 0000000..55b2e70 --- /dev/null +++ b/_output/phrases/entries_options.txt @@ -0,0 +1 @@ +Entries options \ No newline at end of file diff --git a/_output/template_modifications/_metadata.json b/_output/template_modifications/_metadata.json index 04696b7..5d7047c 100644 --- a/_output/template_modifications/_metadata.json +++ b/_output/template_modifications/_metadata.json @@ -14,6 +14,9 @@ "public/rhpz_above_thread_list_clubs_buttons.json": { "hash": "c783001e00f7a63389c9ae988012f5fe" }, + "public/rhpz_account_preferences_nsfw_content.json": { + "hash": "9feae814b9fa8f40a08e1b50e2d410c5" + }, "public/rhpz_account_wrapper_delete_account.json": { "hash": "6594c0474a9b3e737a10dbd9c531521e" }, diff --git a/_output/template_modifications/public/rhpz_account_preferences_nsfw_content.json b/_output/template_modifications/public/rhpz_account_preferences_nsfw_content.json new file mode 100644 index 0000000..ebc8561 --- /dev/null +++ b/_output/template_modifications/public/rhpz_account_preferences_nsfw_content.json @@ -0,0 +1,9 @@ +{ + "template": "account_preferences", + "description": "Add NSFW Content field to the settings", + "execution_order": 10, + "enabled": true, + "action": "str_replace", + "find": "", + "replace": "\n\t\n\t\n\n$0" +} \ No newline at end of file diff --git a/addon.json b/addon.json index bf733c6..1f8aaba 100644 --- a/addon.json +++ b/addon.json @@ -2,8 +2,8 @@ "legacy_addon_id": "", "title": "RomhackPlaza Master Addon", "description": "", - "version_id": 1000000, - "version_string": "1.0.0", + "version_id": 1010070, + "version_string": "1.1.0", "dev": "", "dev_url": "", "faq_url": "", From afd0f434db4ee7989fd30fec19c0c03605b79f44 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Sun, 28 Jun 2026 14:07:20 +0200 Subject: [PATCH 9/9] Update menu entries and fixes some profile picture problems. Added help pages too. --- _data/phrases.xml | 2 + _data/template_modifications.xml | 9 +++ _output/help_pages/_metadata.json | 17 ++++ _output/help_pages/about.json | 8 ++ _output/help_pages/delete_my_data.json | 8 ++ _output/help_pages/dmca.json | 8 ++ .../help_pages/how_to_become_verified.json | 8 ++ _output/help_pages/takedown.json | 8 ++ _output/navigation/_metadata.json | 11 ++- _output/navigation/about.json | 2 +- _output/navigation/discord.json | 2 +- _output/navigation/learn_romhacking.json | 2 +- _output/navigation/legal_pages.json | 2 +- _output/navigation/support_us.json | 15 ++++ _output/phrases/_metadata.json | 78 ++++++++++++++++++- _output/phrases/help_page_desc.about.txt | 1 + .../phrases/help_page_desc.delete_my_data.txt | 1 + _output/phrases/help_page_desc.dmca.txt | 1 + .../help_page_desc.how_to_become_verified.txt | 1 + _output/phrases/help_page_desc.takedown.txt | 1 + _output/phrases/help_page_title.about.txt | 1 + .../help_page_title.delete_my_data.txt | 1 + _output/phrases/help_page_title.dmca.txt | 1 + ...help_page_title.how_to_become_verified.txt | 1 + _output/phrases/help_page_title.takedown.txt | 1 + _output/phrases/logout.txt | 1 + _output/phrases/nav.legal_pages.txt | 2 +- _output/phrases/nav.support_us.txt | 1 + _output/templates/_metadata.json | 25 ++++++ .../templates/public/_help_page_about.html | 19 +++++ .../public/_help_page_delete_my_data.html | 15 ++++ _output/templates/public/_help_page_dmca.html | 23 ++++++ .../_help_page_how_to_become_verified.html | 7 ++ .../templates/public/_help_page_takedown.html | 22 ++++++ 34 files changed, 293 insertions(+), 12 deletions(-) create mode 100644 _output/help_pages/_metadata.json create mode 100644 _output/help_pages/about.json create mode 100644 _output/help_pages/delete_my_data.json create mode 100644 _output/help_pages/dmca.json create mode 100644 _output/help_pages/how_to_become_verified.json create mode 100644 _output/help_pages/takedown.json create mode 100644 _output/navigation/support_us.json create mode 100644 _output/phrases/help_page_desc.about.txt create mode 100644 _output/phrases/help_page_desc.delete_my_data.txt create mode 100644 _output/phrases/help_page_desc.dmca.txt create mode 100644 _output/phrases/help_page_desc.how_to_become_verified.txt create mode 100644 _output/phrases/help_page_desc.takedown.txt create mode 100644 _output/phrases/help_page_title.about.txt create mode 100644 _output/phrases/help_page_title.delete_my_data.txt create mode 100644 _output/phrases/help_page_title.dmca.txt create mode 100644 _output/phrases/help_page_title.how_to_become_verified.txt create mode 100644 _output/phrases/help_page_title.takedown.txt create mode 100644 _output/phrases/logout.txt create mode 100644 _output/phrases/nav.support_us.txt create mode 100644 _output/templates/public/_help_page_about.html create mode 100644 _output/templates/public/_help_page_delete_my_data.html create mode 100644 _output/templates/public/_help_page_dmca.html create mode 100644 _output/templates/public/_help_page_how_to_become_verified.html create mode 100644 _output/templates/public/_help_page_takedown.html diff --git a/_data/phrases.xml b/_data/phrases.xml index 9ab7f1b..9febf13 100644 --- a/_data/phrases.xml +++ b/_data/phrases.xml @@ -4,7 +4,9 @@ + + diff --git a/_data/template_modifications.xml b/_data/template_modifications.xml index 9b05279..9caa38b 100644 --- a/_data/template_modifications.xml +++ b/_data/template_modifications.xml @@ -1,5 +1,14 @@ + + ]]> + + + + +$0]]> + ]]> diff --git a/_output/help_pages/_metadata.json b/_output/help_pages/_metadata.json new file mode 100644 index 0000000..981c737 --- /dev/null +++ b/_output/help_pages/_metadata.json @@ -0,0 +1,17 @@ +{ + "about.json": { + "hash": "d2d00802b4114e28d0a69fba02973a3d" + }, + "delete_my_data.json": { + "hash": "f1eb8202bf076a34bc774c055cb9e7eb" + }, + "dmca.json": { + "hash": "e6dcff244e3981ecbc31e042315d191a" + }, + "how_to_become_verified.json": { + "hash": "4fa48e94d5179225b49d4d0e19daa8e9" + }, + "takedown.json": { + "hash": "13a1dc2ff2041b03aac5a66cc21de7c4" + } +} \ No newline at end of file diff --git a/_output/help_pages/about.json b/_output/help_pages/about.json new file mode 100644 index 0000000..14ccb4e --- /dev/null +++ b/_output/help_pages/about.json @@ -0,0 +1,8 @@ +{ + "page_name": "about", + "display_order": 10, + "callback_class": "", + "callback_method": "", + "advanced_mode": false, + "active": true +} \ No newline at end of file diff --git a/_output/help_pages/delete_my_data.json b/_output/help_pages/delete_my_data.json new file mode 100644 index 0000000..35e18d3 --- /dev/null +++ b/_output/help_pages/delete_my_data.json @@ -0,0 +1,8 @@ +{ + "page_name": "delete-my-data", + "display_order": 10, + "callback_class": "", + "callback_method": "", + "advanced_mode": false, + "active": true +} \ No newline at end of file diff --git a/_output/help_pages/dmca.json b/_output/help_pages/dmca.json new file mode 100644 index 0000000..cfa9ca5 --- /dev/null +++ b/_output/help_pages/dmca.json @@ -0,0 +1,8 @@ +{ + "page_name": "dmca", + "display_order": 50, + "callback_class": "", + "callback_method": "", + "advanced_mode": false, + "active": true +} \ No newline at end of file diff --git a/_output/help_pages/how_to_become_verified.json b/_output/help_pages/how_to_become_verified.json new file mode 100644 index 0000000..b508fa9 --- /dev/null +++ b/_output/help_pages/how_to_become_verified.json @@ -0,0 +1,8 @@ +{ + "page_name": "how-to-become-verified", + "display_order": 20, + "callback_class": "", + "callback_method": "", + "advanced_mode": false, + "active": true +} \ No newline at end of file diff --git a/_output/help_pages/takedown.json b/_output/help_pages/takedown.json new file mode 100644 index 0000000..3b49229 --- /dev/null +++ b/_output/help_pages/takedown.json @@ -0,0 +1,8 @@ +{ + "page_name": "takedown", + "display_order": 40, + "callback_class": "", + "callback_method": "", + "advanced_mode": false, + "active": true +} \ No newline at end of file diff --git a/_output/navigation/_metadata.json b/_output/navigation/_metadata.json index 445a2d9..8256b1a 100644 --- a/_output/navigation/_metadata.json +++ b/_output/navigation/_metadata.json @@ -1,6 +1,6 @@ { "about.json": { - "hash": "362cdca71eb4d21d7b9290ffc8f0df57" + "hash": "6af7d9983ab28cb4b2975a1cd0059f9f" }, "clubs.json": { "hash": "e7ddced6269072f7db774f09424d671c" @@ -15,7 +15,7 @@ "hash": "604cabbdf4fb4fd941dc6123eb119165" }, "discord.json": { - "hash": "37b3a139a26e30bd558de47b9e364d41" + "hash": "225fd5b2a01edb9d28b142293207943a" }, "drafts.json": { "hash": "bea14e944290aeb07659374fa487d61c" @@ -27,10 +27,10 @@ "hash": "4f55ee2e4a49e82c18e9beab428ab0ee" }, "learn_romhacking.json": { - "hash": "3da66fadac2c1aa805e639d727e36223" + "hash": "2a2086e4b84a08f921d1795aca7f3913" }, "legal_pages.json": { - "hash": "34ae35915e620f1f0b5d88dcd25a5b59" + "hash": "cd77592a612aa262580b1ad4eb0490dd" }, "members.json": { "hash": "cad1568d161bea1a7dd1f286b8788e2d" @@ -50,6 +50,9 @@ "submissions_queue.json": { "hash": "071c745afd8f28cf9505702496f72a18" }, + "support_us.json": { + "hash": "bc0c8ad00084960abc5325c31849c543" + }, "tools.json": { "hash": "3d56ca10d6cf3ff772e9ce92d200f2f8" }, diff --git a/_output/navigation/about.json b/_output/navigation/about.json index 836d989..1d7feb0 100644 --- a/_output/navigation/about.json +++ b/_output/navigation/about.json @@ -3,7 +3,7 @@ "display_order": 200, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/pages/about", + "link": "{{ link('help/about') }}", "display_condition": "", "extra_attributes": { "icon": "info" diff --git a/_output/navigation/discord.json b/_output/navigation/discord.json index 4a141f0..dc4176e 100644 --- a/_output/navigation/discord.json +++ b/_output/navigation/discord.json @@ -3,7 +3,7 @@ "display_order": 300, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/discord", + "link": "https://discord.gg/5CKzeWmZZU", "display_condition": "", "extra_attributes": { "icon": "messages-square" diff --git a/_output/navigation/learn_romhacking.json b/_output/navigation/learn_romhacking.json index b91b196..b96d917 100644 --- a/_output/navigation/learn_romhacking.json +++ b/_output/navigation/learn_romhacking.json @@ -3,7 +3,7 @@ "display_order": 100, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/pages/learn", + "link": "{{ link('help/learn-romhacking') }}", "display_condition": "", "extra_attributes": { "icon": "graduation-cap" diff --git a/_output/navigation/legal_pages.json b/_output/navigation/legal_pages.json index 9ce4d49..59de3d7 100644 --- a/_output/navigation/legal_pages.json +++ b/_output/navigation/legal_pages.json @@ -3,7 +3,7 @@ "display_order": 400, "navigation_type_id": "basic", "type_config": { - "link": "{$xf.options.homePageUrl}/pages/legal-pages", + "link": "{{ link('help') }}", "display_condition": "", "extra_attributes": { "icon": "scale" diff --git a/_output/navigation/support_us.json b/_output/navigation/support_us.json new file mode 100644 index 0000000..ae40fc8 --- /dev/null +++ b/_output/navigation/support_us.json @@ -0,0 +1,15 @@ +{ + "parent_navigation_id": "pages", + "display_order": 10, + "navigation_type_id": "basic", + "type_config": { + "link": "https://ko-fi.com/romhackplaza", + "display_condition": "", + "extra_attributes": { + "icon": "coffee", + "color": "var(--rhpz-orange)", + "target": "_blank" + } + }, + "enabled": true +} \ No newline at end of file diff --git a/_output/phrases/_metadata.json b/_output/phrases/_metadata.json index f604db3..5be3d94 100644 --- a/_output/phrases/_metadata.json +++ b/_output/phrases/_metadata.json @@ -41,6 +41,72 @@ "version_string": "1.1.0", "hash": "7c72b58cc8011ac1c23376fffb33f0da" }, + "help_page_desc.about.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "077a75f92ac9d8ed4a1bdf3a40c0f133" + }, + "help_page_desc.delete_my_data.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "c4a426cddbc0d1e2a3703cd202dde965" + }, + "help_page_desc.dmca.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "12054ccd3a006f4414c6c8afd7c20363" + }, + "help_page_desc.how_to_become_verified.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "d1f446e631cffd83b484bb0566f35a35" + }, + "help_page_desc.takedown.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "b010e0f884fe0cbc48dd20c19e026756" + }, + "help_page_title.about.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "8f7f4c1ce7a4f933663d10543562b096" + }, + "help_page_title.delete_my_data.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "17fe5faff39a2cd491cdb4a13fb1e7fc" + }, + "help_page_title.dmca.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "628ff040a9e9ff3e28dc122c5a38f8f9" + }, + "help_page_title.how_to_become_verified.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "5e92642ef830c360b71f586ad6a915e3" + }, + "help_page_title.takedown.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "509f327055d6c047a2a080a90332260c" + }, + "logout.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "0323de4f66a1700e2173e9bcdce02715" + }, "nav.about.txt": { "global_cache": false, "version_id": 1000000, @@ -103,9 +169,9 @@ }, "nav.legal_pages.txt": { "global_cache": false, - "version_id": 1000000, - "version_string": "1.0.0", - "hash": "3c409b33c2ad79df7ed112714d2092be" + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "d2b780c86b3f8e3da8af5ca3891d80c5" }, "nav.members.txt": { "global_cache": false, @@ -143,6 +209,12 @@ "version_string": "1.0.0", "hash": "15fe7b6033b3abae4d4096e7a5d21bff" }, + "nav.support_us.txt": { + "global_cache": false, + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "68af1e9d9402fee977042693b6644fe4" + }, "nav.tools.txt": { "global_cache": false, "version_id": 1000000, diff --git a/_output/phrases/help_page_desc.about.txt b/_output/phrases/help_page_desc.about.txt new file mode 100644 index 0000000..d3f8c69 --- /dev/null +++ b/_output/phrases/help_page_desc.about.txt @@ -0,0 +1 @@ +This page contains a description of our website and its philosophy \ No newline at end of file diff --git a/_output/phrases/help_page_desc.delete_my_data.txt b/_output/phrases/help_page_desc.delete_my_data.txt new file mode 100644 index 0000000..e351125 --- /dev/null +++ b/_output/phrases/help_page_desc.delete_my_data.txt @@ -0,0 +1 @@ +If you want to delete some data, please read this \ No newline at end of file diff --git a/_output/phrases/help_page_desc.dmca.txt b/_output/phrases/help_page_desc.dmca.txt new file mode 100644 index 0000000..5b789da --- /dev/null +++ b/_output/phrases/help_page_desc.dmca.txt @@ -0,0 +1 @@ +Everything you need to know about the DMCA on this site. \ No newline at end of file diff --git a/_output/phrases/help_page_desc.how_to_become_verified.txt b/_output/phrases/help_page_desc.how_to_become_verified.txt new file mode 100644 index 0000000..a5c6a42 --- /dev/null +++ b/_output/phrases/help_page_desc.how_to_become_verified.txt @@ -0,0 +1 @@ +Steps to follow to become a Verified Member \ No newline at end of file diff --git a/_output/phrases/help_page_desc.takedown.txt b/_output/phrases/help_page_desc.takedown.txt new file mode 100644 index 0000000..4748d62 --- /dev/null +++ b/_output/phrases/help_page_desc.takedown.txt @@ -0,0 +1 @@ +Everything you must know if you want write a takedown request \ No newline at end of file diff --git a/_output/phrases/help_page_title.about.txt b/_output/phrases/help_page_title.about.txt new file mode 100644 index 0000000..ae21d83 --- /dev/null +++ b/_output/phrases/help_page_title.about.txt @@ -0,0 +1 @@ +About \ No newline at end of file diff --git a/_output/phrases/help_page_title.delete_my_data.txt b/_output/phrases/help_page_title.delete_my_data.txt new file mode 100644 index 0000000..a90e427 --- /dev/null +++ b/_output/phrases/help_page_title.delete_my_data.txt @@ -0,0 +1 @@ +Delete my data \ No newline at end of file diff --git a/_output/phrases/help_page_title.dmca.txt b/_output/phrases/help_page_title.dmca.txt new file mode 100644 index 0000000..084d9a8 --- /dev/null +++ b/_output/phrases/help_page_title.dmca.txt @@ -0,0 +1 @@ +Digital Millennium Copyright Act (DMCA) Notice \ No newline at end of file diff --git a/_output/phrases/help_page_title.how_to_become_verified.txt b/_output/phrases/help_page_title.how_to_become_verified.txt new file mode 100644 index 0000000..34a8a34 --- /dev/null +++ b/_output/phrases/help_page_title.how_to_become_verified.txt @@ -0,0 +1 @@ +How to become "Verified" \ No newline at end of file diff --git a/_output/phrases/help_page_title.takedown.txt b/_output/phrases/help_page_title.takedown.txt new file mode 100644 index 0000000..2fb8199 --- /dev/null +++ b/_output/phrases/help_page_title.takedown.txt @@ -0,0 +1 @@ +Content Takedown Request \ No newline at end of file diff --git a/_output/phrases/logout.txt b/_output/phrases/logout.txt new file mode 100644 index 0000000..0fffc8f --- /dev/null +++ b/_output/phrases/logout.txt @@ -0,0 +1 @@ +Logout \ No newline at end of file diff --git a/_output/phrases/nav.legal_pages.txt b/_output/phrases/nav.legal_pages.txt index 23a0bf1..b543a74 100644 --- a/_output/phrases/nav.legal_pages.txt +++ b/_output/phrases/nav.legal_pages.txt @@ -1 +1 @@ -Legal Pages \ No newline at end of file +Help & Legal Pages \ No newline at end of file diff --git a/_output/phrases/nav.support_us.txt b/_output/phrases/nav.support_us.txt new file mode 100644 index 0000000..1f04426 --- /dev/null +++ b/_output/phrases/nav.support_us.txt @@ -0,0 +1 @@ +Support us \ No newline at end of file diff --git a/_output/templates/_metadata.json b/_output/templates/_metadata.json index a94f191..109ed7c 100644 --- a/_output/templates/_metadata.json +++ b/_output/templates/_metadata.json @@ -9,6 +9,31 @@ "version_string": "1.0.0", "hash": "cf9c69eb1bfa0821778f60e9866626a4" }, + "public/_help_page_about.html": { + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "f8d5c77616c449f0797c9a8096d7b352" + }, + "public/_help_page_delete_my_data.html": { + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "32f1a682e5729cc6e8da2c41037e604a" + }, + "public/_help_page_dmca.html": { + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "2297a9fffc0824831c5799b5df438f99" + }, + "public/_help_page_how_to_become_verified.html": { + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "11d6e1c5f5547919336b1d7db6cb78c6" + }, + "public/_help_page_takedown.html": { + "version_id": 1010070, + "version_string": "1.1.0", + "hash": "7af5316b4485b73d8d2de2eabb706f4c" + }, "public/approval_item_club_request.html": { "version_id": 1000000, "version_string": "1.0.0", diff --git a/_output/templates/public/_help_page_about.html b/_output/templates/public/_help_page_about.html new file mode 100644 index 0000000..2b10679 --- /dev/null +++ b/_output/templates/public/_help_page_about.html @@ -0,0 +1,19 @@ +
    +
    + + Site Purpose and Content Overview + + This website is dedicated to the preservation, modification, and enhancement of classic retro games. It provides a platform for discussing and sharing modifications known as "romhacks," which are custom alterations made to game ROMs. Our focus is solely on the creative and non-commercial aspects of game modification and does not involve the distribution or use of copyrighted ROM files. + + Clarification on ROMs and Hacking +
      +
    • Legal Compliance: The site does not host or distribute any original copyrighted ROM files. All content shared here pertains exclusively to modifications of games for which users already own the original ROMs. It is intended for educational, archival, and enhancement purposes only.
    • +
    • Non-Malicious Intent: The term "hacking" used on this site refers to the modification of game data and is not related to any form of malicious hacking or illegal activity. The modifications (romhacks) discussed and shared are created to enhance or alter the gameplay experience of retro games in a non-infringing manner.
    • +
    • User Responsibility: Visitors are encouraged to ensure that any game ROMs they use are legally obtained and that their use complies with applicable copyright laws. The site does not provide or endorse illegal downloads of copyrighted material.
    • +
    + Contact Information + + For any concerns or clarifications regarding the content of this site, please contact us directly. We are committed to complying with all legal requirements and ensuring that our platform remains a positive and creative space for retro gaming enthusiasts. + +
    +
    \ No newline at end of file diff --git a/_output/templates/public/_help_page_delete_my_data.html b/_output/templates/public/_help_page_delete_my_data.html new file mode 100644 index 0000000..41cbf18 --- /dev/null +++ b/_output/templates/public/_help_page_delete_my_data.html @@ -0,0 +1,15 @@ +"The right to erasure" (Articles 17 & 19 of the GDPR) state you have the right to have your data erased, without undue delay by the data controller, if you withdraw your consent to the processing. + +In here we explain in detail how to remove your data partially or completely from this site. +

    1. How to remove comments, threads:

    +Go to the post you want to delete and click on the delete button. If you want to delete a thread, delete the first post. If you can't delete a thread or a post, you can also send a report by clicking on the report button. + + +

    2. How to remove entries:

    +To remove entries you have to edit your entry and revert its Status to "draft". A draft means it's unpublished and only you can see it. You can also delete permanently an entry with the delete button. + + + +

    3. How to remove the entire account:

    +Removing the account will remove all the comments, but it will not remove the entries. They will be anonymized and assigned to a "Deleted User", if you want to delete your entries follow the step above "How to remove entries". +

    To delete your account go here

    \ No newline at end of file diff --git a/_output/templates/public/_help_page_dmca.html b/_output/templates/public/_help_page_dmca.html new file mode 100644 index 0000000..7bb7c50 --- /dev/null +++ b/_output/templates/public/_help_page_dmca.html @@ -0,0 +1,23 @@ +

    Introduction

    +Romhacks.org (hereafter referred to as "we", "us", or "our") respects the intellectual property rights of others and expects its users to do the same. We are committed to complying with the DMCA and other applicable laws. We adopt a policy of terminating, in appropriate circumstances, users who are repeat infringers. We may also, at our sole discretion, limit access to the Site and/or terminate the accounts of any users who infringe any intellectual property rights of others, whether or not there is any repeat infringement. +

    Copyright Infringement Notification

    +If you believe that your work has been copied in a way that constitutes copyright infringement, please submit your notification through our contact form, ensuring to indicate "DMCA" in the subject line. The notification should include the following information: +
      +
    1. A physical or electronic signature of a person authorized to act on behalf of the owner of an exclusive right that is allegedly infringed.
    2. +
    3. Identification of the copyrighted work claimed to have been infringed, or, if multiple copyrighted works at a single online site are covered by a single notification, a representative list of such works at that site.
    4. +
    5. Identification of the material that is claimed to be infringing or to be the subject of infringing activity and that is to be removed or access to which is to be disabled, and information reasonably sufficient to permit us to locate the material.
    6. +
    7. Information reasonably sufficient to permit us to contact the complaining party, such as an address, telephone number, and, if available, an electronic mail address at which the complaining party may be contacted.
    8. +
    9. A statement that the complaining party has a good faith belief that use of the material in the manner complained of is not authorized by the copyright owner, its agent, or the law.
    10. +
    11. A statement that the information in the notification is accurate, and under penalty of perjury, that the complaining party is authorized to act on behalf of the owner of an exclusive right that is allegedly infringed.
    12. +
    +

    Counter-Notification Procedures

    +If you believe that your material has been removed by mistake or misidentification, please submit a counter-notification through our contact form with "DMCA" in the subject line. The counter-notification should contain the following information: +
      +
    1. Your physical or electronic signature.
    2. +
    3. Identification of the material that has been removed or to which access has been disabled and the location at which the material appeared before it was removed or access to it was disabled.
    4. +
    5. A statement under penalty of perjury that you have a good faith belief that the material was removed or disabled as a result of mistake or misidentification of the material to be removed or disabled.
    6. +
    7. Your name, address, and telephone number, and a statement that you consent to the jurisdiction of the federal court for [judicial district where your address is located], and that you will accept service of process from the person who provided notification of the alleged infringement.
    8. +
    +If a counter-notice is received by us, we may send a copy of the counter-notice to the original complaining party informing that person that it may replace the removed material or cease disabling it in 10 business days. Unless the copyright owner files an action seeking a court order against the content provider, member, or user, the removed material may be replaced or access to it restored in 10 to 20 business days or more after receipt of the counter-notice, at our discretion. +

    Modifications to Policy

    +We reserve the right to modify the provisions of this DMCA notice and our copyright policy at any time. Such modifications will be effective immediately upon posting on the site. \ No newline at end of file diff --git a/_output/templates/public/_help_page_how_to_become_verified.html b/_output/templates/public/_help_page_how_to_become_verified.html new file mode 100644 index 0000000..0b3f24f --- /dev/null +++ b/_output/templates/public/_help_page_how_to_become_verified.html @@ -0,0 +1,7 @@ +You don't need to do anything special, simply submit something. +While checking your submission we'll research your user name and entry. +If you are the creator of your own entry you'll be immediately verified after the first submission. +That means your next submission will go straight to the site, no queues. +Same for editing your existing entries data, updating the files, etc. + +If you are not the creator of the hack you can also submit things. Since we already had trouble with vandalism, you automatically receive “Verified” status after 10 approved contributions. \ No newline at end of file diff --git a/_output/templates/public/_help_page_takedown.html b/_output/templates/public/_help_page_takedown.html new file mode 100644 index 0000000..61b2e4d --- /dev/null +++ b/_output/templates/public/_help_page_takedown.html @@ -0,0 +1,22 @@ +At Romhacks.org, we deeply respect the creative work of individuals and their rights over their creations. We understand that sometimes content may be shared on our platform that you, as the creator, would prefer to have removed. To make this process as smooth and friendly as possible, we offer an easy way to submit a takedown request. +

    How to Submit a Takedown Request

    +If you find that your content has been shared on Romhacks.org and you would like it to be removed, please follow these simple steps: +
      +
    1. Visit Our Contact Page: Go to our contact page.
    2. +
    3. Complete the Form: Fill out the necessary details in the form. In the subject dropdown menu, please select "Takedown" to ensure your request is processed correctly.
    4. +
    5. Use a Verifiable Email: Provide an email address where we can reach you. If we can't communicate with you and can't confirm who you are we will not go through with the removal.
    6. +
    7. Details of the Content: Include a link where the content appears here on romhacks.org. And any information to help us determine you created the hack.
    8. +
    +

    Verification Process

    +To prevent malicious or unjustified takedown requests, we will conduct a verification process to confirm that you are indeed the creator or rightful owner of the content in question. This may include: +
      +
    • Asking for additional proof of ownership or creation.
    • +
    • Verifying the details provided in the request against the content.
    • +
    • Contacting the author via social media profiles and asking him directly.
    • +
    +

    Our Commitment

    +We aim to process takedown requests promptly and efficiently, respecting both the rights of content creators and the integrity of our platform. We appreciate your cooperation and understanding in this process. +

    Questions or Concerns?

    +If you have any questions or need further assistance regarding the takedown process, please feel free to reach out to us through the same contact form or via Discord. + +We are here to help! \ No newline at end of file