From 2a922cb6d4ed612b44e5a4044f9c6136c629342e Mon Sep 17 00:00:00 2001 From: Thibault Dockx <thibault.dockx@fusiondirectory.org> Date: Fri, 4 Apr 2025 17:04:54 +0100 Subject: [PATCH 1/3] :art: feat(extractor) - implement Extractor class for handling task extraction with support for multiple formats --- plugins/tasks/Extractor.php | 315 ++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 plugins/tasks/Extractor.php diff --git a/plugins/tasks/Extractor.php b/plugins/tasks/Extractor.php new file mode 100644 index 0000000..1ad125e --- /dev/null +++ b/plugins/tasks/Extractor.php @@ -0,0 +1,315 @@ +<?php + +class Extractor implements EndpointInterface +{ + private TaskGateway $gateway; + + public function __construct(TaskGateway $gateway) + { + $this->gateway = $gateway; + } + + /** + * @return array + * Part of the interface of orchestrator plugin to treat GET method + */ + public function processEndPointGet(): array + { + // Retrieve tasks of type 'extract' + return $this->gateway->getObjectTypeTask('extract'); + } + + /** + * @param array|null $data + * @return array + * Note: Part of the interface of orchestrator plugin to treat POST method + */ + public function processEndPointPost(array $data = NULL): array + { + return []; + } + + /** + * @param array|null $data + * @return array + * Note: Part of the interface of orchestrator plugin to treat DELETE method + */ + public function processEndPointDelete(array $data = NULL): array + { + return []; + } + + /** + * @param array|null $data + * @return array + * @throws Exception + * Note: Part of the interface of orchestrator plugin to treat PATCH method + */ + public function processEndPointPatch(array $data = NULL): array + { + $result = []; + $extractTasks = $this->gateway->getObjectTypeTask('extract'); + + // Path is now expected in the JSON body ($data) + $path = $data['path'] ?? '/srv/orchestrator/'; + + foreach ($extractTasks as $task) { + try { + if (!$this->gateway->statusAndScheduleCheck($task)) { + // Skip this task if it does not meet the status and schedule criteria + continue; + } + + // Get the main task configuration + $mainTaskConfig = $this->getExtractMainTaskConfig($task['fdtasksgranularmaster'][0]); + + // Get user DN from the task + $userDn = $task['fdtasksgranulardn'][0]; + + // Get user attributes + $userAttributes = $this->getUserAttributes($userDn, $mainTaskConfig); + + // Format comes from the main task configuration + $format = isset($mainTaskConfig[0]['fdextractortaskformat']) ? + strtolower($mainTaskConfig[0]['fdextractortaskformat'][0]) : 'csv'; + + // Create directory if it doesn't exist + $this->ensureDirectoryExists($path); + + // Get main task CN for filename + $mainTaskCn = $this->getMainTaskCn($task['fdtasksgranularmaster'][0]); + + // Determine filename with main task name and date with hours + $date = date('Y-m-d_H-i-s'); + $filename = isset($data['filename']) ? + $path . $data['filename'] . '_' . $date . '.' . $format : + $path . $mainTaskCn . '_' . $date . '.' . $format; + + // Extract and write to file + $success = $this->extractToFile($userAttributes, $filename, $format); + + if ($success) { + $result[$task['dn']]['result'] = "User attributes successfully extracted to $filename"; + $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2'); + } else { + throw new Exception("Failed to write data to $filename"); + } + + } catch (Exception $e) { + $result[$task['dn']]['result'] = "Error extracting user attributes: " . $e->getMessage(); + $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage()); + } + } + + return $result; + } + + /** + * @param string $mainTaskDn + * @return array + * Note: Retrieve the configuration from the main extract task. + */ + private function getExtractMainTaskConfig(string $mainTaskDn): array + { + return $this->gateway->getLdapTasks( + '(objectClass=fdExtractorTasks)', + ['fdExtractorTaskFormat', 'cn'], + '', + $mainTaskDn + ); + } + + /** + * @param string $userDn + * @param array $mainTaskConfig + * @return array + * Note: Get all user attributes from the user DN. + */ + private function getUserAttributes(string $userDn, array $mainTaskConfig): array + { + // Get all user data from LDAP + $userData = $this->gateway->getLdapTasks( + '(objectClass=*)', + ['*'], + '', + $userDn + ); + + // Process and return user data + $this->gateway->unsetCountKeys($userData); + return $userData; + } + + /** + * @param string $path + * @return bool + * @throws Exception + * Note: Create directory if it doesn't exist. + */ + private function ensureDirectoryExists(string $path): bool + { + if (!is_dir($path)) { + if (!mkdir($path, 0755, true)) { + throw new Exception("Failed to create directory: $path"); + } + } + return true; + } + + /** + * @param array $userAttributes + * @param string $filename + * @param string $format + * @return bool + * @throws Exception + * Note: Extract user attributes to a file. + */ + private function extractToFile(array $userAttributes, string $filename, string $format): bool + { + switch (strtolower($format)) { + case 'csv': + return $this->exportToCsv($userAttributes, $filename); + case 'json': + return $this->exportToJson($userAttributes, $filename); + case 'xml': + return $this->exportToXml($userAttributes, $filename); + default: + return $this->exportToCsv($userAttributes, $filename); + } + } + + /** + * @param array $userAttributes + * @param string $filename + * @return bool + * @throws Exception + * Note: Export user attributes to CSV. + */ + private function exportToCsv(array $userAttributes, string $filename): bool + { + $fileExists = file_exists($filename); + $handle = fopen($filename, 'a'); + + if ($handle === false) { + throw new Exception("Could not open file: $filename"); + } + + try { + if (empty($userAttributes)) { + return true; // No attributes to write + } + + $user = $userAttributes[0]; + $columns = []; + $data = []; + + // Prepare columns and data + foreach ($user as $attribute => $values) { + if (is_array($values)) { + foreach ($values as $key => $value) { + if (is_numeric($key)) { + $columns[] = $attribute; + $data[] = $value; + break; // Only take the first value for simplicity + } + } + } + } + + // Write header if file is new + if (!$fileExists) { + fputcsv($handle, $columns); + } + + // Write data + fputcsv($handle, $data); + + return true; + } finally { + fclose($handle); + } + } + + /** + * @param array $userAttributes + * @param string $filename + * @return bool + * Note: Export user attributes to JSON. + */ + private function exportToJson(array $userAttributes, string $filename): bool + { + $existingData = []; + + // Read existing data if file exists + if (file_exists($filename)) { + $existingJson = file_get_contents($filename); + if (!empty($existingJson)) { + $existingData = json_decode($existingJson, true) ?? []; + } + } + + // Add new data + $existingData[] = $userAttributes[0]; + + // Write back to file + return file_put_contents($filename, json_encode($existingData, JSON_PRETTY_PRINT)) !== false; + } + + /** + * @param array $userAttributes + * @param string $filename + * @return bool + * Note: Export user attributes to XML. + */ + private function exportToXml(array $userAttributes, string $filename): bool + { + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = true; + + // Create root element if file doesn't exist + if (file_exists($filename)) { + $dom->load($filename); + $root = $dom->documentElement; + } else { + $root = $dom->createElement('users'); + $dom->appendChild($root); + } + + // Add new user element + $user = $dom->createElement('user'); + + foreach ($userAttributes[0] as $attribute => $values) { + if (is_array($values)) { + foreach ($values as $key => $value) { + if (is_numeric($key)) { + $attr = $dom->createElement($attribute, htmlspecialchars($value)); + $user->appendChild($attr); + } + } + } + } + + $root->appendChild($user); + + // Write to file + return $dom->save($filename) !== false; + } + + /** + * Get the CN (Common Name) of the main task + * + * @param string $mainTaskDn + * @return string + */ + private function getMainTaskCn(string $mainTaskDn): string + { + $mainTask = $this->gateway->getLdapTasks( + '(objectClass=*)', + ['cn'], + '', + $mainTaskDn + ); + + return $mainTask[0]['cn'][0] ?? 'extract'; + } +} \ No newline at end of file -- GitLab From 1e3d445cdae931cccaaf3f27435b2c59bf41e0a4 Mon Sep 17 00:00:00 2001 From: Thibault Dockx <thibault.dockx@fusiondirectory.org> Date: Fri, 4 Apr 2025 17:51:55 +0100 Subject: [PATCH 2/3] :art: feat(extractor) - enhance CSV, JSON, and XML export methods to handle duplicate UIDs and improve filename formatting --- plugins/tasks/Extractor.php | 152 ++++++++++++++++++++++++++++-------- 1 file changed, 118 insertions(+), 34 deletions(-) diff --git a/plugins/tasks/Extractor.php b/plugins/tasks/Extractor.php index 1ad125e..1faaa33 100644 --- a/plugins/tasks/Extractor.php +++ b/plugins/tasks/Extractor.php @@ -79,8 +79,8 @@ class Extractor implements EndpointInterface // Get main task CN for filename $mainTaskCn = $this->getMainTaskCn($task['fdtasksgranularmaster'][0]); - // Determine filename with main task name and date with hours - $date = date('Y-m-d_H-i-s'); + // Determine filename with main task name and date with hour (no minutes or seconds) + $date = date('Y-m-d_H'); // Using only year-month-day_hour format $filename = isset($data['filename']) ? $path . $data['filename'] . '_' . $date . '.' . $format : $path . $mainTaskCn . '_' . $date . '.' . $format; @@ -183,47 +183,99 @@ class Extractor implements EndpointInterface * @param string $filename * @return bool * @throws Exception - * Note: Export user attributes to CSV. + * Note: Export user attributes to CSV, preventing duplicate UIDs and handling new attributes. */ private function exportToCsv(array $userAttributes, string $filename): bool { - $fileExists = file_exists($filename); - $handle = fopen($filename, 'a'); - - if ($handle === false) { - throw new Exception("Could not open file: $filename"); + if (empty($userAttributes)) { + return true; // No attributes to write } - try { - if (empty($userAttributes)) { - return true; // No attributes to write + $user = $userAttributes[0]; + $userData = []; + $allColumns = []; + $existingData = []; + $uidKey = 'uid'; // The attribute to check for duplicates + $newUserUid = ''; + + // Extract UID and prepare user data + foreach ($user as $attribute => $values) { + if (is_array($values)) { + foreach ($values as $key => $value) { + if (is_numeric($key)) { + $userData[$attribute] = $value; + $allColumns[$attribute] = true; // Use as associative array to avoid duplicates + + if (strtolower($attribute) === $uidKey) { + $newUserUid = $value; + } + + break; // Only take the first value for simplicity + } + } } - - $user = $userAttributes[0]; - $columns = []; - $data = []; - - // Prepare columns and data - foreach ($user as $attribute => $values) { - if (is_array($values)) { - foreach ($values as $key => $value) { - if (is_numeric($key)) { - $columns[] = $attribute; - $data[] = $value; - break; // Only take the first value for simplicity + } + + // If no UID found, generate a random one + if (empty($newUserUid)) { + $newUserUid = 'user_' . uniqid(); + $userData[$uidKey] = $newUserUid; + $allColumns[$uidKey] = true; + } + + // Read existing file if it exists + if (file_exists($filename)) { + $handle = fopen($filename, 'r'); + if ($handle !== false) { + // Read headers + $headers = fgetcsv($handle); + if ($headers !== false) { + // Add existing headers to all columns + foreach ($headers as $header) { + $allColumns[$header] = true; + } + + // Read existing data + while (($row = fgetcsv($handle)) !== false) { + $rowData = []; + foreach ($headers as $index => $header) { + $rowData[$header] = $row[$index] ?? ''; + } + // Only add to existing data if it's not the same UID as new user + if (isset($rowData[$uidKey]) && $rowData[$uidKey] !== $newUserUid) { + $existingData[] = $rowData; } } } + fclose($handle); } + } + + // Convert all columns associative array to indexed array + $finalColumns = array_keys($allColumns); + + // Add new user data to existing data + $existingData[] = $userData; + + // Write to file + $handle = fopen($filename, 'w'); // 'w' to overwrite with complete data + if ($handle === false) { + throw new Exception("Could not open file: $filename"); + } + + try { + // Write headers + fputcsv($handle, $finalColumns); - // Write header if file is new - if (!$fileExists) { - fputcsv($handle, $columns); + // Write data rows + foreach ($existingData as $row) { + $outputRow = []; + foreach ($finalColumns as $column) { + $outputRow[] = $row[$column] ?? ''; // Use empty string if attribute not found + } + fputcsv($handle, $outputRow); } - // Write data - fputcsv($handle, $data); - return true; } finally { fclose($handle); @@ -234,17 +286,31 @@ class Extractor implements EndpointInterface * @param array $userAttributes * @param string $filename * @return bool - * Note: Export user attributes to JSON. + * Note: Export user attributes to JSON with duplicate UID handling. */ private function exportToJson(array $userAttributes, string $filename): bool { $existingData = []; + $uidKey = 'uid'; + $newUserUid = ''; + + // Get UID of new user + if (!empty($userAttributes[0][$uidKey][0])) { + $newUserUid = $userAttributes[0][$uidKey][0]; + } // Read existing data if file exists if (file_exists($filename)) { $existingJson = file_get_contents($filename); if (!empty($existingJson)) { - $existingData = json_decode($existingJson, true) ?? []; + $jsonData = json_decode($existingJson, true) ?? []; + + // Filter out any entries with the same UID + foreach ($jsonData as $entry) { + if (!isset($entry[$uidKey][0]) || $entry[$uidKey][0] !== $newUserUid) { + $existingData[] = $entry; + } + } } } @@ -259,17 +325,35 @@ class Extractor implements EndpointInterface * @param array $userAttributes * @param string $filename * @return bool - * Note: Export user attributes to XML. + * Note: Export user attributes to XML with duplicate UID handling. */ private function exportToXml(array $userAttributes, string $filename): bool { $dom = new DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; + $uidKey = 'uid'; + $newUserUid = ''; - // Create root element if file doesn't exist + // Get UID of new user + if (!empty($userAttributes[0][$uidKey][0])) { + $newUserUid = $userAttributes[0][$uidKey][0]; + } + + // Create or load XML document if (file_exists($filename)) { $dom->load($filename); $root = $dom->documentElement; + + // Remove any existing user with the same UID + if (!empty($newUserUid)) { + $xpath = new DOMXPath($dom); + $users = $xpath->query("/users/user[{$uidKey}='{$newUserUid}']"); + if ($users->length > 0) { + foreach ($users as $user) { + $root->removeChild($user); + } + } + } } else { $root = $dom->createElement('users'); $dom->appendChild($root); -- GitLab From a6a64fbaa76a5a5d2abb3a4d17949b51e7a91343 Mon Sep 17 00:00:00 2001 From: Thibault Dockx <thibault.dockx@fusiondirectory.org> Date: Mon, 7 Apr 2025 14:05:34 +0100 Subject: [PATCH 3/3] :art: style(extractor) - improve code formatting by adding spaces in function signatures for better readability --- plugins/tasks/Extractor.php | 140 ++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/plugins/tasks/Extractor.php b/plugins/tasks/Extractor.php index 1faaa33..d9b7d81 100644 --- a/plugins/tasks/Extractor.php +++ b/plugins/tasks/Extractor.php @@ -4,7 +4,7 @@ class Extractor implements EndpointInterface { private TaskGateway $gateway; - public function __construct(TaskGateway $gateway) + public function __construct (TaskGateway $gateway) { $this->gateway = $gateway; } @@ -13,7 +13,7 @@ class Extractor implements EndpointInterface * @return array * Part of the interface of orchestrator plugin to treat GET method */ - public function processEndPointGet(): array + public function processEndPointGet (): array { // Retrieve tasks of type 'extract' return $this->gateway->getObjectTypeTask('extract'); @@ -24,7 +24,7 @@ class Extractor implements EndpointInterface * @return array * Note: Part of the interface of orchestrator plugin to treat POST method */ - public function processEndPointPost(array $data = NULL): array + public function processEndPointPost (array $data = NULL): array { return []; } @@ -34,7 +34,7 @@ class Extractor implements EndpointInterface * @return array * Note: Part of the interface of orchestrator plugin to treat DELETE method */ - public function processEndPointDelete(array $data = NULL): array + public function processEndPointDelete (array $data = NULL): array { return []; } @@ -45,11 +45,11 @@ class Extractor implements EndpointInterface * @throws Exception * Note: Part of the interface of orchestrator plugin to treat PATCH method */ - public function processEndPointPatch(array $data = NULL): array + public function processEndPointPatch (array $data = NULL): array { $result = []; $extractTasks = $this->gateway->getObjectTypeTask('extract'); - + // Path is now expected in the JSON body ($data) $path = $data['path'] ?? '/srv/orchestrator/'; @@ -62,39 +62,39 @@ class Extractor implements EndpointInterface // Get the main task configuration $mainTaskConfig = $this->getExtractMainTaskConfig($task['fdtasksgranularmaster'][0]); - + // Get user DN from the task $userDn = $task['fdtasksgranulardn'][0]; - + // Get user attributes $userAttributes = $this->getUserAttributes($userDn, $mainTaskConfig); - + // Format comes from the main task configuration - $format = isset($mainTaskConfig[0]['fdextractortaskformat']) ? + $format = isset($mainTaskConfig[0]['fdextractortaskformat']) ? strtolower($mainTaskConfig[0]['fdextractortaskformat'][0]) : 'csv'; - + // Create directory if it doesn't exist $this->ensureDirectoryExists($path); - + // Get main task CN for filename $mainTaskCn = $this->getMainTaskCn($task['fdtasksgranularmaster'][0]); - + // Determine filename with main task name and date with hour (no minutes or seconds) $date = date('Y-m-d_H'); // Using only year-month-day_hour format - $filename = isset($data['filename']) ? - $path . $data['filename'] . '_' . $date . '.' . $format : + $filename = isset($data['filename']) ? + $path . $data['filename'] . '_' . $date . '.' . $format : $path . $mainTaskCn . '_' . $date . '.' . $format; - + // Extract and write to file $success = $this->extractToFile($userAttributes, $filename, $format); - + if ($success) { $result[$task['dn']]['result'] = "User attributes successfully extracted to $filename"; $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2'); } else { throw new Exception("Failed to write data to $filename"); } - + } catch (Exception $e) { $result[$task['dn']]['result'] = "Error extracting user attributes: " . $e->getMessage(); $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage()); @@ -109,7 +109,7 @@ class Extractor implements EndpointInterface * @return array * Note: Retrieve the configuration from the main extract task. */ - private function getExtractMainTaskConfig(string $mainTaskDn): array + private function getExtractMainTaskConfig (string $mainTaskDn): array { return $this->gateway->getLdapTasks( '(objectClass=fdExtractorTasks)', @@ -125,7 +125,7 @@ class Extractor implements EndpointInterface * @return array * Note: Get all user attributes from the user DN. */ - private function getUserAttributes(string $userDn, array $mainTaskConfig): array + private function getUserAttributes (string $userDn, array $mainTaskConfig): array { // Get all user data from LDAP $userData = $this->gateway->getLdapTasks( @@ -134,7 +134,7 @@ class Extractor implements EndpointInterface '', $userDn ); - + // Process and return user data $this->gateway->unsetCountKeys($userData); return $userData; @@ -146,14 +146,14 @@ class Extractor implements EndpointInterface * @throws Exception * Note: Create directory if it doesn't exist. */ - private function ensureDirectoryExists(string $path): bool + private function ensureDirectoryExists (string $path): bool { if (!is_dir($path)) { - if (!mkdir($path, 0755, true)) { + if (!mkdir($path, 0755, TRUE)) { throw new Exception("Failed to create directory: $path"); } } - return true; + return TRUE; } /** @@ -164,7 +164,7 @@ class Extractor implements EndpointInterface * @throws Exception * Note: Extract user attributes to a file. */ - private function extractToFile(array $userAttributes, string $filename, string $format): bool + private function extractToFile (array $userAttributes, string $filename, string $format): bool { switch (strtolower($format)) { case 'csv': @@ -185,58 +185,58 @@ class Extractor implements EndpointInterface * @throws Exception * Note: Export user attributes to CSV, preventing duplicate UIDs and handling new attributes. */ - private function exportToCsv(array $userAttributes, string $filename): bool + private function exportToCsv (array $userAttributes, string $filename): bool { if (empty($userAttributes)) { - return true; // No attributes to write + return TRUE; // No attributes to write } - + $user = $userAttributes[0]; $userData = []; $allColumns = []; $existingData = []; $uidKey = 'uid'; // The attribute to check for duplicates $newUserUid = ''; - + // Extract UID and prepare user data foreach ($user as $attribute => $values) { if (is_array($values)) { foreach ($values as $key => $value) { if (is_numeric($key)) { - $userData[$attribute] = $value; - $allColumns[$attribute] = true; // Use as associative array to avoid duplicates - + $userData[$attribute] = $value; + $allColumns[$attribute] = TRUE; // Use as associative array to avoid duplicates + if (strtolower($attribute) === $uidKey) { $newUserUid = $value; } - + break; // Only take the first value for simplicity } } } } - + // If no UID found, generate a random one if (empty($newUserUid)) { $newUserUid = 'user_' . uniqid(); $userData[$uidKey] = $newUserUid; - $allColumns[$uidKey] = true; + $allColumns[$uidKey] = TRUE; } - + // Read existing file if it exists if (file_exists($filename)) { $handle = fopen($filename, 'r'); - if ($handle !== false) { + if ($handle !== FALSE) { // Read headers $headers = fgetcsv($handle); - if ($headers !== false) { + if ($headers !== FALSE) { // Add existing headers to all columns foreach ($headers as $header) { - $allColumns[$header] = true; + $allColumns[$header] = TRUE; } - + // Read existing data - while (($row = fgetcsv($handle)) !== false) { + while (($row = fgetcsv($handle)) !== FALSE) { $rowData = []; foreach ($headers as $index => $header) { $rowData[$header] = $row[$index] ?? ''; @@ -250,23 +250,23 @@ class Extractor implements EndpointInterface fclose($handle); } } - + // Convert all columns associative array to indexed array $finalColumns = array_keys($allColumns); - + // Add new user data to existing data $existingData[] = $userData; - + // Write to file $handle = fopen($filename, 'w'); // 'w' to overwrite with complete data - if ($handle === false) { + if ($handle === FALSE) { throw new Exception("Could not open file: $filename"); } - + try { // Write headers fputcsv($handle, $finalColumns); - + // Write data rows foreach ($existingData as $row) { $outputRow = []; @@ -275,8 +275,8 @@ class Extractor implements EndpointInterface } fputcsv($handle, $outputRow); } - - return true; + + return TRUE; } finally { fclose($handle); } @@ -288,23 +288,23 @@ class Extractor implements EndpointInterface * @return bool * Note: Export user attributes to JSON with duplicate UID handling. */ - private function exportToJson(array $userAttributes, string $filename): bool + private function exportToJson (array $userAttributes, string $filename): bool { $existingData = []; $uidKey = 'uid'; $newUserUid = ''; - + // Get UID of new user if (!empty($userAttributes[0][$uidKey][0])) { $newUserUid = $userAttributes[0][$uidKey][0]; } - + // Read existing data if file exists if (file_exists($filename)) { $existingJson = file_get_contents($filename); if (!empty($existingJson)) { - $jsonData = json_decode($existingJson, true) ?? []; - + $jsonData = json_decode($existingJson, TRUE) ?? []; + // Filter out any entries with the same UID foreach ($jsonData as $entry) { if (!isset($entry[$uidKey][0]) || $entry[$uidKey][0] !== $newUserUid) { @@ -313,12 +313,12 @@ class Extractor implements EndpointInterface } } } - + // Add new data $existingData[] = $userAttributes[0]; - + // Write back to file - return file_put_contents($filename, json_encode($existingData, JSON_PRETTY_PRINT)) !== false; + return file_put_contents($filename, json_encode($existingData, JSON_PRETTY_PRINT)) !== FALSE; } /** @@ -327,23 +327,23 @@ class Extractor implements EndpointInterface * @return bool * Note: Export user attributes to XML with duplicate UID handling. */ - private function exportToXml(array $userAttributes, string $filename): bool + private function exportToXml (array $userAttributes, string $filename): bool { $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->formatOutput = true; + $dom->formatOutput = TRUE; $uidKey = 'uid'; $newUserUid = ''; - + // Get UID of new user if (!empty($userAttributes[0][$uidKey][0])) { $newUserUid = $userAttributes[0][$uidKey][0]; } - + // Create or load XML document if (file_exists($filename)) { $dom->load($filename); $root = $dom->documentElement; - + // Remove any existing user with the same UID if (!empty($newUserUid)) { $xpath = new DOMXPath($dom); @@ -358,10 +358,10 @@ class Extractor implements EndpointInterface $root = $dom->createElement('users'); $dom->appendChild($root); } - + // Add new user element $user = $dom->createElement('user'); - + foreach ($userAttributes[0] as $attribute => $values) { if (is_array($values)) { foreach ($values as $key => $value) { @@ -372,20 +372,20 @@ class Extractor implements EndpointInterface } } } - + $root->appendChild($user); - + // Write to file - return $dom->save($filename) !== false; + return $dom->save($filename) !== FALSE; } /** * Get the CN (Common Name) of the main task - * + * * @param string $mainTaskDn * @return string */ - private function getMainTaskCn(string $mainTaskDn): string + private function getMainTaskCn (string $mainTaskDn): string { $mainTask = $this->gateway->getLdapTasks( '(objectClass=*)', @@ -393,7 +393,7 @@ class Extractor implements EndpointInterface '', $mainTaskDn ); - + return $mainTask[0]['cn'][0] ?? 'extract'; } } \ No newline at end of file -- GitLab