BrightcoveVideoController.php in Brightcove Video Connect 3.x
Same filename and directory in other branches
Namespace
Drupal\brightcove\ControllerFile
src/Controller/BrightcoveVideoController.phpView source
<?php
namespace Drupal\brightcove\Controller;
use Brightcove\API\Exception\APIException;
use Drupal\brightcove\BrightcoveUtil;
use Drupal\brightcove\Entity\BrightcoveTextTrack;
use Drupal\brightcove\Entity\BrightcoveVideo;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\Queue\QueueInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Provides controller for video related callbacks.
*/
class BrightcoveVideoController extends ControllerBase {
/**
* Database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $connection;
/**
* The brightcove_video storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $videoStorage;
/**
* The brightcove_text_track storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $textTrackStorage;
/**
* The video queue object.
*
* @var \Drupal\Core\Queue\QueueInterface
*/
protected $videoQueue;
/**
* Key-value expirable store.
*
* @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface
*/
protected $keyValueExpirable;
/**
* Lock backend.
*
* @var \Drupal\Core\Lock\LockBackendInterface
*/
protected $lock;
/**
* Controller constructor.
*
* @param \Drupal\Core\Database\Connection $connection
* Database connection.
* @param \Drupal\Core\Entity\EntityStorageInterface $video_storage
* Brightcove Video entity storage.
* @param \Drupal\Core\Entity\EntityStorageInterface $text_track_storage
* Brightcove Text Track entity storage.
* @param \Drupal\Core\Queue\QueueInterface $video_queue
* The Video queue object.
* @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $key_value_expirable
* Key-value expirable store.
* @param \Drupal\Core\Lock\LockBackendInterface $lock
* Lock backend.
*/
public function __construct(Connection $connection, EntityStorageInterface $video_storage, EntityStorageInterface $text_track_storage, QueueInterface $video_queue, KeyValueExpirableFactoryInterface $key_value_expirable, LockBackendInterface $lock) {
$this->connection = $connection;
$this->videoStorage = $video_storage;
$this->textTrackStorage = $text_track_storage;
$this->videoQueue = $video_queue;
$this->keyValueExpirable = $key_value_expirable;
$this->lock = $lock;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('database'), $container
->get('entity_type.manager')
->getStorage('brightcove_video'), $container
->get('entity_type.manager')
->getStorage('brightcove_text_track'), $container
->get('queue')
->get('brightcove_video_queue_worker'), $container
->get('keyvalue.expirable'), $container
->get('lock'));
}
/**
* Menu callback to update the existing Video with the latest version.
*
* @param int $entity_id
* The ID of the video in Drupal.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* Redirection response.
*/
public function update($entity_id) {
/** @var \Drupal\brightcove\Entity\BrightcoveVideo $video_entity */
$video_entity = BrightcoveVideo::load($entity_id);
/** @var \Brightcove\API\CMS $cms */
$cms = BrightcoveUtil::getCmsApi($video_entity
->getApiClient());
// Update video.
$video = $cms
->getVideo($video_entity
->getBrightcoveId());
$this->videoQueue
->createItem([
'api_client_id' => $video_entity
->getApiClient(),
'video' => $video,
]);
// Run batch.
batch_set([
'operations' => [
[
[
BrightcoveUtil::class,
'runQueue',
],
[
'brightcove_video_queue_worker',
],
],
[
[
BrightcoveUtil::class,
'runQueue',
],
[
'brightcove_text_track_queue_worker',
],
],
[
[
BrightcoveUtil::class,
'runQueue',
],
[
'brightcove_text_track_delete_queue_worker',
],
],
],
]);
// Run batch and redirect back to the video edit form.
return batch_process(Url::fromRoute('entity.brightcove_video.edit_form', [
'brightcove_video' => $entity_id,
]));
}
/**
* Ingestion callback for Brightcove.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* Request object.
* @param int $token
* The token which matches the video ID.
*
* @return \Symfony\Component\HttpFoundation\Response
* An empty Response object.
*/
public function ingestionCallback(Request $request, $token) {
$status = BrightcoveUtil::runWithSemaphore(function () use ($request, $token) {
$content = Json::decode($request
->getContent());
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \Exception('Failed to decode JSON from response: ' . json_last_error_msg());
}
if (is_array($content) && $content['status'] == 'SUCCESS' && $content['version'] == 1 && $content['action'] == 'CREATE') {
$video_id = $this->keyValueExpirable
->get('brightcove_callback')
->get($token);
if (!empty($video_id)) {
/** @var \Drupal\brightcove\Entity\BrightcoveVideo $video_entity */
$video_entity = BrightcoveVideo::load($video_id);
if (!is_null($video_entity)) {
$cms = BrightcoveUtil::getCmsApi($video_entity
->getApiClient());
switch ($content['entityType']) {
// Video.
case 'TITLE':
// Delete video file from the entity.
$video_entity
->setVideoFile(NULL);
$video_entity
->save();
break;
// Assets.
case 'ASSET':
// Check for Text Track ID format. There is no other way to
// determine whether the asset is a text track or something
// else...
if (preg_match('/^\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}$/i', $content['entity'])) {
$text_tracks = $video_entity
->getTextTracks();
foreach ($text_tracks as $key => $text_track) {
if (!empty($text_track['target_id'])) {
/** @var \Drupal\brightcove\Entity\BrightcoveTextTrack $text_track_entity */
$text_track_entity = BrightcoveTextTrack::load($text_track['target_id']);
if (!is_null($text_track_entity) && empty($text_track_entity
->getTextTrackId())) {
// Remove text track without Brightcove ID.
$text_track_entity
->delete();
// Try to find the ingested text track on the video
// object and recreate it.
$cms = BrightcoveUtil::getCmsApi($video_entity
->getApiClient());
$video = $cms
->getVideo($video_entity
->getBrightcoveId());
$api_text_tracks = $video
->getTextTracks();
$found_api_text_track = NULL;
foreach ($api_text_tracks as $api_text_track) {
if ($api_text_track
->getId() == $content['entity']) {
$found_api_text_track = $api_text_track;
break;
}
}
// Create new text track.
if (!is_null($found_api_text_track)) {
BrightcoveTextTrack::createOrUpdate($found_api_text_track, $this->textTrackStorage, $video_entity
->id());
}
// We need to process only one per request.
break;
}
}
}
}
else {
$client = BrightcoveUtil::getClient($video_entity
->getApiClient());
$api_client = BrightcoveUtil::getApiClient($video_entity
->getApiClient());
// Check for each asset type by try-and-error, currently there
// is no other way to determine which asset is what...
$asset_types = [
BrightcoveVideo::IMAGE_TYPE_THUMBNAIL,
BrightcoveVideo::IMAGE_TYPE_POSTER,
];
foreach ($asset_types as $type) {
try {
$client
->request('GET', 1, 'cms', $api_client
->getAccountId(), '/videos/' . $video_entity
->getBrightcoveId() . '/assets/' . $type . '/' . $content['entity'], NULL);
switch ($type) {
case BrightcoveVideo::IMAGE_TYPE_THUMBNAIL:
case BrightcoveVideo::IMAGE_TYPE_POSTER:
$images = $cms
->getVideoImages($video_entity
->getBrightcoveId());
$function = ucfirst($type);
// @TODO: Download the image only if truly different.
// But this may not be possible without downloading
// the image.
$video_entity
->saveImage($type, $images
->{"get{$function}"}());
break 2;
}
} catch (APIException $e) {
// Do nothing here, just catch the exception to not
// generate an error.
}
}
}
// @TODO: Do we have to do anything with the rest of the assets?
break;
// Don't do anything if we got something else.
default:
return NULL;
}
// Update video entity with the latest update date.
$video = $cms
->getVideo($video_entity
->getBrightcoveId());
$video_entity
->setChangedTime(strtotime($video
->getUpdatedAt()));
$video_entity
->save();
}
}
}
return TRUE;
}, $this->lock);
return new Response('', $status === FALSE ? 409 : 200);
}
/**
* Destructor.
*/
public function __destruct() {
// Make sure that the semaphore gets released.
if ($this
->state()
->get('brightcove_video_semaphore', FALSE) == TRUE) {
$this
->state()
->set('brightcove_video_semaphore', FALSE);
}
}
}
Classes
Name | Description |
---|---|
BrightcoveVideoController | Provides controller for video related callbacks. |