Fix: Add proper Application.php and fix DI

- Created appinfo/Application.php (Nextcloud app bootstrap)
  - Extends OCP\AppFramework\App
  - Registers proper app ID: analyticshub
  - Loads CSS and JS files
- Removed obsolete lib/App.php file
- Updated all AppInfo::APP_NAME references to Application::APP_NAME
  - AdminController, ApiV1Controller
  - GoogleAnalyticsService, LLMService
- Fixed dependency injection in AdminController
  - Injected IConfig service properly
- Added missing use statements

This is the core fix for the app not appearing in Nextcloud.
Nextcloud requires appinfo/Application.php to initialize the app.
This commit is contained in:
WLTBAgent
2026-02-13 18:38:35 +00:00
parent 64bc88d6de
commit 13c313352c
6 changed files with 47 additions and 65 deletions

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace OCA\AnalyticsHub\AppInfo;
use OCP\AppFramework\App;
use OCP\Util;
/**
* Application class for Mini-CMO Analytics Hub
*/
class Application extends App {
public const APP_NAME = 'analyticshub';
public const APP_ID = 'analyticshub';
public function __construct(array $urlParams = []) {
parent::__construct(self::APP_ID, $urlParams);
// Load scripts and styles
Util::addStyle(self::APP_ID, 'admin');
Util::addScript(self::APP_ID, 'admin');
}
}

View File

