AddOn/Calender_Office365/GraphCalendar.php hinzugefügt
This commit is contained in:
parent
a36c757730
commit
b69f9dc73b
|
|
@ -0,0 +1,305 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Klasse zur Interaktion mit dem Microsoft Graph API für Kalenderfunktionen.
|
||||
*/
|
||||
class GraphCalendar
|
||||
{
|
||||
// Konfigurationswerte und interne Felder
|
||||
private $clientId;
|
||||
private $clientSecret;
|
||||
private $tenantId;
|
||||
private $graphUrl = 'https://graph.microsoft.com/v1.0'; // Basis-URL für das Microsoft Graph API
|
||||
private $token;
|
||||
private $headers;
|
||||
private $defaultUserEmail;
|
||||
|
||||
/**
|
||||
* Konstruktor: Initialisiert mit Azure AD App-Credentials und optionaler Standard-E-Mail.
|
||||
*/
|
||||
public function __construct($clientId, $clientSecret, $tenantId, $defaultUserEmail = null)
|
||||
{
|
||||
$this->clientId = $clientId;
|
||||
$this->clientSecret = $clientSecret;
|
||||
$this->tenantId = $tenantId;
|
||||
$this->defaultUserEmail = $defaultUserEmail;
|
||||
|
||||
// Authentifizierung gegen Microsoft Graph API durchführen
|
||||
$this->authenticate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentifiziert sich mit dem Client-Credentials-Flow (ohne Benutzerinteraktion)
|
||||
*/
|
||||
private function authenticate()
|
||||
{
|
||||
$tokenUrl = "https://login.microsoftonline.com/{$this->tenantId}/oauth2/v2.0/token";
|
||||
|
||||
// Daten für den OAuth2 Token-Request
|
||||
$data = [
|
||||
'grant_type' => 'client_credentials',
|
||||
'client_id' => $this->clientId,
|
||||
'client_secret' => $this->clientSecret,
|
||||
'scope' => 'https://graph.microsoft.com/.default', // Zugriff auf alle berechtigten Graph APIs
|
||||
];
|
||||
|
||||
// Token abrufen
|
||||
$response = $this->postCurl($tokenUrl, ['Content-Type: application/x-www-form-urlencoded'], $data);
|
||||
$decoded = json_decode($response, true);
|
||||
$this->token = $decoded['access_token'];
|
||||
|
||||
// Standard-Header für alle API-Requests
|
||||
$this->headers = [
|
||||
"Authorization: Bearer {$this->token}",
|
||||
"Content-Type: application/json"
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt eine gültige Benutzer-E-Mail zurück oder wirft einen Fehler
|
||||
*/
|
||||
private function resolveUserEmail($userEmail)
|
||||
{
|
||||
if (!empty($userEmail)) {
|
||||
return $userEmail;
|
||||
} elseif (!empty($this->defaultUserEmail)) {
|
||||
return $this->defaultUserEmail;
|
||||
} else {
|
||||
throw new Exception("Keine Benutzer-E-Mail angegeben.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt alle oder ein bestimmtes Kalender-Event zurück
|
||||
*/
|
||||
public function getEvents($eventId = "", $userEmail = "")
|
||||
{
|
||||
$email = $this->resolveUserEmail($userEmail);
|
||||
|
||||
if($eventId == ""){
|
||||
// Alle Events des Nutzers abrufen
|
||||
$eventsResponse = $this->getCurl("$this->graphUrl/users/{$email}/calendar/events", $this->headers);
|
||||
return json_decode($eventsResponse, true)['value'] ?? [];
|
||||
} else {
|
||||
// Nur ein einzelnes Event anhand der ID abrufen
|
||||
$eventsResponse = $this->getCurl("{$this->graphUrl}/users/{$email}/calendar/events/{$eventId}", $this->headers);
|
||||
return json_decode($eventsResponse, true) ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt ein neues Kalender-Event (mit optionalem Teams-Link und Teilnehmern)
|
||||
*/
|
||||
public function createEvent($subject, $startTime, $endTime, $isTeamsTermin = false, $description = '', $location = "", $gustArray = array(), $userEmail = "", $timezone = 'Europe/Berlin')
|
||||
{
|
||||
$email = $this->resolveUserEmail($userEmail);
|
||||
|
||||
// Event-Daten vorbereiten
|
||||
$event = [
|
||||
'subject' => $subject,
|
||||
'start' => [
|
||||
'dateTime' => $startTime,
|
||||
'timeZone' => $timezone
|
||||
],
|
||||
'end' => [
|
||||
'dateTime' => $endTime,
|
||||
'timeZone' => $timezone
|
||||
],
|
||||
'body' => [
|
||||
'contentType' => 'HTML',
|
||||
'content' => $description
|
||||
],
|
||||
'location' => [
|
||||
'displayName' => $location
|
||||
]
|
||||
];
|
||||
|
||||
// Optional: Teams-Termin aktivieren
|
||||
if($isTeamsTermin == true){
|
||||
$event['isOnlineMeeting'] = true;
|
||||
$event['onlineMeetingProvider'] = 'teamsForBusiness';
|
||||
}
|
||||
|
||||
// Teilnehmer hinzufügen, falls vorhanden
|
||||
if(count($gustArray) > 0){
|
||||
$event['attendees'] = $gustArray;
|
||||
}
|
||||
|
||||
// Event erstellen
|
||||
$url = "{$this->graphUrl}/users/{$email}/calendar/events";
|
||||
$response = $this->postJsonCurl($url, $this->headers, $event);
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bestehendes Event aktualisieren
|
||||
*/
|
||||
public function updateEvent($eventId, $subject, $startTime, $endTime, $isTeamsTermin = false, $description = '', $location = "", $gustArray = array(), $userEmail = "", $timezone = 'Europe/Berlin')
|
||||
{
|
||||
$email = $this->resolveUserEmail($userEmail);
|
||||
|
||||
// Neue Eventdaten
|
||||
$event = [
|
||||
'subject' => $subject,
|
||||
'start' => [
|
||||
'dateTime' => $startTime,
|
||||
'timeZone' => $timezone
|
||||
],
|
||||
'end' => [
|
||||
'dateTime' => $endTime,
|
||||
'timeZone' => $timezone
|
||||
],
|
||||
'body' => [
|
||||
'contentType' => 'HTML',
|
||||
'content' => $description
|
||||
],
|
||||
'location' => [
|
||||
'displayName' => $location
|
||||
],
|
||||
'isOnlineMeeting' => $isTeamsTermin
|
||||
];
|
||||
|
||||
// Teams-Link ggf. setzen
|
||||
if($isTeamsTermin == true){
|
||||
$event['onlineMeetingProvider'] = 'teamsForBusiness';
|
||||
}
|
||||
|
||||
// Teilnehmer aktualisieren
|
||||
if(count($gustArray) > 0){
|
||||
$event['attendees'] = $gustArray;
|
||||
}
|
||||
|
||||
// Event patchen (aktualisieren)
|
||||
$url = "{$this->graphUrl}/users/{$email}/calendar/events/{$eventId}";
|
||||
$result = $this->patchJsonCurl($url, $this->headers, $event);
|
||||
return [
|
||||
'status' => $result['status'],
|
||||
'response' => json_decode($result['response'], true)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht ein Kalender-Event anhand der ID
|
||||
*/
|
||||
public function deleteEvent($eventId, $userEmail = "")
|
||||
{
|
||||
$email = $this->resolveUserEmail($userEmail);
|
||||
$url = "{$this->graphUrl}/users/{$email}/calendar/events/{$eventId}";
|
||||
return $this->deleteCurl($url, $this->headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hängt eine Datei als Attachment an ein Kalender-Event.
|
||||
*
|
||||
* @param string $eventId Die ID des Events
|
||||
* @param string $fileName Der Dateiname (z.B. "dokument.pdf")
|
||||
* @param string $fileContent Der Inhalt der Datei als Base64-kodierter String
|
||||
* @param string $contentType Der MIME-Typ der Datei (z.B. "application/pdf")
|
||||
* @param string $userEmail Optional: Benutzer-E-Mail, falls abweichend
|
||||
* @return array Antwort von der Graph API
|
||||
*/
|
||||
public function addAttachmentToEvent($eventId, $fileName, $fileContent, $contentType = 'application/octet-stream', $userEmail = '')
|
||||
{
|
||||
$email = $this->resolveUserEmail($userEmail);
|
||||
|
||||
// Attachment-Objekt
|
||||
$attachment = [
|
||||
'@odata.type' => '#microsoft.graph.fileAttachment',
|
||||
'name' => $fileName,
|
||||
'contentType' => $contentType,
|
||||
'contentBytes' => base64_encode($fileContent)
|
||||
];
|
||||
|
||||
$url = "{$this->graphUrl}/users/{$email}/events/{$eventId}/attachments";
|
||||
$response = $this->postJsonCurl($url, $this->headers, $attachment);
|
||||
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
|
||||
// === HELPER-FUNKTIONEN FÜR CURL ===
|
||||
|
||||
/**
|
||||
* POST-Request mit URL-encoded Daten
|
||||
*/
|
||||
private function postCurl($url, $headers, $data)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => http_build_query($data),
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET-Request
|
||||
*/
|
||||
private function getCurl($url, $headers)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST-Request mit JSON-Daten
|
||||
*/
|
||||
private function postJsonCurl($url, $headers, $json)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => json_encode($json),
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* PATCH-Request (teilweises Update von Ressourcen)
|
||||
*/
|
||||
private function patchJsonCurl($url, $headers, $json)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CUSTOMREQUEST => 'PATCH',
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => json_encode($json),
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
return ['status' => $httpCode, 'response' => $response];
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE-Request
|
||||
*/
|
||||
private function deleteCurl($url, $headers)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CUSTOMREQUEST => 'DELETE',
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
]);
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
return $httpCode;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue