$resource->username, 'email' => $resource->get('email'), 'fullname' => $resource->get('fullname'), 'title' => $resource->get('title'), 'state' => $resource->get('state', 'enabled'), 'language' => $resource->get('language', ''), 'content_editor' => $resource->get('content_editor', ''), 'access' => $resource->get('access', []), 'groups' => array_values(array_filter( (array) $resource->get('groups', []), 'is_string', )), 'avatar_url' => self::resolveAvatarUrl($resource), 'twofa_enabled' => (bool) $resource->get('twofa_enabled', false), 'twofa_secret' => $resource->get('twofa_secret') ? true : false, 'created' => $this->formatTimestamp($resource->get('created')), 'modified' => $this->formatTimestamp($resource->get('modified')), ]; } /** * Resolve the avatar URL for a user. * Returns the URL to an uploaded avatar, or null if none exists. */ public static function resolveAvatarUrl(UserInterface $resource): ?string { $avatar = $resource->get('avatar'); // Avatar is stored as { filename: { name, type, size, path } } or similar if (is_array($avatar) && !empty($avatar)) { $first = reset($avatar); if (is_array($first) && isset($first['path'])) { // path is relative to Grav root (e.g. user/accounts/avatars/file.jpg) $filePath = GRAV_ROOT . '/' . $first['path']; if (file_exists($filePath)) { // Generate a thumbnail URL via the thumbnail service $locator = \Grav\Common\Grav::instance()['locator']; $cacheDir = $locator->findResource('cache://', true, true) . '/api/thumbnails'; $thumbService = new \Grav\Plugin\Api\Services\ThumbnailService($cacheDir, 200); $filename = $thumbService->getThumbnailFilename($filePath); if ($filename) { $thumbService->getThumbnail($filePath); $config = \Grav\Common\Grav::instance()['config']; $route = $config->get('plugins.api.route', '/api'); $prefix = $config->get('plugins.api.version_prefix', 'v1'); return $route . '/' . $prefix . '/thumbnails/' . $filename; } } } } return null; } private function formatTimestamp(mixed $timestamp): ?string { if ($timestamp === null || $timestamp === 0) { return null; } return (new DateTimeImmutable('@' . (int) $timestamp)) ->setTimezone(new DateTimeZone('UTC')) ->format(DateTimeImmutable::ATOM); } }