@@ -1,50 +0,0 @@
<?php
declare(strict_types=1);
namespace OCA\AnalyticsHub;
use OCP\AppFramework\App;
use OCA\AnalyticsHub\Controller\ApiV1Controller;
use OCP\AnalyticsHub\Controller\ReportController;
use OCP\AnalyticsHub\Service\GoogleAnalyticsService;
use OCP\AnalyticsHub\Service\LLMService;
use OCP\AnalyticsHub\Service\DataProcessor;
class App extends App {
public const APP_NAME = 'analytics_hub';
public function __construct(array $urlParams = []) {
parent::__construct(self::APP_NAME, $urlParams);
// Register services
$this->registerService('GoogleAnalyticsService', function($c) {
return new GoogleAnalyticsService($c);
});
$this->registerService('LLMService', function($c) {
return new LLMService($c);
});
$this->registerService('DataProcessor', function($c) {
return new DataProcessor($c);
});
// Register controllers
$this->registerService('ApiV1Controller', function($c) {
return new ApiV1Controller($c);
});
$this->registerService('ReportController', function($c) {
return new ReportController($c);
});
$this->registerService('AdminController', function($c) {
return new AdminController($c);
});
}
public function getContainer() {
return $this->getContainer();
}

View File

@@ -10,10 +10,12 @@ use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCA\AnalyticsHub\AppInfo\Application;
use OCA\AnalyticsHub\Service\GoogleAnalyticsService; use OCA\AnalyticsHub\Service\GoogleAnalyticsService;
use OCA\AnalyticsHub\Service\LLMService; use OCA\AnalyticsHub\Service\LLMService;
use OCA\AnalyticsHub\Service\DataProcessor; use OCA\AnalyticsHub\Service\DataProcessor;
use OCP\IConfig;
/** /**
* Admin Settings Controller * Admin Settings Controller
@@ -21,15 +23,18 @@ use OCA\AnalyticsHub\Service\DataProcessor;
*/ */
class AdminController { class AdminController {
private IConfig $config;
private GoogleAnalyticsService $gaService; private GoogleAnalyticsService $gaService;
private LLMService $llmService; private LLMService $llmService;
private DataProcessor $dataProcessor; private DataProcessor $dataProcessor;
public function __construct( public function __construct(
IConfig $config,
GoogleAnalyticsService $gaService, GoogleAnalyticsService $gaService,
LLMService $llmService, LLMService $llmService,
DataProcessor $dataProcessor DataProcessor $dataProcessor
) { ) {
$this->config = $config;
$this->gaService = $gaService; $this->gaService = $gaService;
$this->llmService = $llmService; $this->llmService = $llmService;
$this->dataProcessor = $dataProcessor; $this->dataProcessor = $dataProcessor;
@@ -41,7 +46,7 @@ class AdminController {
*/ */
public function index(): TemplateResponse { public function index(): TemplateResponse {
return new TemplateResponse('analyticshub', 'admin', [ return new TemplateResponse('analyticshub', 'admin', [
'app_name' => AppInfo::APP_NAME, 'app_name' => Application::APP_NAME,
'version' => AppInfo::getVersion(), 'version' => AppInfo::getVersion(),
'status' => $this->gaService->isConfigured() ? 'configured' : 'not_configured', 'status' => $this->gaService->isConfigured() ? 'configured' : 'not_configured',
]); ]);
@@ -145,7 +150,7 @@ class AdminController {
*/ */
public function getStatus(IRequest $request): DataResponse { public function getStatus(IRequest $request): DataResponse {
$status = [ $status = [
'app_name' => AppInfo::APP_NAME, 'app_name' => Application::APP_NAME,
'version' => AppInfo::getVersion(), 'version' => AppInfo::getVersion(),
'status' => 'operational', 'status' => 'operational',
'google_analytics' => $this->gaService->isConfigured() ? 'configured' : 'not_configured', 'google_analytics' => $this->gaService->isConfigured() ? 'configured' : 'not_configured',
@@ -164,10 +169,10 @@ class AdminController {
* Helper methods * Helper methods
*/ */
private function saveConfigValue(string $key, string $value): void { private function saveConfigValue(string $key, string $value): void {
$this->getConfig()->setAppValue($key, $value, AppInfo::APP_NAME); $this->config->setAppValue(Application::APP_NAME, $key, $value);
} }
private function getConfigValue(string $key): ?string { private function getConfigValue(string $key): ?string {
return $this->getConfig()->getAppValue($key, AppInfo::APP_NAME); return $this->config->getAppValue(Application::APP_NAME, $key);
} }
} }

View File

@@ -9,6 +9,7 @@ use OCP\IResponse;
use OCP\AppFramework\Http; use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCA\AnalyticsHub\AppInfo\Application;
use OCA\AnalyticsHub\Service\GoogleAnalyticsService; use OCA\AnalyticsHub\Service\GoogleAnalyticsService;
use OCA\AnalyticsHub\Service\LLMService; use OCA\AnalyticsHub\Service\LLMService;
@@ -146,7 +147,7 @@ class ApiV1Controller {
$this->validateAgentAccess(); $this->validateAgentAccess();
$status = [ $status = [
'app_name' => AppInfo::APP_NAME, 'app_name' => Application::APP_NAME,
'version' => AppInfo::getVersion(), 'version' => AppInfo::getVersion(),
'status' => 'operational', 'status' => 'operational',
'google_analytics' => $this->gaService->isConfigured() ? 'configured' : 'not_configured', 'google_analytics' => $this->gaService->isConfigured() ? 'configured' : 'not_configured',

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace OCA\AnalyticsHub\Service; namespace OCA\AnalyticsHub\Service;
use OCA\AnalyticsHub\Model\ClientConfig; use OCA\AnalyticsHub\Model\ClientConfig;
use OCA\AnalyticsHub\AppInfo\Application;
use OCP\IConfig; use OCP\IConfig;
use OCP\Util\Logger; use OCP\Util\Logger;
use OCP\Util\SimplePDOMapper; use OCP\Util\SimplePDOMapper;
@@ -33,9 +34,9 @@ class GoogleAnalyticsService {
* Check if Google Analytics is configured * Check if Google Analytics is configured
*/ */
public function isConfigured(): bool { public function isConfigured(): bool {
$clientId = $this->config->getAppValue('google_client_id', AppInfo::APP_NAME); $clientId = $this->config->getAppValue('google_client_id', Application::APP_NAME);
$clientSecret = $this->config->getAppValue('google_client_secret', AppInfo::APP_NAME); $clientSecret = $this->config->getAppValue('google_client_secret', Application::APP_NAME);
$refreshToken = $this->config->getAppValue('google_refresh_token', AppInfo::APP_NAME); $refreshToken = $this->config->getAppValue('google_refresh_token', Application::APP_NAME);
return !empty($clientId) && !empty($clientSecret) && !empty($refreshToken); return !empty($clientId) && !empty($clientSecret) && !empty($refreshToken);
} }
@@ -44,7 +45,7 @@ class GoogleAnalyticsService {
* Check if LLM service is configured * Check if LLM service is configured
*/ */
public function isLLMConfigured(): bool { public function isLLMConfigured(): bool {
$apiKey = $this->config->getAppValue('anthropic_api_key', AppInfo::APP_NAME); $apiKey = $this->config->getAppValue('anthropic_api_key', Application::APP_NAME);
return !empty($apiKey); return !empty($apiKey);
} }
@@ -73,7 +74,7 @@ class GoogleAnalyticsService {
* Get all clients * Get all clients
*/ */
private function getClients(): array { private function getClients(): array {
$json = $this->config->getAppValue('clients_json', AppInfo::APP_NAME); $json = $this->config->getAppValue('clients_json', Application::APP_NAME);
if (empty($json)) { if (empty($json)) {
return []; return [];
} }
@@ -155,7 +156,7 @@ class GoogleAnalyticsService {
* Get fresh access token * Get fresh access token
*/ */
private function getFreshAccessToken(): string { private function getFreshAccessToken(): string {
$refreshToken = $this->config->getAppValue('google_refresh_token', AppInfo::APP_NAME); $refreshToken = $this->config->getAppValue('google_refresh_token', Application::APP_NAME);
if (empty($refreshToken)) { if (empty($refreshToken)) {
throw new \Exception('Refresh token not configured'); throw new \Exception('Refresh token not configured');
@@ -188,8 +189,8 @@ class GoogleAnalyticsService {
* Refresh access token using refresh token * Refresh access token using refresh token
*/ */
private function refreshAccessToken(string $refreshToken): ?array { private function refreshAccessToken(string $refreshToken): ?array {
$clientId = $this->config->getAppValue('google_client_id', AppInfo::APP_NAME); $clientId = $this->config->getAppValue('google_client_id', Application::APP_NAME);
$clientSecret = $this->config->getAppValue('google_client_secret', AppInfo::APP_NAME); $clientSecret = $this->config->getAppValue('google_client_secret', Application::APP_NAME);
$url = self::TOKEN_REFRESH_URL; $url = self::TOKEN_REFRESH_URL;
$data = [ $data = [

View File

@@ -32,7 +32,7 @@ class LLMService {
* Check if LLM service is configured * Check if LLM service is configured
*/ */
public function isConfigured(): bool { public function isConfigured(): bool {
$apiKey = $this->config->getAppValue('anthropic_api_key', AppInfo::APP_NAME); $apiKey = $this->config->getAppValue('anthropic_api_key', Application::APP_NAME);
return !empty($apiKey); return !empty($apiKey);
} }
@@ -43,7 +43,7 @@ class LLMService {
$this->logger->info("Generating LLM report for: {$client->getName()}"); $this->logger->info("Generating LLM report for: {$client->getName()}");
try { try {
$apiKey = $this->config->getAppValue('anthropic_api_key', AppInfo::APP_NAME); $apiKey = $this->config->getAppValue('anthropic_api_key', Application::APP_NAME);
if (empty($apiKey)) { if (empty($apiKey)) {
throw new \Exception('Anthropic API key not configured'); throw new \Exception('Anthropic API key not configured');