602 lines
25 KiB
PHP
602 lines
25 KiB
PHP
<?php
|
|
/**
|
|
* Atlassian Jira Cloud REST API Integratie voor Fociz
|
|
* Beheert verbindingstest, ophalen van aan de gebruiker toegewezen issues en import naar dagtaken.
|
|
*/
|
|
|
|
require_once __DIR__ . '/../http.php';
|
|
require_once __DIR__ . '/../../config/database.php';
|
|
|
|
/**
|
|
* Normaliseert het Jira domein naar een schone URL zonder slash aan het einde
|
|
*/
|
|
function jira_normalize_domain(string $domain): string {
|
|
$domain = trim($domain);
|
|
if (!preg_match('#^https?://#i', $domain)) {
|
|
$domain = 'https://' . $domain;
|
|
}
|
|
return rtrim($domain, '/');
|
|
}
|
|
|
|
/**
|
|
* Haalt het centrale bedrijfsdomein voor Atlassian Jira op
|
|
*/
|
|
function jira_get_company_domain(): string {
|
|
$domain = fociz_env('JIRA_DOMAIN', '');
|
|
if (!empty($domain)) {
|
|
return jira_normalize_domain($domain);
|
|
}
|
|
|
|
try {
|
|
$db = get_db_connection();
|
|
// Zoek bij beheerder(s) in de integrations tabel
|
|
$stmt = $db->query("
|
|
SELECT i.settings
|
|
FROM integrations i
|
|
JOIN users u ON i.user_id = u.id
|
|
WHERE u.role = 'ADMIN' AND i.provider = 'JIRA' AND i.settings IS NOT NULL
|
|
ORDER BY i.updated_at DESC
|
|
LIMIT 1
|
|
");
|
|
$row = $stmt->fetch();
|
|
if (!empty($row['settings'])) {
|
|
$settings = json_decode($row['settings'], true) ?: [];
|
|
if (!empty($settings['jira_domain'])) {
|
|
return jira_normalize_domain($settings['jira_domain']);
|
|
}
|
|
}
|
|
|
|
// Fallback naar een willekeurige JIRA rij
|
|
$fallback = $db->query("
|
|
SELECT settings FROM integrations WHERE provider = 'JIRA' AND settings LIKE '%jira_domain%' LIMIT 1
|
|
")->fetch();
|
|
if (!empty($fallback['settings'])) {
|
|
$settings = json_decode($fallback['settings'], true) ?: [];
|
|
if (!empty($settings['jira_domain'])) {
|
|
return jira_normalize_domain($settings['jira_domain']);
|
|
}
|
|
}
|
|
} catch (Throwable $e) {
|
|
error_log("jira_get_company_domain error: " . $e->getMessage());
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Genereert de Basic Authentication header voor Atlassian REST API
|
|
*/
|
|
function jira_get_auth_header(string $email, string $apiToken): string {
|
|
return 'Basic ' . base64_encode(trim($email) . ':' . trim($apiToken));
|
|
}
|
|
|
|
/**
|
|
* Test de verbinding met Atlassian Jira Cloud via /rest/api/3/myself
|
|
*/
|
|
function jira_test_connection(string $domain, string $email, string $apiToken): array {
|
|
$cleanDomain = jira_normalize_domain($domain);
|
|
if (empty($cleanDomain) || empty($email) || empty($apiToken)) {
|
|
return [
|
|
'success' => false,
|
|
'error' => 'Vul een Jira domein, e-mailadres en Atlassian API token in.',
|
|
];
|
|
}
|
|
|
|
$authHeader = jira_get_auth_header($email, $apiToken);
|
|
$url = $cleanDomain . '/rest/api/3/myself';
|
|
|
|
$response = fociz_http_request($url, [
|
|
'method' => 'GET',
|
|
'headers' => [
|
|
'Authorization' => $authHeader,
|
|
'Accept' => 'application/json',
|
|
],
|
|
'timeout' => 10,
|
|
]);
|
|
|
|
// Fallback naar api v2 indien v3 niet beschikbaar is
|
|
if ($response['status'] === 404) {
|
|
$urlV2 = $cleanDomain . '/rest/api/2/myself';
|
|
$response = fociz_http_request($urlV2, [
|
|
'method' => 'GET',
|
|
'headers' => [
|
|
'Authorization' => $authHeader,
|
|
'Accept' => 'application/json',
|
|
],
|
|
'timeout' => 10,
|
|
]);
|
|
}
|
|
|
|
if ($response['status'] === 200 && is_array($response['json'])) {
|
|
$user = $response['json'];
|
|
return [
|
|
'success' => true,
|
|
'user' => [
|
|
'displayName' => $user['displayName'] ?? 'Atlassian Gebruiker',
|
|
'emailAddress' => $user['emailAddress'] ?? $email,
|
|
'accountId' => $user['accountId'] ?? ($user['key'] ?? ''),
|
|
'active' => $user['active'] ?? true,
|
|
'timeZone' => $user['timeZone'] ?? 'Europe/Amsterdam',
|
|
],
|
|
];
|
|
}
|
|
|
|
$errMsg = 'Verbinding mislukt met Jira.';
|
|
if ($response['status'] === 401) {
|
|
$errMsg = 'Authenticatie geweigerd (HTTP 401). Controleer uw e-mailadres en zorg dat u een geldig Atlassian API token gebruikt.';
|
|
} elseif ($response['status'] === 403) {
|
|
$errMsg = 'Toegang geweigerd (HTTP 403). Uw account heeft onvoldoende rechten op dit Jira domein.';
|
|
} elseif ($response['status'] === 404) {
|
|
$errMsg = 'Jira Cloud domein niet gevonden (HTTP 404). Controleer het ingevoerde domein (bijv. uwbedrijf.atlassian.net).';
|
|
} elseif (!empty($response['error'])) {
|
|
$errMsg = "Netwerkfout: {$response['error']}";
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'error' => $errMsg,
|
|
'status' => $response['status'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Haalt alle actieve issues op die zijn toegewezen aan de ingelogde Jira gebruiker
|
|
*/
|
|
/**
|
|
* Haalt issues op via een flexibele JQL query via Atlassian REST API
|
|
*/
|
|
function jira_fetch_issues(string $domain, string $email, string $apiToken, string $jql, int $maxResults = 50): array {
|
|
$cleanDomain = jira_normalize_domain($domain);
|
|
$authHeader = jira_get_auth_header($email, $apiToken);
|
|
|
|
$params = [
|
|
'jql' => $jql,
|
|
'maxResults' => min($maxResults, 100),
|
|
'fields' => 'summary,status,priority,issuetype,parent,project,assignee,reporter,duedate,updated',
|
|
];
|
|
|
|
$url = $cleanDomain . '/rest/api/3/search?' . http_build_query($params);
|
|
|
|
$response = fociz_http_request($url, [
|
|
'method' => 'GET',
|
|
'headers' => [
|
|
'Authorization' => $authHeader,
|
|
'Accept' => 'application/json',
|
|
],
|
|
'timeout' => 12,
|
|
]);
|
|
|
|
// Fallback naar api v2
|
|
if ($response['status'] === 404) {
|
|
$urlV2 = $cleanDomain . '/rest/api/2/search?' . http_build_query($params);
|
|
$response = fociz_http_request($urlV2, [
|
|
'method' => 'GET',
|
|
'headers' => [
|
|
'Authorization' => $authHeader,
|
|
'Accept' => 'application/json',
|
|
],
|
|
'timeout' => 12,
|
|
]);
|
|
}
|
|
|
|
if ($response['status'] !== 200 || !isset($response['json']['issues'])) {
|
|
return [
|
|
'success' => false,
|
|
'error' => $response['json']['errorMessages'][0] ?? ($response['error'] ?? 'Kan Jira tickets niet ophalen'),
|
|
'issues' => [],
|
|
];
|
|
}
|
|
|
|
$rawIssues = $response['json']['issues'];
|
|
$issues = [];
|
|
|
|
foreach ($rawIssues as $item) {
|
|
$fields = $item['fields'] ?? [];
|
|
$key = $item['key'] ?? '';
|
|
$summary = $fields['summary'] ?? '(Geen titel)';
|
|
$statusName = $fields['status']['name'] ?? 'To Do';
|
|
$statusCategory = $fields['status']['statusCategory']['key'] ?? 'indeterminate';
|
|
$priorityName = $fields['priority']['name'] ?? 'Medium';
|
|
$issueTypeName = $fields['issuetype']['name'] ?? 'Taak';
|
|
$issueTypeIcon = $fields['issuetype']['iconUrl'] ?? '';
|
|
$projectName = $fields['project']['name'] ?? 'Project';
|
|
$projectKey = $fields['project']['key'] ?? '';
|
|
$dueDate = $fields['duedate'] ?? null;
|
|
$updated = $fields['updated'] ?? null;
|
|
|
|
$assigneeName = $fields['assignee']['displayName'] ?? 'Niet toegewezen';
|
|
$assigneeAvatar = $fields['assignee']['avatarUrls']['48x48'] ?? ($fields['assignee']['avatarUrls']['32x32'] ?? '');
|
|
|
|
$issues[] = [
|
|
'key' => $key,
|
|
'summary' => $summary,
|
|
'status' => $statusName,
|
|
'status_category' => $statusCategory,
|
|
'priority' => $priorityName,
|
|
'issue_type' => $issueTypeName,
|
|
'issue_type_icon' => $issueTypeIcon,
|
|
'project' => $projectName,
|
|
'project_key' => $projectKey,
|
|
'assignee_name' => $assigneeName,
|
|
'assignee_avatar' => $assigneeAvatar,
|
|
'due_date' => $dueDate,
|
|
'updated' => $updated,
|
|
'url' => "{$cleanDomain}/browse/{$key}",
|
|
'source' => 'JIRA_LIVE',
|
|
];
|
|
}
|
|
|
|
return [
|
|
'success' => true,
|
|
'issues' => $issues,
|
|
'total' => count($issues),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Haalt alle actieve issues op die zijn toegewezen aan de ingelogde Jira gebruiker
|
|
*/
|
|
function jira_fetch_assigned_issues(string $domain, string $email, string $apiToken, int $maxResults = 50): array {
|
|
$jql = 'assignee = currentUser() ORDER BY updated DESC';
|
|
return jira_fetch_issues($domain, $email, $apiToken, $jql, $maxResults);
|
|
}
|
|
|
|
/**
|
|
* Haalt openstaande team issues op die horen bij de projecten van de gebruiker
|
|
*/
|
|
function jira_fetch_team_issues(string $domain, string $email, string $apiToken, int $maxResults = 50): array {
|
|
$jql = 'assignee != currentUser() AND statusCategory != Done ORDER BY updated DESC';
|
|
return jira_fetch_issues($domain, $email, $apiToken, $jql, $maxResults);
|
|
}
|
|
|
|
/**
|
|
* Haalt de complete dashboard data op (persoonlijk + team) inclusief statistieken
|
|
*/
|
|
function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array {
|
|
$db = get_db_connection();
|
|
$stmt = $db->prepare("SELECT * FROM integrations WHERE user_id = ? AND provider = 'JIRA' AND is_enabled = 1");
|
|
$stmt->execute([$userId]);
|
|
$integration = $stmt->fetch();
|
|
|
|
// Sandbox / Demo dataset indien niet gekoppeld of expliciet in demomodus
|
|
if (!$integration || !empty($integration['is_demo_mode'])) {
|
|
$assigned = [
|
|
[
|
|
'key' => 'FOC-101',
|
|
'summary' => 'Tweestapsverificatie (2FA TOTP) flow implementeren',
|
|
'status' => 'In Progress',
|
|
'status_category' => 'indeterminate',
|
|
'priority' => 'High',
|
|
'issue_type' => 'Story',
|
|
'project' => 'Fociz Platform',
|
|
'project_key' => 'FOC',
|
|
'assignee_name' => 'Mijzelf',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+2 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-2 hours')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-101',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-102',
|
|
'summary' => 'Interactief whiteboard canvas voor brainstormsessies',
|
|
'status' => 'To Do',
|
|
'status_category' => 'new',
|
|
'priority' => 'High',
|
|
'issue_type' => 'Feature',
|
|
'project' => 'Fociz Platform',
|
|
'project_key' => 'FOC',
|
|
'assignee_name' => 'Mijzelf',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+4 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-102',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-103',
|
|
'summary' => 'Koppeling met Microsoft Outlook Calendar & Teams Graph API',
|
|
'status' => 'In Review',
|
|
'status_category' => 'indeterminate',
|
|
'priority' => 'Medium',
|
|
'issue_type' => 'Task',
|
|
'project' => 'Integrations Hub',
|
|
'project_key' => 'INT',
|
|
'assignee_name' => 'Mijzelf',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d'),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-4 hours')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-103',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-104',
|
|
'summary' => 'Roadmap kwartaalweergave en voortgangsindicatoren',
|
|
'status' => 'To Do',
|
|
'status_category' => 'new',
|
|
'priority' => 'Medium',
|
|
'issue_type' => 'Story',
|
|
'project' => 'Roadmap Module',
|
|
'project_key' => 'ROAD',
|
|
'assignee_name' => 'Mijzelf',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+7 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-3 days')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-104',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-108',
|
|
'summary' => 'CSS scrollbar glitch oplossen in Kanban lane op Firefox',
|
|
'status' => 'In Progress',
|
|
'status_category' => 'indeterminate',
|
|
'priority' => 'Highest',
|
|
'issue_type' => 'Bug',
|
|
'project' => 'UI/UX Redesign',
|
|
'project_key' => 'UI',
|
|
'assignee_name' => 'Mijzelf',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+1 day')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-30 minutes')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-108',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-112',
|
|
'summary' => 'Avatar upload beveiliging en compressie optimalisatie',
|
|
'status' => 'Done',
|
|
'status_category' => 'done',
|
|
'priority' => 'Medium',
|
|
'issue_type' => 'Task',
|
|
'project' => 'Security',
|
|
'project_key' => 'SEC',
|
|
'assignee_name' => 'Mijzelf',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('-1 day')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-5 hours')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-112',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
];
|
|
|
|
$team = [
|
|
[
|
|
'key' => 'FOC-95',
|
|
'summary' => 'Sessie timeout notificatie verschijnt niet tijdig bij inactieve tab',
|
|
'status' => 'In Progress',
|
|
'status_category' => 'indeterminate',
|
|
'priority' => 'Highest',
|
|
'issue_type' => 'Bug',
|
|
'project' => 'Fociz Platform',
|
|
'project_key' => 'FOC',
|
|
'assignee_name' => 'Lisa Bakker',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+1 day')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-1 hour')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-95',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-98',
|
|
'summary' => 'Automatische e-mail triggers voor taakdeadlines en uitnodigingen',
|
|
'status' => 'To Do',
|
|
'status_category' => 'new',
|
|
'priority' => 'High',
|
|
'issue_type' => 'Story',
|
|
'project' => 'Notifications',
|
|
'project_key' => 'NOTIF',
|
|
'assignee_name' => 'Daan van Dijk',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+3 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-2 days')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-98',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-105',
|
|
'summary' => 'Database indexering optimaliseren voor grote audit logs',
|
|
'status' => 'In Review',
|
|
'status_category' => 'indeterminate',
|
|
'priority' => 'Medium',
|
|
'issue_type' => 'Task',
|
|
'project' => 'Database & Core',
|
|
'project_key' => 'CORE',
|
|
'assignee_name' => 'Sophie de Vries',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+5 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-105',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-107',
|
|
'summary' => 'Exporteer wekelijkse team rapportage naar PDF en Excel spreadsheet',
|
|
'status' => 'To Do',
|
|
'status_category' => 'new',
|
|
'priority' => 'Low',
|
|
'issue_type' => 'Feature',
|
|
'project' => 'Reporting',
|
|
'project_key' => 'REP',
|
|
'assignee_name' => 'Thomas Jansen',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+10 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-4 days')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-107',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-110',
|
|
'summary' => 'Real-time websocket synchronisatie voor gelijktijdig bewerken van borden',
|
|
'status' => 'To Do',
|
|
'status_category' => 'new',
|
|
'priority' => 'High',
|
|
'issue_type' => 'Story',
|
|
'project' => 'Realtime Engine',
|
|
'project_key' => 'RT',
|
|
'assignee_name' => 'Bram Meijer',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+6 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-6 hours')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-110',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-114',
|
|
'summary' => 'Datum picker springt terug naar 1970 bij lege invoer',
|
|
'status' => 'To Do',
|
|
'status_category' => 'new',
|
|
'priority' => 'Medium',
|
|
'issue_type' => 'Bug',
|
|
'project' => 'UI/UX Redesign',
|
|
'project_key' => 'UI',
|
|
'assignee_name' => 'Niet toegewezen',
|
|
'assignee_avatar' => '',
|
|
'due_date' => null,
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-2 days')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-114',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-89',
|
|
'summary' => 'GDPR / AVG compliancy en geautomatiseerd data retentiebeleid',
|
|
'status' => 'In Progress',
|
|
'status_category' => 'indeterminate',
|
|
'priority' => 'Medium',
|
|
'issue_type' => 'Epic',
|
|
'project' => 'Security',
|
|
'project_key' => 'SEC',
|
|
'assignee_name' => 'Lisa Bakker',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('+14 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-3 hours')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-89',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
[
|
|
'key' => 'FOC-82',
|
|
'summary' => 'Performance optimalisatie van vector avatar rendering in navigatiebalk',
|
|
'status' => 'Done',
|
|
'status_category' => 'done',
|
|
'priority' => 'Low',
|
|
'issue_type' => 'Task',
|
|
'project' => 'UI/UX Redesign',
|
|
'project_key' => 'UI',
|
|
'assignee_name' => 'Sophie de Vries',
|
|
'assignee_avatar' => '',
|
|
'due_date' => date('Y-m-d', strtotime('-3 days')),
|
|
'updated' => date('Y-m-d H:i:s', strtotime('-2 days')),
|
|
'url' => 'https://jira.atlassian.net/browse/FOC-82',
|
|
'source' => 'SANDBOX',
|
|
],
|
|
];
|
|
|
|
return [
|
|
'is_demo' => true,
|
|
'success' => true,
|
|
'domain' => 'sandbox.atlassian.net',
|
|
'email' => 'demo@fociz.nl',
|
|
'account_name' => 'Demo Account',
|
|
'last_sync_at' => date('Y-m-d H:i:s'),
|
|
'assigned_issues' => $assigned,
|
|
'team_issues' => $team,
|
|
];
|
|
}
|
|
|
|
$settings = json_decode($integration['settings'] ?? '{}', true) ?: [];
|
|
$domain = !empty($settings['jira_domain']) ? $settings['jira_domain'] : jira_get_company_domain();
|
|
$email = $settings['jira_email'] ?? fociz_env('JIRA_EMAIL', '');
|
|
$apiToken = $settings['jira_api_token'] ?? fociz_env('JIRA_API_TOKEN', '');
|
|
$accName = $settings['account_name'] ?? 'Atlassian Gebruiker';
|
|
|
|
if (empty($domain) || empty($email) || empty($apiToken)) {
|
|
return [
|
|
'is_demo' => false,
|
|
'success' => false,
|
|
'error' => 'Jira configuratie is onvolledig. Controleer je instellingen.',
|
|
'assigned_issues' => [],
|
|
'team_issues' => [],
|
|
];
|
|
}
|
|
|
|
// Sessiecache voor 60 seconden
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
@session_start();
|
|
}
|
|
$cacheKey = "jira_dashboard_user_{$userId}";
|
|
$cached = $_SESSION[$cacheKey] ?? null;
|
|
|
|
if (!$forceRefresh && $cached && is_array($cached) && ($cached['timestamp'] ?? 0) > (time() - 60)) {
|
|
return array_merge($cached['data'], ['from_cache' => true]);
|
|
}
|
|
|
|
// Ophalen van toegewezen taken
|
|
$assignedRes = jira_fetch_assigned_issues($domain, $email, $apiToken, 50);
|
|
// Ophalen van teamtaken
|
|
$teamRes = jira_fetch_team_issues($domain, $email, $apiToken, 50);
|
|
|
|
if (!$assignedRes['success'] && !$teamRes['success']) {
|
|
return [
|
|
'is_demo' => false,
|
|
'success' => false,
|
|
'error' => $assignedRes['error'] ?? 'Kan Jira tickets niet ophalen.',
|
|
'assigned_issues' => [],
|
|
'team_issues' => [],
|
|
];
|
|
}
|
|
|
|
$assignedIssues = $assignedRes['success'] ? $assignedRes['issues'] : [];
|
|
$teamIssues = $teamRes['success'] ? $teamRes['issues'] : [];
|
|
|
|
$data = [
|
|
'is_demo' => false,
|
|
'success' => true,
|
|
'domain' => $domain,
|
|
'email' => $email,
|
|
'account_name' => $accName,
|
|
'last_sync_at' => date('Y-m-d H:i:s'),
|
|
'assigned_issues' => $assignedIssues,
|
|
'team_issues' => $teamIssues,
|
|
];
|
|
|
|
$_SESSION[$cacheKey] = [
|
|
'timestamp' => time(),
|
|
'data' => $data,
|
|
];
|
|
|
|
// Werk last_sync_at bij in database
|
|
$stmtUpdate = $db->prepare("UPDATE integrations SET last_sync_at = NOW() WHERE id = ?");
|
|
$stmtUpdate->execute([$integration['id']]);
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Haalt de Jira tickets op voor een Fociz gebruiker (backwards compatibility)
|
|
*/
|
|
function jira_get_user_issues(int $userId, bool $forceRefresh = false): array {
|
|
$data = jira_get_dashboard_data($userId, $forceRefresh);
|
|
return [
|
|
'is_demo' => $data['is_demo'] ?? false,
|
|
'success' => $data['success'] ?? false,
|
|
'error' => $data['error'] ?? null,
|
|
'issues' => $data['assigned_issues'] ?? [],
|
|
'from_cache' => $data['from_cache'] ?? false,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Ontkoppelt Jira integratie voor een gebruiker
|
|
*/
|
|
function jira_disconnect(int $userId): bool {
|
|
$db = get_db_connection();
|
|
$stmt = $db->prepare("DELETE FROM integrations WHERE user_id = ? AND provider = 'JIRA'");
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
@session_start();
|
|
}
|
|
unset($_SESSION["jira_issues_user_{$userId}"]);
|
|
unset($_SESSION["jira_dashboard_user_{$userId}"]);
|
|
return $stmt->execute([$userId]);
|
|
}
|
|
|
|
|