Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schedule Criteria: CMS API + XMR update to displays #2686

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions lib/Controller/DisplayGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/
namespace Xibo\Controller;

use Psr\Http\Message\ResponseInterface;
use Slim\Http\Response as Response;
use Slim\Http\ServerRequest as Request;
use Xibo\Entity\Display;
Expand All @@ -36,14 +37,17 @@
use Xibo\Factory\TagFactory;
use Xibo\Service\PlayerActionServiceInterface;
use Xibo\Support\Exception\AccessDeniedException;
use Xibo\Support\Exception\ControllerNotImplemented;
use Xibo\Support\Exception\GeneralException;
use Xibo\Support\Exception\InvalidArgumentException;
use Xibo\Support\Exception\NotFoundException;
use Xibo\XMR\ChangeLayoutAction;
use Xibo\XMR\CollectNowAction;
use Xibo\XMR\CommandAction;
use Xibo\XMR\OverlayLayoutAction;
use Xibo\XMR\PlayerActionException;
use Xibo\XMR\RevertToSchedule;
use Xibo\XMR\ScheduleCriteriaUpdateAction;
use Xibo\XMR\TriggerWebhookAction;

/**
Expand Down Expand Up @@ -2869,6 +2873,120 @@ public function triggerWebhook(Request $request, Response $response, $id)
'id' => $displayGroup->displayGroupId
]);

return $this->render($request, $response);
}

/**
* @SWG\Post(
* path="/displaygroup/criteria[/{displayGroupId}]",
* operationId="ScheduleCriteriaUpdate",
* tags={"displayGroup"},
* summary="Action: Push Criteria Update",
* description="Send criteria updates to the specified DisplayGroup or to all displays if displayGroupId is not
* provided.",
* @SWG\Parameter(
* name="displayGroupId",
* in="path",
* description="The display group id",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="criteriaUpdates",
* in="body",
* description="The criteria updates to send to the Player",
* required=true,
* @SWG\Schema(
* type="array",
* @SWG\Items(
* type="object",
* @SWG\Property(property="metric", type="string"),
* @SWG\Property(property="value", type="string"),
* @SWG\Property(property="ttl", type="integer")
* )
* )
* ),
* @SWG\Response(
* response=204,
* description="Successful operation"
* ),
* @SWG\Response(
* response=400,
* description="Invalid criteria format"
* )
* )
*
* @param Request $request
nadzpogi marked this conversation as resolved.
Show resolved Hide resolved
* @param Response $response
* @param int|null $displayGroupId
* @return ResponseInterface|Response
* @throws ControllerNotImplemented
* @throws GeneralException
* @throws NotFoundException
* @throws PlayerActionException
*/
public function pushCriteriaUpdate(Request $request, Response $response, int $displayGroupId = null): Response|ResponseInterface
{
$sanitizedParams = $this->getSanitizer($request->getParams());

// Get criteria updates
$criteriaUpdates = $sanitizedParams->getArray('criteriaUpdates');

// ensure criteria updates exists
if (empty($criteriaUpdates)) {
throw new InvalidArgumentException(__('No criteria found.'), 'criteriaUpdates');
}

// Initialize array to hold sanitized criteria updates
$sanitizedCriteriaUpdates = [];

// Loop through each criterion and sanitize the input
foreach ($criteriaUpdates as $criteria) {
$criteriaSanitizer = $this->getSanitizer($criteria);

// Sanitize and retrieve the metric, value, and ttl
$metric = $criteriaSanitizer->getString('metric');
$value = $criteriaSanitizer->getString('value');
$ttl = $criteriaSanitizer->getInt('ttl');

// Ensure each criterion has metric, value, and ttl
if (empty($metric) || empty($value) || empty($ttl)) {
nadzpogi marked this conversation as resolved.
Show resolved Hide resolved
// Throw an exception if any of the required fields are missing or empty
throw new PlayerActionException(
__('Invalid criteria format. Metric, value, and ttl must all be present and not empty.')
);
}

// Add sanitized criteria
$sanitizedCriteriaUpdates[] = [
'metric' => $metric,
'value' => $value,
'ttl' => $ttl
];
}

if ($displayGroupId !== null) {
nadzpogi marked this conversation as resolved.
Show resolved Hide resolved
// fetch displays under the Display Group
$displayGroup = $this->displayFactory->getByDisplayGroupId($displayGroupId);
} else {
// fetch all displays regardless of Display Group
$displayGroup = $this->displayFactory->query();
}

// Create and send the player action
$this->playerAction->sendAction(
$displayGroup,
(new ScheduleCriteriaUpdateAction())->setCriteriaUpdates($sanitizedCriteriaUpdates)
);

// Return
$this->getState()->hydrate([
'httpStatus' => 204,
'message' => __('Schedule criteria updates sent to players.'),
'id' => $displayGroupId
]);


return $this->render($request, $response);
}
}
67 changes: 67 additions & 0 deletions lib/XMR/ScheduleCriteriaUpdateAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/*
* Copyright (C) 2024 Xibo Signage Ltd
*
* Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
* Xibo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Xibo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
*/

namespace Xibo\XMR;

/**
* Class ScheduleCriteriaUpdateAction
* @package Xibo\XMR
*/
class ScheduleCriteriaUpdateAction extends PlayerAction
{
/**
* @var array
*/
public $criteriaUpdates = [];

public function __construct()
{
$this->setQos(10);
}

/**
* Set criteria updates
* @param array $criteriaUpdates an array of criteria updates
* @return $this
*/
public function setCriteriaUpdates(array $criteriaUpdates)
{
$this->criteriaUpdates = $criteriaUpdates;
return $this;
}

/**
* @inheritdoc
*/
public function getMessage(): string
{
$this->action = 'criteriaUpdate';

// Ensure criteriaUpdates array is not empty
if (empty($this->criteriaUpdates)) {
// Throw an exception if criteriaUpdates is not provided
throw new PlayerActionException(__('Criteria updates not provided.'));
}

return $this->serializeToJson(['criteriaUpdates']);
}
}
1 change: 1 addition & 0 deletions lib/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@
$app->post('/displaygroup', ['\Xibo\Controller\DisplayGroup','add'])
->addMiddleware(new \Xibo\Middleware\FeatureAuth($app->getContainer(), ['displaygroup.add']))
->setName('displayGroup.add');
$app->post('/displaygroup/criteria[/{displayGroupId}]', ['\Xibo\Controller\DisplayGroup','pushCriteriaUpdate'])->setName('displayGroup.criteria.push');

$app->post('/displaygroup/{id}/action/collectNow', ['\Xibo\Controller\DisplayGroup','collectNow'])
->addMiddleware(new \Xibo\Middleware\FeatureAuth($app->getContainer(), ['displaygroup.view']))
Expand Down
Loading