View source
<?php
namespace Drupal\brightcove\Entity;
use Brightcove\API\Exception\APIException;
use Brightcove\API\Request\IngestImage;
use Brightcove\API\Request\IngestRequest;
use Brightcove\API\Request\IngestRequestMaster;
use Brightcove\API\Request\IngestTextTrack;
use Brightcove\Object\Video\Link;
use Brightcove\Object\Video\Schedule;
use Brightcove\Object\Video\TextTrack;
use Brightcove\Object\Video\TextTrackSource;
use Brightcove\Object\Video\Video;
use Drupal\brightcove\BrightcoveUtil;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\brightcove\BrightcoveVideoInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\link\LinkItemInterface;
use Drupal\taxonomy\Entity\Term;
use Drupal\time_formatter\Plugin\Field\FieldFormatter\TimeFieldFormatter;
class BrightcoveVideo extends BrightcoveVideoPlaylistCmsEntity implements BrightcoveVideoInterface {
protected $ingestRequest = NULL;
protected function getIngestRequest() {
if (is_null($this->ingestRequest)) {
$this->ingestRequest = new IngestRequest();
}
return $this->ingestRequest;
}
protected function provideDefaultValuesForImageField(array &$values) {
foreach ($values as $delta => &$value) {
$file = File::load($value['target_id']);
if (!is_null($file)) {
$value += [
'display' => $file->status->value,
'description' => '',
'upload' => '',
];
}
}
}
public function saveImage($type, $image) {
$image_dir = 'public://';
switch ($type) {
case self::IMAGE_TYPE_THUMBNAIL:
$image_dir .= self::VIDEOS_IMAGES_THUMBNAILS_DIR;
break;
case self::IMAGE_TYPE_POSTER:
$image_dir .= self::VIDEOS_IMAGES_POSTERS_DIR;
break;
default:
throw new \Exception(t("Invalid type given: @type, the type argument must be either '@thumbnail' or '@poster'.", [
'@type' => $type,
'@thumbnail' => self::IMAGE_TYPE_THUMBNAIL,
'@poster' => self::IMAGE_TYPE_POSTER,
]));
}
$function = ucfirst($type);
$needs_save = TRUE;
preg_match('/\\/(?!.*\\/)([\\w-\\.]+)/i', $img_src = is_array($image) ? $image['src'] : $image
->getSrc(), $matches);
if (isset($matches[1])) {
$entity_image = $this
->{"get{$function}"}();
if (!empty($entity_image['target_id'])) {
$file = File::load($entity_image['target_id']);
if (!is_null($file) && $file
->getFileName() != $matches[1]) {
$this
->{"set{$function}"}(NULL);
}
elseif (!is_null($file) && $file
->getFilename() == $matches[1]) {
$needs_save = FALSE;
}
}
if ($needs_save) {
$image_content = file_get_contents($img_src);
if (file_prepare_directory($image_dir, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY)) {
$image_name = $matches[1];
$file = file_save_data($image_content, "{$image_dir}/{$image_name}");
if ($file !== FALSE) {
$this
->{"set{$function}"}($file
->id());
}
}
}
}
return $this;
}
private function deleteFile($target_id) {
if (!is_numeric($target_id) || $target_id <= 0) {
throw new \Exception(t('Target ID must be non-zero number.'));
}
$file = File::load($target_id);
if (!is_null($file)) {
$file
->delete();
}
return $this;
}
protected function createIngestImage($type) {
if (!in_array($type, [
self::IMAGE_TYPE_POSTER,
self::IMAGE_TYPE_THUMBNAIL,
])) {
throw new \Exception(t("Invalid type given: @type, the type argument must be either '@thumbnail' or '@poster'.", [
'@type' => $type,
'@thumbnail' => self::IMAGE_TYPE_THUMBNAIL,
'@poster' => self::IMAGE_TYPE_POSTER,
]));
}
$function = ucfirst($type);
if (!empty($this
->{"get{$function}"}()['target_id'])) {
$ingest_request = $this
->getIngestRequest();
$file = File::load($this
->{"get{$function}"}()['target_id']);
$image_factory = \Drupal::service('image.factory');
$image = $image_factory
->get($file
->getFileUri());
if (!is_null($image)) {
$ingest_image = new IngestImage();
$ingest_image
->setUrl(file_create_url($file
->getFileUri()));
$ingest_image
->setWidth($image
->getWidth());
$ingest_image
->setHeight($image
->getHeight());
$ingest_request
->{"set{$function}"}($ingest_image);
}
}
}
protected function getIngestionToken() {
$token = NULL;
try {
do {
$token = Crypt::hmacBase64($this
->getVideoId(), Crypt::randomBytesBase64() . Settings::getHashSalt());
} while (\Drupal::keyValueExpirable('brightcove_callback')
->has($token));
\Drupal::keyValueExpirable('brightcove_callback')
->setWithExpire($token, $this
->id(), \Drupal::config('brightcove.settings')
->get('notification.callbackExpirationTime'));
} catch (\Exception $e) {
watchdog_exception('brightcove', $e);
$token = NULL;
}
return $token;
}
public function getVideoId() {
return $this
->get('video_id')->value;
}
public function setVideoId($video_id) {
$this
->set('video_id', $video_id);
return $this;
}
public function getDuration() {
return $this
->get('duration')->value;
}
public function setDuration($duration) {
$this
->set('duration', $duration);
return $this;
}
public function getRelatedLink() {
$value = $this
->get('related_link')
->getValue();
if (empty($value[0])) {
return [];
}
if (!isset($value[0]['attributes'])) {
$value[0]['attributes'] = [];
}
return $value[0];
}
public function setRelatedLink($related_link) {
if (!empty($related_link['uri']) && !preg_match('/[\\w-]+:\\/\\//i', $related_link['uri'])) {
$related_link['uri'] = "http://{$related_link['uri']}";
}
$this
->set('related_link', $related_link);
return $this;
}
public function getLongDescription() {
return $this
->get('long_description')->value;
}
public function setLongDescription($long_description) {
$this
->set('long_description', $long_description);
return $this;
}
public function getEconomics() {
return $this
->get('economics')->value;
}
public function setEconomics($economics) {
$this
->set('economics', $economics);
return $this;
}
public function getVideoFile() {
$value = $this
->get('video_file')
->getValue();
if (empty($value[0]['target_id'])) {
return [];
}
if (!isset($value[0]['upload'])) {
$value[0]['upload'] = '';
}
return $value[0];
}
public function setVideoFile($video_file) {
$video_to_delete = $this
->getVideoFile();
if ($video_file == NULL && !empty($video_to_delete['target_id'])) {
$this
->deleteFile($video_to_delete['target_id']);
}
$this
->set('video_file', $video_file);
return $this;
}
public function getVideoUrl() {
return $this
->get('video_url')->value;
}
public function setVideoUrl($video_url) {
$this
->set('video_url', $video_url);
return $this;
}
public function getProfile() {
return $this
->get('profile')->value;
}
public function setProfile($profile) {
$this
->set('profile', $profile);
return $this;
}
public function getPoster() {
$values = $this
->get('poster')
->getValue();
if (empty($values[0]['target_id'])) {
return NULL;
}
$this
->provideDefaultValuesForImageField($values);
return $values[0];
}
public function setPoster($poster) {
$poster_to_delete = $this
->getPoster();
if (is_null($poster) && !empty($poster_to_delete['target_id'])) {
$this
->deleteFile($poster_to_delete['target_id']);
}
$this
->set('poster', $poster);
return $this;
}
public function getThumbnail() {
$values = $this
->get('thumbnail')
->getValue();
if (empty($values[0]['target_id'])) {
return NULL;
}
$this
->provideDefaultValuesForImageField($values);
return $values[0];
}
public function setThumbnail($thumbnail) {
$thumbnail_to_delete = $this
->getThumbnail();
if (is_null($thumbnail) && !empty($thumbnail_to_delete['target_id'])) {
$this
->deleteFile($thumbnail_to_delete['target_id']);
}
$this
->set('thumbnail', $thumbnail);
return $this;
}
public function getCustomFieldValues() {
$value = $this
->get('custom_field_values')
->getValue();
if (!empty($value)) {
return $value[0];
}
return $value;
}
public function setCustomFieldValues(array $values) {
return $this
->set('custom_field_values', $values);
}
public function getScheduleStartsAt() {
$value = $this
->get('schedule_starts_at')
->getValue();
if (empty($value)) {
return NULL;
}
return $value[0]['value'];
}
public function setScheduleStartsAt($schedule_starts_at) {
$this
->set('schedule_starts_at', $schedule_starts_at);
return $this;
}
public function getScheduleEndsAt() {
$value = $this
->get('schedule_ends_at')
->getValue();
if (empty($value)) {
return NULL;
}
return $value[0]['value'];
}
public function setScheduleEndsAt($schedule_ends_at) {
$this
->set('schedule_ends_at', $schedule_ends_at);
return $this;
}
public function getTextTracks() {
return $this
->get('text_tracks')
->getValue();
}
public function setTextTracks($text_tracks) {
return $this
->set('text_tracks', $text_tracks);
}
public static function loadByBrightcoveVideoId($account_id, $brightcove_video_id) {
$api_client_ids = \Drupal::entityQuery('brightcove_api_client')
->condition('account_id', $account_id)
->execute();
$entity_ids = \Drupal::entityQuery('brightcove_video')
->condition('api_client', reset($api_client_ids))
->condition('video_id', $brightcove_video_id)
->condition('status', 1)
->execute();
if (!empty($entity_ids)) {
return self::load(reset($entity_ids));
}
return NULL;
}
public function save($upload = FALSE) {
$status = $this
->id() ? SAVED_UPDATED : SAVED_NEW;
$saved = parent::save();
if ($upload) {
$cms = BrightcoveUtil::getCmsApi($this
->getApiClient());
$video = new Video();
$video
->setName($this
->getName());
if ($this
->isFieldChanged('description')) {
$video
->setDescription($this
->getDescription());
}
if ($this
->isFieldChanged('duration')) {
$video
->setDuration($this
->getDuration());
}
if ($this
->isFieldChanged('economics')) {
$video
->setEconomics($this
->getEconomics());
}
if ($this
->isFieldChanged('tags')) {
$term_ids = [];
foreach ($this
->getTags() as $tag) {
$term_ids[] = $tag['target_id'];
}
$terms = Term::loadMultiple($term_ids);
$tags = [];
foreach ($terms as $term) {
$tags[] = $term
->getName();
}
$video
->setTags($tags);
}
if ($this
->isFieldChanged('related_link')) {
$link = new Link();
$related_link = $this
->getRelatedLink();
$is_link_set = FALSE;
if (!empty($related_link['uri'])) {
$link
->setUrl(Url::fromUri($related_link['uri'], [
'absolute' => TRUE,
])
->toString());
$is_link_set = TRUE;
}
if (!empty($related_link['title'])) {
$link
->setText($related_link['title']);
$is_link_set = TRUE;
}
if ($is_link_set) {
$video
->setLink($link);
}
else {
$video
->setLink();
}
}
if ($this
->isFieldChanged('long_description')) {
$video
->setLongDescription($this
->getLongDescription());
}
if ($this
->isFieldChanged('reference_id')) {
$video
->setReferenceId($this
->getReferenceId());
}
$custom_field_num = \Drupal::entityQuery('brightcove_custom_field')
->condition('api_client', $this
->getApiClient())
->count()
->execute();
if ($this
->isFieldChanged('custom_field_values') && $custom_field_num) {
$video
->setCustomFields($this
->getCustomFieldValues());
}
if ($this
->isFieldChanged('schedule_starts_at') || $this
->isFieldChanged('schedule_ends_at')) {
$starts_at = $this
->getScheduleStartsAt();
$ends_at = $this
->getScheduleEndsAt();
$schedule = new Schedule();
$is_schedule_set = FALSE;
if (!is_null($starts_at)) {
$schedule
->setStartsAt($starts_at . '.000Z');
$is_schedule_set = TRUE;
}
if (!is_null($ends_at)) {
$schedule
->setEndsAt($ends_at . '.000Z');
$is_schedule_set = TRUE;
}
if ($is_schedule_set) {
$video
->setSchedule($schedule);
}
else {
$video
->setSchedule();
}
}
if ($this
->isFieldChanged('text_tracks')) {
$video_text_tracks = [];
$ingest_text_tracks = [];
foreach ($this
->getTextTracks() as $text_track) {
if (!empty($text_track['target_id'])) {
$text_track_entity = BrightcoveTextTrack::load($text_track['target_id']);
if (!is_null($text_track_entity)) {
$webvtt_file = $text_track_entity
->getWebVttFile();
if (!empty($webvtt_file[0]['target_id'])) {
$file = File::load($webvtt_file[0]['target_id']);
if (!is_null($file)) {
$ingest_text_tracks[] = (new IngestTextTrack())
->setSrclang($text_track_entity
->getSourceLanguage())
->setUrl(file_create_url($file
->getFileUri()))
->setKind($text_track_entity
->getKind())
->setLabel($text_track_entity
->getLabel())
->setDefault($text_track_entity
->isDefault());
}
}
else {
$video_text_track = (new TextTrack())
->setId($text_track_entity
->getTextTrackId())
->setSrclang($text_track_entity
->getSourceLanguage())
->setLabel($text_track_entity
->getLabel())
->setKind($text_track_entity
->getKind())
->setMimeType($text_track_entity
->getMimeType())
->setAssetId($text_track_entity
->getAssetId());
if (!empty($text_track_entity
->getAssetId())) {
$video_text_track
->setAssetId($text_track_entity
->getAssetId());
}
else {
$video_text_track
->setSrc($text_track_entity
->getSource());
}
$video_text_track_sources = [];
foreach ($text_track_entity
->getSources() as $source) {
$text_track_source = new TextTrackSource();
$text_track_source
->setSrc($source['uri']);
$video_text_track_sources[] = $text_track_source;
}
$video_text_track
->setSources($video_text_track_sources);
$video_text_tracks[] = $video_text_track;
}
}
}
}
$video
->setTextTracks($video_text_tracks);
}
if ($this
->isFieldChanged('status')) {
$video
->setState($this
->isPublished() ? self::STATE_ACTIVE : self::STATE_INACTIVE);
}
switch ($status) {
case SAVED_NEW:
$saved_video = $cms
->createVideo($video);
$this
->setVideoId($saved_video
->getId());
$this
->setCreatedTime(strtotime($saved_video
->getCreatedAt()));
break;
case SAVED_UPDATED:
$video
->setId($this
->getVideoId());
$saved_video = $cms
->updateVideo($video);
break;
}
if ($this
->isFieldChanged(self::IMAGE_TYPE_THUMBNAIL)) {
$this
->createIngestImage(self::IMAGE_TYPE_THUMBNAIL);
}
if ($this
->isFieldChanged(self::IMAGE_TYPE_POSTER)) {
$this
->createIngestImage(self::IMAGE_TYPE_POSTER);
}
if ($this
->isFieldChanged('video_file') && !empty($this
->getVideoFile())) {
$file = File::load($this
->getVideoFile()['target_id']);
$ingest_request = $this
->getIngestRequest();
$ingest_master = new IngestRequestMaster();
$ingest_master
->setUrl(file_create_url($file
->getFileUri()));
$ingest_request
->setMaster($ingest_master);
$profiles = self::getProfileAllowedValues($this
->getApiClient());
$ingest_request
->setProfile($profiles[$this
->getProfile()]);
}
if ($this
->isFieldChanged('video_url') && !empty($this
->getVideoUrl())) {
$ingest_request = $this
->getIngestRequest();
$ingest_master = new IngestRequestMaster();
$ingest_master
->setUrl($this
->getVideoUrl());
$ingest_request
->setMaster($ingest_master);
$profiles = self::getProfileAllowedValues($this
->getApiClient());
$ingest_request
->setProfile($profiles[$this
->getProfile()]);
}
if (!empty($ingest_text_tracks)) {
$ingest_request = $this
->getIngestRequest();
$ingest_request
->setTextTracks($ingest_text_tracks);
}
if (isset($saved_video)) {
$this
->setChangedTime(strtotime($saved_video
->getUpdatedAt()));
parent::save();
}
if (!is_null($this->ingestRequest)) {
$token = $this
->getIngestionToken();
if (!is_null($token)) {
$callback_url = Url::fromRoute('brightcove_ingestion_callback', [
'token' => $token,
], [
'absolute' => TRUE,
])
->toString();
$this->ingestRequest
->setCallbacks([
$callback_url,
]);
}
$di = BrightcoveUtil::getDiApi($this
->getApiClient());
$di
->createIngest($this
->getVideoId(), $this->ingestRequest);
}
}
$this->changedFields = [];
return $saved;
}
public function delete($local_only = FALSE) {
if (!$this
->isNew() && !$local_only) {
$api_client = BrightcoveUtil::getApiClient($this
->getApiClient());
$client = $api_client
->getClient();
try {
$client
->request('DELETE', 1, 'cms', $api_client
->getAccountId(), "/videos/{$this->getVideoId()}/references", NULL);
$cms = BrightcoveUtil::getCmsApi($this
->getApiClient());
$cms
->deleteVideo($this
->getVideoId());
parent::delete();
} catch (APIException $e) {
if ($e
->getCode() == 404) {
drupal_set_message(t('The video was not found on Brightcove, only the local version was deleted.'), 'warning');
parent::delete();
}
else {
drupal_set_message(t('There was an error while trying to delete the Video from Brightcove: @error', [
'@error' => $e
->getMessage(),
]), 'error');
}
}
}
else {
parent::delete();
}
}
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$weight = -30;
$fields['bcvid'] = BaseFieldDefinition::create('integer')
->setLabel(t('ID'))
->setDescription(t('The Drupal entity ID of the Brightcove Video.'))
->setReadOnly(TRUE);
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setDescription(t('The Brightcove Video UUID.'))
->setReadOnly(TRUE);
$fields['api_client'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('API Client'))
->setDescription(t('Brightcove API credentials (account) to use.'))
->setRequired(TRUE)
->setSetting('target_type', 'brightcove_api_client')
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['player'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Player'))
->setDescription(t('Brightcove Player to be used for playback.'))
->setSetting('target_type', 'brightcove_player')
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Enabled'))
->setDescription(t('Determines whether the video is playable.'))
->setDefaultValue(TRUE)
->setSettings([
'on_label' => t('Active'),
'off_label' => t('Inactive'),
])
->setDisplayOptions('form', [
'type' => 'boolean_checkbox',
'label' => 'above',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'boolean',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['name'] = BaseFieldDefinition::create('string')
->setLabel(t('Name'))
->setDescription(t('Title of the video.'))
->setRequired(TRUE)
->setSettings([
'text_processing' => 0,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'string',
'label' => 'hidden',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE);
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language code'))
->setDescription(t('The language code for the Brightcove Video.'))
->setDisplayOptions('form', [
'type' => 'language_select',
'weight' => ++$weight,
])
->setDisplayConfigurable('form', TRUE);
$fields['video_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Video ID'))
->setDescription(t('Unique Video ID assigned by Brightcove.'))
->setReadOnly(TRUE)
->setDisplayOptions('view', [
'type' => 'string',
'label' => 'inline',
'weight' => ++$weight,
])
->setDisplayConfigurable('view', TRUE);
$fields['duration'] = BaseFieldDefinition::create('integer')
->setLabel(t('Video Duration'))
->setReadOnly(TRUE)
->setDisplayOptions('view', [
'type' => 'number_time',
'label' => 'inline',
'weight' => ++$weight,
'settings' => [
'storage' => TimeFieldFormatter::STORAGE_MILLISECONDS,
'display' => TimeFieldFormatter::DISPLAY_NUMBERSMS,
],
])
->setDisplayConfigurable('view', TRUE);
$fields['description'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Short description'))
->setDescription(t('Max 250 characters.'))
->setDisplayOptions('form', [
'type' => 'string_textarea',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'basic_string',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE)
->addPropertyConstraints('value', [
'Length' => [
'max' => 250,
],
]);
$fields['tags'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Tags'))
->setDescription(t('Max 1200 tags per video'))
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
->setSettings([
'target_type' => 'taxonomy_term',
'handler_settings' => [
'target_bundles' => [
self::TAGS_VID => self::TAGS_VID,
],
'auto_create' => TRUE,
],
])
->setDisplayOptions('form', [
'type' => 'entity_reference_autocomplete',
'weight' => ++$weight,
'settings' => [
'autocomplete_type' => 'tags',
],
])
->setDisplayOptions('view', [
'type' => 'entity_reference_label',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['related_link'] = BaseFieldDefinition::create('link')
->setLabel(t('Related Link'))
->setSettings([
'max_length' => 150,
'link_type' => LinkItemInterface::LINK_GENERIC,
'title' => DRUPAL_OPTIONAL,
])
->setDisplayOptions('form', [
'type' => 'link_default',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'link',
'label' => 'inline',
'weight' => $weight,
'settings' => [
'trim_length' => 150,
'target' => '_blank',
],
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['reference_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Reference ID'))
->addConstraint('UniqueField')
->setDescription(t('Value specified must be unique'))
->setSettings([
'max_length' => 150,
'text_processing' => 0,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'string',
'label' => 'inline',
'weight' => $weight,
])
->setDefaultValueCallback(static::class . '::getDefaultReferenceId')
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['long_description'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Long description'))
->setDescription(t('Max 5000 characters'))
->setDisplayOptions('form', [
'type' => 'string_textarea',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'basic_string',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE)
->addPropertyConstraints('value', [
'Length' => [
'max' => 5000,
],
]);
$fields['economics'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Advertising'))
->setRequired(TRUE)
->setDefaultValue(self::ECONOMICS_TYPE_FREE)
->setSetting('allowed_values', [
self::ECONOMICS_TYPE_FREE => 'Free',
self::ECONOMICS_TYPE_AD_SUPPORTED => 'Ad Supported',
])
->setDisplayOptions('form', [
'type' => 'options_buttons',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'string',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['video_file'] = BaseFieldDefinition::create('file')
->setLabel(t('Video source'))
->setSettings([
'file_extensions' => '3gp 3g2 aac ac3 asf avchd avi avs bdav dv dxa ea eac3 f4v flac flv h261 h263 h264 m2p m2ts m4a m4v mjpeg mka mks mkv mov mp3 mp4 mpeg mpegts mpg mt2s mts ogg ps qt rtsp thd ts vc1 wav webm wma wmv',
'file_directory' => '[random:hash:md5]',
])
->setDisplayOptions('form', [
'type' => 'file_generic',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'file_url_plain',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['video_url'] = BaseFieldDefinition::create('uri')
->setLabel(t('Video source URL'))
->setDisplayOptions('form', [
'type' => 'uri',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'uri_link',
'label' => 'inline',
'weight' => $weight,
'settings' => [
'trim_length' => 150,
'target' => '_blank',
],
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['profile'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Encoding profile'))
->setRequired(TRUE)
->setSetting('allowed_values_function', [
self::class,
'profileAllowedValues',
])
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => ++$weight,
])
->setDisplayConfigurable('form', TRUE);
$fields['poster'] = BaseFieldDefinition::create('image')
->setLabel(t('Video Still'))
->setSettings([
'file_extensions' => 'jpg jpeg png',
'file_directory' => self::VIDEOS_IMAGES_POSTERS_DIR,
'alt_field' => FALSE,
'alt_field_required' => FALSE,
])
->setDisplayOptions('form', [
'type' => 'image_image',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'image',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['thumbnail'] = BaseFieldDefinition::create('image')
->setLabel(t('Thumbnail'))
->setSettings([
'file_extensions' => 'jpg jpeg png',
'file_directory' => self::VIDEOS_IMAGES_THUMBNAILS_DIR,
'alt_field' => FALSE,
'alt_field_required' => FALSE,
])
->setDisplayOptions('form', [
'type' => 'image_image',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'image',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['custom_field_values'] = BaseFieldDefinition::create('map');
$fields['schedule_starts_at'] = BaseFieldDefinition::create('datetime')
->setLabel(t('Scheduled Start Date'))
->setDescription(t('If not specified, the video will be Available Immediately.'))
->setDisplayOptions('form', [
'type' => 'datetime_default',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'datetime_default',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['schedule_ends_at'] = BaseFieldDefinition::create('datetime')
->setLabel(t('Scheduled End Date'))
->setDescription(t('If not specified, the video will have No End Date.'))
->setDisplayOptions('form', [
'type' => 'datetime_default',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'datetime_default',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['text_tracks'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Text Tracks'))
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
->setDescription(t('Referenced text tracks which belong to the video.'))
->setSetting('target_type', 'brightcove_text_track')
->setDisplayOptions('form', [
'type' => 'brightcove_inline_entity_form_complex',
'settings' => [
'allow_new' => TRUE,
'allow_existing' => FALSE,
],
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'entity_reference_label',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Authored by'))
->setDescription(t('The username of the Brightcove Video author.'))
->setTranslatable(TRUE)
->setDefaultValueCallback('Drupal\\brightcove\\Entity\\BrightcoveVideo::getCurrentUserId')
->setSetting('target_type', 'user')
->setDisplayOptions('form', [
'type' => 'entity_reference_autocomplete',
'weight' => ++$weight,
'settings' => [
'match_operator' => 'CONTAINS',
'size' => '60',
'autocomplete_type' => 'tags',
'placeholder' => '',
],
])
->setDisplayOptions('view', [
'type' => 'author',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time that the Brightcove Video was created.'))
->setTranslatable(TRUE)
->setDisplayOptions('view', [
'label' => 'inline',
'type' => 'timestamp',
'weight' => ++$weight,
])
->setDisplayConfigurable('view', TRUE);
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time that the Brightcove Video was last edited.'))
->setTranslatable(TRUE);
$fields['force_ads'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Force Ads'))
->setDefaultValue(FALSE);
$fields['geo_countries'] = BaseFieldDefinition::create('string')
->setLabel(t('Geo-filtering Country List'))
->setDescription(t('ISO-3166 country code list.'))
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
->setSettings([
'max_length' => 5,
'text_processing' => 0,
])
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['geo_restricted'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Geo-filtering On'))
->setDefaultValue(FALSE)
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
'settings' => [
'display_label' => TRUE,
],
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['geo_exclude_countries'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Geo-filtering Options: Exclude countries'))
->setDescription(t('If enabled, country list is treated as a list of countries excluded from viewing.'))
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
'settings' => [
'display_label' => TRUE,
],
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['logo_alignment'] = BaseFieldDefinition::create('list_string')
->setLabel(t('Logo Overlay Alignment'))
->setCardinality(4)
->setSetting('allowed_values', [
'top_left' => 'Top Left',
'top_right' => 'Top Right',
'bottom_left' => 'Bottom Left',
'bottom_right' => 'Bottom Right',
])
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['logo_image'] = BaseFieldDefinition::create('image')
->setLabel(t('Logo Overlay Image'))
->setSettings([
'file_extensions' => 'png gif',
'file_directory' => '[random:hash:md5]',
'alt_field' => FALSE,
'alt_field_required' => FALSE,
])
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'above',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['logo_tooltip'] = BaseFieldDefinition::create('string')
->setLabel(t('Logo Overlay Tooltip'))
->setSettings([
'max_length' => 128,
'text_processing' => 0,
])
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['logo_url'] = BaseFieldDefinition::create('link')
->setLabel(t('Logo Overlay URL'))
->setSettings([
'max_length' => 128,
'link_type' => LinkItemInterface::LINK_GENERIC,
'title' => DRUPAL_DISABLED,
])
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
'settings' => [
'trim_length' => 128,
'target' => '_blank',
],
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['bumper_video'] = BaseFieldDefinition::create('file')
->setLabel(t('Bumper Video'))
->setDescription(t('FLV or H264 video file to playback before the Video content'))
->setSettings([
'file_extensions' => 'flv',
'file_directory' => '[random:hash:md5]',
])
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['viral'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Viral Distribution'))
->setDescription(t('Enables the get code and blogging menu options for the video'))
->setDefaultValue(FALSE)
->setDisplayOptions('form', [
'type' => 'hidden',
'weight' => ++$weight,
'settings' => [
'display_label' => TRUE,
],
])
->setDisplayOptions('view', [
'type' => 'hidden',
'label' => 'inline',
'weight' => $weight,
])
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
return $fields;
}
public static function getProfileAllowedValues($api_client) {
$profiles = [];
if (!empty($api_client)) {
$cid = 'brightcove:video:profiles:' . $api_client;
if ($cache = \Drupal::cache()
->get($cid)) {
$profiles = $cache->data;
}
else {
$api_client_entity = BrightcoveAPIClient::load($api_client);
try {
if (!is_null($api_client_entity)) {
$client = $api_client_entity
->getClient();
$json = $client
->request('GET', 1, 'ingestion', $api_client_entity
->getAccountId(), '/profiles', NULL);
foreach ($json as $profile) {
$profiles[$profile['id']] = $profile['name'];
}
asort($profiles);
\Drupal::cache()
->set($cid, $profiles);
}
else {
$profiles[] = t('Error: unable to fetch the list');
}
} catch (APIException $exception) {
$profiles[] = t('Error: unable to fetch the list');
watchdog_exception('brightcove', $exception);
}
}
}
return $profiles;
}
public static function profileAllowedValues(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL, &$cacheable = TRUE) {
$profiles = [];
if ($entity instanceof BrightcoveVideo) {
if (empty($entity
->id())) {
$api_clients = \Drupal::entityQuery('brightcove_api_client')
->execute();
foreach ($api_clients as $api_client_id) {
$profiles[$api_client_id] = self::getProfileAllowedValues($api_client_id);
}
}
else {
$profiles = self::getProfileAllowedValues($entity
->getApiClient());
}
}
return $profiles;
}
public static function createOrUpdate(Video $video, EntityStorageInterface $storage, $api_client_id = NULL) {
$existing_video = $storage
->getQuery()
->condition('video_id', $video
->getId())
->execute();
$needs_save = FALSE;
if (!empty($existing_video)) {
$video_entity = self::load(reset($existing_video));
if ($video_entity
->getChangedTime() < strtotime($video
->getUpdatedAt())) {
$needs_save = TRUE;
}
}
else {
if (is_null($api_client_id)) {
throw new \Exception(t('To create a new BrightcoveVideo entity, the api_client_id must be given.'));
}
$values = [
'video_id' => $video
->getId(),
'api_client' => [
'target_id' => $api_client_id,
],
'created' => strtotime($video
->getCreatedAt()),
];
$video_entity = self::create($values);
$needs_save = TRUE;
}
if ($needs_save) {
$video_entity
->setChangedTime(strtotime($video
->getUpdatedAt()));
if ($video_entity
->getDescription() != ($description = $video
->getDescription())) {
$video_entity
->setDescription($description);
}
if ($video_entity
->getDuration() != ($duration = $video
->getDuration())) {
$video_entity
->setDuration($duration);
}
if ($video_entity
->getEconomics() != ($economics = $video
->getEconomics())) {
$video_entity
->setEconomics($economics);
}
BrightcoveUtil::saveOrUpdateTags($video_entity, $api_client_id, $video
->getTags());
$images = $video
->getImages();
if (!empty($images[self::IMAGE_TYPE_THUMBNAIL]) && !empty($images[self::IMAGE_TYPE_THUMBNAIL]
->getSrc())) {
$video_entity
->saveImage(self::IMAGE_TYPE_THUMBNAIL, $images[self::IMAGE_TYPE_THUMBNAIL]);
}
else {
$video_entity
->setThumbnail(NULL);
}
if (!empty($images[self::IMAGE_TYPE_POSTER]) && !empty($images[self::IMAGE_TYPE_POSTER]
->getSrc())) {
$video_entity
->saveImage(self::IMAGE_TYPE_POSTER, $images[self::IMAGE_TYPE_POSTER]);
}
else {
$video_entity
->setPoster(NULL);
}
$link = $video
->getLink();
$related_link_field = $video_entity
->getRelatedLink() ?: NULL;
$related_link = [];
if (empty($related_link_field) && !empty($link)) {
$related_link['uri'] = $link
->getUrl();
$related_link['title'] = $link
->getText();
}
elseif (!empty($related_link_field) && !empty($link)) {
if ($related_link_field['uri'] != ($url = $link
->getUrl())) {
$related_link['uri'] = $url;
}
if ($related_link_field['title'] != ($title = $link
->getText())) {
$related_link['title'] = $title;
}
}
else {
$video_entity
->setRelatedLink(NULL);
}
if (!empty($related_link)) {
$video_entity
->setRelatedLink($related_link);
}
if ($video_entity
->getLongDescription() != ($long_description = $video
->getLongDescription())) {
$video_entity
->setLongDescription($long_description);
}
if ($video_entity
->getName() != ($name = $video
->getName())) {
$video_entity
->setName($name);
}
if ($video_entity
->getReferenceId() != ($reference_id = $video
->getReferenceId())) {
$video_entity
->setReferenceId($reference_id);
}
if ($video_entity
->getCustomFieldValues() != ($custom_fields = $video
->getCustomFields())) {
$video_entity
->setCustomFieldValues($custom_fields);
}
$schedule = $video
->getSchedule();
if (!is_null($schedule)) {
if ($video_entity
->getScheduleStartsAt() != ($starts_at = $schedule
->getStartsAt())) {
$video_entity
->setScheduleStartsAt(BrightcoveUtil::convertDate($starts_at));
}
if ($video_entity
->getScheduleEndsAt() != ($ends_at = $schedule
->getEndsAt())) {
$video_entity
->setScheduleEndsAt(BrightcoveUtil::convertDate($ends_at));
}
}
else {
$video_entity
->setScheduleStartsAt(NULL);
$video_entity
->setScheduleEndsAt(NULL);
}
$state = $video
->getState() == self::STATE_ACTIVE ? TRUE : FALSE;
if ($video_entity
->isPublished() != $state) {
$video_entity
->setPublished($state);
}
$video_entity
->save();
}
return $video_entity;
}
}