From ea90f512cf887c16d02cb5afe3d405adcb51a0c5 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Tue, 3 Mar 2026 14:01:27 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20inversion=20relation=20User=E2=86=92Pro?= =?UTF-8?q?jects,=20les=20projets=20pointent=20vers=20les=20utilisateurs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le champ `users` est désormais sur le blueprint projet. Les blueprints pochet/client perdent leur champ `projects`. La logique PHP (user-projects, managers, controller, template, mark-all-read) lit project.users au lieu de user.projects. Script de migration inclus. Co-Authored-By: Claude Opus 4.6 --- public/site/blueprints/pages/project.yml | 4 + public/site/blueprints/users/client.yml | 7 +- public/site/blueprints/users/pochet.yml | 5 -- public/site/config/config.php | 1 + .../config/routes/migrate-user-projects.php | 75 +++++++++++++++++++ public/site/controllers/site.php | 8 +- public/site/models/project.php | 12 +-- .../notifications/routes/mark-all-read.php | 2 +- public/site/plugins/user-projects/index.php | 10 ++- public/site/templates/projects.json.php | 2 +- 10 files changed, 101 insertions(+), 25 deletions(-) create mode 100644 public/site/config/routes/migrate-user-projects.php diff --git a/public/site/blueprints/pages/project.yml b/public/site/blueprints/pages/project.yml index 6962aa5..6243b53 100644 --- a/public/site/blueprints/pages/project.yml +++ b/public/site/blueprints/pages/project.yml @@ -85,6 +85,10 @@ tabs: query: page.logo.toFile layout: cardlets required: true + users: + label: Utilisateurs assignés + type: users + multiple: true - width: 2/3 sections: diff --git a/public/site/blueprints/users/client.yml b/public/site/blueprints/users/client.yml index 9476739..f321069 100644 --- a/public/site/blueprints/users/client.yml +++ b/public/site/blueprints/users/client.yml @@ -36,7 +36,7 @@ sections: fr: Projet(s) en cours en: Current project(s) link: https://designtopack.morphozbygroupepochet.com/ - value: "{{ user.projects.toPages.count }}" + value: "{{ user.currentProjects.count }}" icon: folder content: label: ' ' @@ -52,8 +52,3 @@ sections: layout: cardlets required: true width: 1/2 - projects: - label: Projets - type: pages - query: page('projects').children - width: 1/2 diff --git a/public/site/blueprints/users/pochet.yml b/public/site/blueprints/users/pochet.yml index 2030b05..fab2a50 100644 --- a/public/site/blueprints/users/pochet.yml +++ b/public/site/blueprints/users/pochet.yml @@ -14,11 +14,6 @@ fields: - Sales Manager default: Project Panager width: 1/4 - projects: - label: Projets - type: pages - query: page('projects').children - width: 3/4 hiddenProjects: label: Projets masqués type: pages diff --git a/public/site/config/config.php b/public/site/config/config.php index 4ac5104..280672f 100644 --- a/public/site/config/config.php +++ b/public/site/config/config.php @@ -44,6 +44,7 @@ return [ require(__DIR__ . '/routes/request-project-creation.php'), require(__DIR__ . '/routes/request-optimization-appointment.php'), require(__DIR__ . '/routes/migrate-notifications.php'), + require(__DIR__ . '/routes/migrate-user-projects.php'), ], 'hooks' => [ 'page.create:after' => require_once(__DIR__ . '/hooks/create-steps.php'), diff --git a/public/site/config/routes/migrate-user-projects.php b/public/site/config/routes/migrate-user-projects.php new file mode 100644 index 0000000..abe71bf --- /dev/null +++ b/public/site/config/routes/migrate-user-projects.php @@ -0,0 +1,75 @@ + 'migrate-user-projects.json', + 'method' => 'POST', + 'action' => function () { + $user = kirby()->user(); + + if (!$user || $user->role()->id() !== 'admin') { + return [ + 'status' => 'error', + 'message' => 'Cette action nécessite les droits administrateur.' + ]; + } + + $migrated = []; + $errors = []; + + $nonAdminUsers = kirby()->users()->filter(fn($u) => $u->role()->id() !== 'admin'); + + foreach ($nonAdminUsers as $u) { + if (!$u->projects()->exists() || $u->projects()->isEmpty()) { + continue; + } + + $userProjects = $u->projects()->toPages(); + + foreach ($userProjects as $project) { + try { + $currentUsers = $project->users()->yaml(); + + $userUuid = $u->uuid()->toString(); + + if (in_array($userUuid, $currentUsers)) { + continue; + } + + $currentUsers[] = $userUuid; + $project->update(['users' => $currentUsers]); + + $migrated[] = [ + 'user' => $u->name()->value(), + 'email' => $u->email(), + 'project' => $project->title()->value(), + ]; + } catch (\Throwable $th) { + $errors[] = [ + 'user' => $u->email(), + 'project' => $project->title()->value(), + 'error' => $th->getMessage() + ]; + } + } + } + + return [ + 'status' => 'success', + 'message' => count($migrated) . ' assignations migrées.', + 'migrated' => $migrated, + 'errors' => $errors + ]; + } +]; diff --git a/public/site/controllers/site.php b/public/site/controllers/site.php index 27524bd..14a8e61 100644 --- a/public/site/controllers/site.php +++ b/public/site/controllers/site.php @@ -27,8 +27,12 @@ return function ($page, $kirby, $site) { } } - if ($kirby->user()->projects()->exists() && $kirby->user()->projects()->isNotEmpty()) { - $userData['projects'] = $kirby->user()->projects()->toPages()->map(function ($project) { + $userProjects = $kirby->user()->currentProjects()->merge( + $kirby->user()->archivedProjects() + ); + + if ($userProjects->count() > 0) { + $userData['projects'] = $userProjects->map(function ($project) { return [ "title" => (string) $project->title(), "uri" => (string) $project->uri(), diff --git a/public/site/models/project.php b/public/site/models/project.php index 15f663e..4ea0543 100644 --- a/public/site/models/project.php +++ b/public/site/models/project.php @@ -222,12 +222,12 @@ class ProjectPage extends NotificationsPage { // } public function managers() { - return kirby()->users()->filter(function($user) { - if ($user->role() != 'admin' && $user->projects()->isEmpty()) { - return false; - } - - return $user->role() == 'admin' || $user->projects()->toPages()->has($this); + if ($this->users()->isEmpty()) { + return kirby()->users()->filterBy('role', 'admin'); + } + $projectUsers = $this->users()->toUsers(); + return kirby()->users()->filter(function($user) use ($projectUsers) { + return $user->role() == 'admin' || $projectUsers->has($user); }); } } \ No newline at end of file diff --git a/public/site/plugins/notifications/routes/mark-all-read.php b/public/site/plugins/notifications/routes/mark-all-read.php index c06cc80..7c2a071 100644 --- a/public/site/plugins/notifications/routes/mark-all-read.php +++ b/public/site/plugins/notifications/routes/mark-all-read.php @@ -23,7 +23,7 @@ return [ if ($user->role()->name() === 'admin') { $projects = page('projects')->children()->toArray(); } else { - $projects = $user->projects()->toPages()->toArray(); + $projects = $user->currentProjects()->toArray(); } $count = $collector->markAllAsRead($projects, $user); diff --git a/public/site/plugins/user-projects/index.php b/public/site/plugins/user-projects/index.php index 15c5aad..733a9b3 100644 --- a/public/site/plugins/user-projects/index.php +++ b/public/site/plugins/user-projects/index.php @@ -5,16 +5,18 @@ Kirby::plugin('adrienpayet/pdc-authorized-projects', [ 'currentProjects' => function() { if ($this->role() == 'admin') { return page('projects')->children()->listed(); - } else { - return $this->projects()->toPages()->listed(); } + return page('projects')->children()->listed()->filter(function($project) { + return $project->users()->toUsers()->has($this); + }); }, 'archivedProjects' => function() { if ($this->role() == 'admin') { return page('projects')->children()->unlisted(); - } else { - return $this->projects()->toPages()->unlisted(); } + return page('projects')->children()->unlisted()->filter(function($project) { + return $project->users()->toUsers()->has($this); + }); }, ] ]); diff --git a/public/site/templates/projects.json.php b/public/site/templates/projects.json.php index 2b2eaad..542ee7e 100644 --- a/public/site/templates/projects.json.php +++ b/public/site/templates/projects.json.php @@ -46,7 +46,7 @@ $currentUser = $kirby->user(); try { $children = $currentUser->role() == 'admin' ? $page->childrenAndDrafts()->map(fn($project) => getProjectData($project, $currentUser))->values() - : $currentUser->projects()->toPages()->map(fn($project) => getProjectData($project, $currentUser))->values(); + : $currentUser->currentProjects()->map(fn($project) => getProjectData($project, $currentUser))->values(); } catch (\Throwable $th) { throw new Exception($th->getMessage() . ' line ' . $th->getLine() . ' in file ' . $th->getFile(), 1); $children = [];