All checks were successful
Deploy Preprod / Build and Deploy to Preprod (push) Successful in 30s
Respect de l'ordre des groupes défini dans le champ groups du panel. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
246 lines
No EOL
7.4 KiB
PHP
246 lines
No EOL
7.4 KiB
PHP
<?php
|
|
|
|
use adrienpayet\notifications\NotificationsPage;
|
|
|
|
class ProjectPage extends NotificationsPage {
|
|
public function getSteps() {
|
|
$apiCache = kirby()->cache('api');
|
|
$stepsData = $apiCache?->get($this->slug() . '_' . 'steps');
|
|
|
|
if ($stepsData === null || count($stepsData) === 0) {
|
|
$this->rebuildStepsCache();
|
|
};
|
|
|
|
$stepsData = $apiCache->get($this->slug() . '_' . 'steps');
|
|
|
|
return $stepsData;
|
|
}
|
|
|
|
/**
|
|
* Récupère les notifications pour ce projet (version allégée avec cache).
|
|
* Cache par utilisateur pour inclure le isRead.
|
|
*/
|
|
public function getNotificationsLight($user) {
|
|
if (!$user) {
|
|
return [];
|
|
}
|
|
|
|
$apiCache = kirby()->cache('api');
|
|
$cacheKey = $this->slug() . '_notifications_' . $user->uuid();
|
|
$notifications = $apiCache?->get($cacheKey);
|
|
|
|
// Si pas en cache, collecter et cacher
|
|
if ($notifications === null) {
|
|
$collector = kirby()->option('adrienpayet.pdc-notifications.collector');
|
|
if (!$collector) {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
$notifications = $collector->collectLight($this, $user);
|
|
$apiCache->set($cacheKey, $notifications);
|
|
} catch (\Throwable $e) {
|
|
error_log("Error caching notifications for {$this->slug()}: " . $e->getMessage());
|
|
return [];
|
|
}
|
|
}
|
|
|
|
return $notifications;
|
|
}
|
|
|
|
/**
|
|
* Invalide le cache des notifications de ce projet pour tous les utilisateurs.
|
|
*/
|
|
public function invalidateNotificationsCache() {
|
|
$apiCache = kirby()->cache('api');
|
|
// Invalider pour tous les users
|
|
foreach (kirby()->users() as $user) {
|
|
$cacheKey = $this->slug() . '_notifications_' . $user->uuid();
|
|
$apiCache->remove($cacheKey);
|
|
}
|
|
}
|
|
|
|
public function rebuildStepsCache() {
|
|
// Create steps
|
|
$steps = [];
|
|
foreach ($this->children() as $child) {
|
|
try {
|
|
$steps[] = $this->createStep($child);
|
|
} catch (\Throwable $th) {
|
|
throw new Exception("Can't create step. File " . $th->getFile() . " line " . $th->getLine(), 1);
|
|
}
|
|
}
|
|
|
|
// Sort steps by their index
|
|
usort($steps, fn($a, $b) => $a['index'] <=> $b['index']);
|
|
|
|
$apiCache = kirby()->cache('api');
|
|
$apiCache->set($this->slug() . '_' . 'steps', $steps);
|
|
}
|
|
|
|
private function createStep($child) {
|
|
$files = [];
|
|
$uri = null;
|
|
|
|
if (str_contains($child->stepName()->value(), 'Brief') || $child->stepName()->value() === "industrialIdeation") {
|
|
$this->handleBriefStep($child, $files, $uri);
|
|
}
|
|
|
|
if ($child->stepName() == 'proposal') {
|
|
$this->handleProposalStep($child, $files, $uri);
|
|
}
|
|
|
|
if ($child->stepName() == 'virtualSample') {
|
|
$this->handleVirtualSampleStep($child, $files, $uri);
|
|
}
|
|
|
|
if ($child->stepName() == 'physicalSample') {
|
|
$this->handlePhysicalSampleStep($child, $files, $uri);
|
|
}
|
|
|
|
return [
|
|
'label' => $child->title()->value(),
|
|
'id' => $child->stepName()->value(),
|
|
'slug' => $child->slug(),
|
|
'index' => intval($child->stepIndex()->value()),
|
|
'modified' => $child->modified('Y-MM-dd'),
|
|
'isValidated' => $child->isValidated() == 'true' ? true : false,
|
|
'description' => $child->description()->isNotempty() ? $child->description()->value() : null,
|
|
'title' => $child->headline()->isNotempty() ? $child->headline()->value() : null,
|
|
'date' => $child->date()->isNotempty() ? $child->date()->value() : null,
|
|
'cover' => $child->cover()->isNotempty() ? $child->cover()->toFile()->url() : null,
|
|
'uri' => $uri,
|
|
'files' => $files,
|
|
];
|
|
}
|
|
|
|
private function handleBriefStep($child, &$files, &$uri) {
|
|
$uri = $child->uri();
|
|
|
|
if ($child->moodboard()->isNotEmpty()) {
|
|
foreach ($child->moodboard()->toFiles() as $file) {
|
|
$files[] = getFileData($file);
|
|
}
|
|
}
|
|
|
|
if ($child->pdf()->isNotEmpty()) {
|
|
$files[] = getFileData($child->pdf()->toFile());
|
|
}
|
|
}
|
|
|
|
private function handleProposalStep($child, &$files, &$uri) {
|
|
$uri = $child->parent()->uri() . '?dialog=' . $child->slug();
|
|
if ($child->pdf()->isNotEmpty()) {
|
|
foreach ($child->pdf()->toFiles() as $file) {
|
|
$files[] = getFileData($file);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function handleVirtualSampleStep($child, &$files, &$uri) {
|
|
$uri = $child->parent()->uri() . '?dialog=' . $child->slug();
|
|
|
|
if ($child->hasChildren()) {
|
|
$files['dynamic'] = [];
|
|
|
|
foreach ($child->children() as $key => $track) {
|
|
$trackData = [
|
|
'title' => (string) $track->title(),
|
|
'slug' => (string) $track->slug(),
|
|
'backgroundColor' => (string) $track->backgroundColor(),
|
|
'files' => [],
|
|
];
|
|
|
|
foreach ($track->views()->toFiles() as $view) {
|
|
$trackData['files'][] = getFileData($view, true);
|
|
}
|
|
|
|
if ($track->group()->isNotEmpty()) {
|
|
$files['dynamic'][$track->group()->value()][] = $trackData;
|
|
} else {
|
|
$files['dynamic']['Autres pistes'][] = $trackData;
|
|
}
|
|
}
|
|
|
|
// Récupérer l'ordre des groupes depuis le champ groups
|
|
$orderedGroups = $child->groups()->split();
|
|
|
|
// Réorganiser $files['dynamic'] selon l'ordre défini
|
|
if (!empty($orderedGroups)) {
|
|
$orderedDynamic = [];
|
|
|
|
foreach ($orderedGroups as $group) {
|
|
if (isset($files['dynamic'][$group])) {
|
|
$orderedDynamic[$group] = $files['dynamic'][$group];
|
|
}
|
|
}
|
|
|
|
// Ajouter les groupes non définis dans le champ à la fin
|
|
foreach ($files['dynamic'] as $group => $tracks) {
|
|
if (!isset($orderedDynamic[$group])) {
|
|
$orderedDynamic[$group] = $tracks;
|
|
}
|
|
}
|
|
|
|
$files['dynamic'] = $orderedDynamic;
|
|
}
|
|
|
|
// Toujours mettre "Autres pistes" à la fin
|
|
if (isset($files['dynamic']['Autres pistes'])) {
|
|
$others = $files['dynamic']['Autres pistes'];
|
|
unset($files['dynamic']['Autres pistes']);
|
|
$files['dynamic']['Autres pistes'] = $others;
|
|
}
|
|
|
|
}
|
|
|
|
if ($child->rawGlass()->isNotEmpty() || $child->finishedGlass()->isNotEmpty()) {
|
|
$files['static'] = [];
|
|
}
|
|
|
|
if ($child->rawGlass()->isNotEmpty()) {
|
|
$files['static']['rawGlass'] = getFileData($child->rawGlass()->toFile());
|
|
}
|
|
|
|
if ($child->finishedGlass()->isNotEmpty()) {
|
|
$files['static']['finishedGlass'] = getFileData($child->finishedGlass()->toFile());
|
|
}
|
|
}
|
|
|
|
private function handlePhysicalSampleStep($child, &$files, &$uri) {
|
|
$uri = $child->parent()->uri() . '?dialog=' . $child->slug();
|
|
|
|
if ($child->media()->isNotEmpty()) {
|
|
foreach ($child->media()->toFiles() as $file) {
|
|
$files[] = getFileData($file);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function getStepLabel() {
|
|
$stepsLabel = [
|
|
"clientBrief" => "brief",
|
|
"proposal" => "offre commerciale",
|
|
"extendedBrief" => "brief enrichi",
|
|
"industrialIdeation" => "idéation industrielle",
|
|
"virtualSample" => "échantillon virtuel",
|
|
"physicalSample" => "échantillon physique",
|
|
];
|
|
|
|
return $stepsLabel[$this->currentStep()->value()];
|
|
}
|
|
|
|
// public function printManagers() {
|
|
// return A::implode($this->managers()->toUsers()->pluck('name'), ', ');
|
|
// }
|
|
|
|
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);
|
|
});
|
|
}
|
|
} |