Skip to content

Commit

Permalink
Merge branch 'feature/DIMOC-332/broadcasting'
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenvdlinde committed Nov 2, 2024
2 parents 80b01a6 + f758fb4 commit e877d38
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 113 deletions.
11 changes: 8 additions & 3 deletions lib/Controller/CatalogiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use OCA\OpenCatalogi\Db\CatalogMapper;
use OCA\OpenCatalogi\Service\DirectoryService;
use OCA\OpenCatalogi\Service\ObjectService;
use OCA\OpenCatalogi\Service\BroadcastService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
Expand All @@ -31,14 +32,16 @@ class CatalogiController extends Controller
* @param CatalogMapper $catalogMapper The catalog mapper
* @param ObjectService $objectService The object service
* @param DirectoryService $directoryService The directory service
* @param BroadcastService $broadcastService The broadcast service
*/
public function __construct(
$appName,
IRequest $request,
private readonly IAppConfig $config,
private readonly CatalogMapper $catalogMapper,
private readonly ObjectService $objectService,
private readonly DirectoryService $directoryService
private readonly DirectoryService $directoryService,
private readonly BroadcastService $broadcastService
)
{
parent::__construct($appName, $request);
Expand Down Expand Up @@ -111,7 +114,8 @@ public function create(ObjectService $objectService): JSONResponse
// Save the new catalog object
$object = $this->objectService->saveObject('catalog', $data);

$this->directoryService->updateAllExternalDirectories();
// Update all external directories
$this->broadcastService->broadcast();

// Return the created object as a JSON response
return new JSONResponse($object);
Expand Down Expand Up @@ -141,7 +145,8 @@ public function update(string|int $id, ObjectService $objectService): JSONRespon
// Save the updated catalog object
$object = $this->objectService->saveObject('catalog', $data);

$this->directoryService->updateAllExternalDirectories();
// Update all external directories
$this->broadcastService->broadcast();

// Return the updated object as a JSON response
return new JSONResponse($object);
Expand Down
10 changes: 10 additions & 0 deletions lib/Controller/DirectoryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ public function update(): JSONResponse
return new JSONResponse(['error' => 'directory parameter is required'], 400);
}

// Check if URL contains 'local' and throw exception if it does
if (str_contains(strtolower($url), 'local')) {
return new JSONResponse(['error' => 'Local URLs are not allowed'], 400);
}

// Validate the URL
if (!filter_var($url, FILTER_VALIDATE_URL)) {
return new JSONResponse(['error' => 'Invalid URL provided'], 400);
}

// Sync the external directory with the provided URL
$data = $this->directoryService->syncExternalDirectory($url);

Expand Down
11 changes: 10 additions & 1 deletion lib/Controller/PublicationTypesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use OCA\OpenCatalogi\Db\PublicationTypeMapper;
use OCA\OpenCatalogi\Service\ObjectService;
use OCA\OpenCatalogi\Service\DirectoryService;
use OCA\OpenCatalogi\Service\BroadcastService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\JSONResponse;
Expand All @@ -27,14 +28,16 @@ class PublicationTypesController extends Controller
* @param PublicationTypeMapper $publicationTypeMapper The publication type mapper
* @param ObjectService $objectService The object service
* @param DirectoryService $directoryService The directory service
* @param BroadcastService $broadcastService The broadcast service
*/
public function __construct(
$appName,
IRequest $request,
private readonly IAppConfig $config,
private readonly PublicationTypeMapper $publicationTypeMapper,
private readonly ObjectService $objectService,
private readonly DirectoryService $directoryService
private readonly DirectoryService $directoryService,
private readonly BroadcastService $broadcastService
)
{
parent::__construct($appName, $request);
Expand Down Expand Up @@ -115,6 +118,9 @@ public function create(): JSONResponse
// Save the new publication type object
$object = $this->objectService->saveObject('publicationType', $data);

// Update all external directories
$this->broadcastService->broadcast();

// Return the created object as a JSON response
return new JSONResponse($object);
}
Expand All @@ -139,6 +145,9 @@ public function update(string|int $id): JSONResponse
// Save the updated publication type object
$object = $this->objectService->saveObject('publicationType', $data);

// Update all external directories
$this->broadcastService->broadcast();

// Return the updated object as a JSON response
return new JSONResponse($object);
}
Expand Down
87 changes: 87 additions & 0 deletions lib/Service/BroadcastService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace OCA\OpenCatalogi\Service;

use DateTime;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\IAppConfig;
use OCP\IURLGenerator;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\Uid\Uuid;
use OCA\OpenCatalogi\Service\ObjectService;

/**
* Service class for handling directory-related operations
*/
class BroadcastService
{
/** @var string The name of the app */
private string $appName = 'opencatalogi';

/** @var Client The HTTP client for making requests */
private Client $client;

/**
* Constructor for BroadcastService
*
* @param IURLGenerator $urlGenerator URL generator interface
* @param IAppConfig $config App configuration interface
* @param ObjectService $objectService Object service for handling objects
*/
public function __construct(
private readonly IURLGenerator $urlGenerator,
private readonly IAppConfig $config,
private readonly ObjectService $objectService,
)
{
$this->client = new Client([]);
}

/**
* Broadcast this OpenCatalogi directory to one or more instances
*
* @param string|null $url Optional URL of a specific instance to broadcast to
* @throws DoesNotExistException|MultipleObjectsReturnedException|ContainerExceptionInterface|NotFoundExceptionInterface|GuzzleException
*/
public function broadcast(?string $url = null): void {
// Initialize hooks array
$hooks = [];

// If URL is provided, add it to hooks
if ($url !== null) {
$hooks[] = $url;
}
// Otherwise get all unique directory URLs
else {
$listings = $this->objectService->getObjects(objectType: 'listing');
$hooks = array_unique(array_column($listings, 'directory'));
}

// Get the URL of this directory
$directoryUrl = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute('opencatalogi.directory.index'));

// Broadcast to each hook
foreach ($hooks as $hook) {
// Send POST request with directory URL
try {
$this->client->post($hook, [
'json' => [
'directory' => $directoryUrl
]
]);

// Log successful broadcast
\OC::$server->getLogger()->info('Successfully broadcasted to ' . $hook);

} catch (\Exception $e) {
// Throw a warning since broadcasting failure shouldn't break the application flow
// but we still want to notify about the issue
\OC::$server->getLogger()->warning('Failed to broadcast to ' . $hook . ': ' . $e->getMessage());
}
}
}
}
Loading

0 comments on commit e877d38

Please sign in to comment.