mirror of
https://github.com/DanielnetoDotCom/YouPHPTube
synced 2025-10-03 09:49:28 +02:00
EPG updates
This commit is contained in:
parent
5d002be4ed
commit
0ba25294f2
24 changed files with 783 additions and 491 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -11,7 +11,6 @@
|
|||
/plugin/AutoShare/
|
||||
/plugin/Backup/
|
||||
/plugin/Blackblaze_B2/
|
||||
/plugin/Bookmark/
|
||||
/plugin/Chat2/
|
||||
/plugin/CountryRedirect/
|
||||
/plugin/CreateUserManager/
|
||||
|
|
|
@ -4,7 +4,7 @@ if (file_exists("../videos/configuration.php")) {
|
|||
exit;
|
||||
}
|
||||
|
||||
$installationVersion = "12.0";
|
||||
$installationVersion = "12.1";
|
||||
|
||||
error_log("Installation: ".__LINE__." ". json_encode($_POST));
|
||||
header('Content-Type: application/json');
|
||||
|
|
|
@ -181,6 +181,7 @@ CREATE TABLE IF NOT EXISTS `videos` (
|
|||
`likes` INT(11) NULL DEFAULT NULL,
|
||||
`dislikes` INT(11) NULL DEFAULT NULL,
|
||||
`users_id_company` INT(11) NULL DEFAULT NULL,
|
||||
`epg_link` VARCHAR(400) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `fk_videos_users1_idx` (`users_id_company` ASC),
|
||||
INDEX `fk_videos_users_idx` (`users_id` ASC),
|
||||
|
@ -197,6 +198,7 @@ CREATE TABLE IF NOT EXISTS `videos` (
|
|||
INDEX `videos_dislikes_index` (`dislikes` ASC),
|
||||
INDEX `fk_videos_live_transmitions_history1_idx` (`live_transmitions_history_id` ASC),
|
||||
INDEX `total_sec_watchinindex` (`total_seconds_watching` ASC),
|
||||
INDEX `index_epg_link` (`epg_link` ASC),
|
||||
FULLTEXT INDEX `index17vname` (`title`),
|
||||
FULLTEXT INDEX `index18vdesc` (`description`),
|
||||
CONSTRAINT `fk_videos_sites1`
|
||||
|
|
|
@ -24,7 +24,7 @@ if (empty($_POST)) {
|
|||
|
||||
useVideoHashOrLogin();
|
||||
if (!User::canUpload()) {
|
||||
$obj->msg = __("Permission denied to receive a file: " . json_encode($_POST));
|
||||
$obj->msg = __("Permission denied to receive a image: " . json_encode($_POST));
|
||||
_error_log("ReceiveImage: " . $obj->msg);
|
||||
die(json_encode($obj));
|
||||
}
|
||||
|
|
|
@ -1620,6 +1620,11 @@ function im_resize($file_src, $file_dest, $wd, $hd, $q = 80) {
|
|||
if (empty($file_dest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(preg_match('/notfound_/', $file_dest)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($file_src)) {
|
||||
_error_log("im_resize: Source not found: {$file_src}");
|
||||
return false;
|
||||
|
|
|
@ -64,6 +64,7 @@ if (!class_exists('Video')) {
|
|||
protected $dislikes;
|
||||
protected $users_id_company;
|
||||
protected $created;
|
||||
protected $epg_link;
|
||||
public static $statusDesc = [
|
||||
'a' => 'Active',
|
||||
'k' => 'Active and Encoding',
|
||||
|
@ -571,7 +572,7 @@ if (!class_exists('Video')) {
|
|||
}
|
||||
}
|
||||
}
|
||||
return [$videoFound, audioFound];
|
||||
return [$videoFound, $audioFound];
|
||||
}
|
||||
|
||||
public function setClean_title($clean_title) {
|
||||
|
@ -4206,10 +4207,10 @@ if (!class_exists('Video')) {
|
|||
$return->posterPortrait = "{$path['url']}{$path['filename']}_portrait.jpg";
|
||||
}
|
||||
|
||||
if(defaultIsLandscape()){
|
||||
$return->default = array('url'=>$return->posterLandscape, 'path'=>$return->posterLandscapePath);
|
||||
}else{
|
||||
$return->default = array('url'=>$return->posterPortrait, 'path'=>$return->posterPortraitPath);
|
||||
if (defaultIsLandscape()) {
|
||||
$return->default = array('url' => $return->posterLandscape, 'path' => $return->posterLandscapePath);
|
||||
} else {
|
||||
$return->default = array('url' => $return->posterPortrait, 'path' => $return->posterPortraitPath);
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
@ -5444,11 +5445,11 @@ if (!class_exists('Video')) {
|
|||
static function getSeoTags($videos_id) {
|
||||
global $advancedCustom, $_getSeoTags;
|
||||
|
||||
if(!isset($_getSeoTags)){
|
||||
if (!isset($_getSeoTags)) {
|
||||
$_getSeoTags = array();
|
||||
}
|
||||
|
||||
if(!empty($_getSeoTags[$videos_id])){
|
||||
if (!empty($_getSeoTags[$videos_id])) {
|
||||
return $_getSeoTags[$videos_id];
|
||||
}
|
||||
|
||||
|
@ -5468,14 +5469,14 @@ if (!class_exists('Video')) {
|
|||
}
|
||||
|
||||
$keywords = strip_tags($advancedCustom->keywords);
|
||||
if(AVideoPlugin::isEnabledByName('VideoTags')){
|
||||
if (AVideoPlugin::isEnabledByName('VideoTags')) {
|
||||
//$keywords .= ", $videos_id";
|
||||
$tags = VideoTags::getArrayFromVideosId($videos_id);
|
||||
if(!empty($tags)){
|
||||
if(!empty($keywords)){
|
||||
if (!empty($tags)) {
|
||||
if (!empty($keywords)) {
|
||||
$keywords .= ', ';
|
||||
}
|
||||
$keywords .= implode(', ',$tags);
|
||||
$keywords .= implode(', ', $tags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5501,35 +5502,95 @@ if (!class_exists('Video')) {
|
|||
|
||||
$head = '';
|
||||
foreach ($meta as $key => $value) {
|
||||
if(empty($value)){
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
$head .= '<meta name="'.$key.'" content='. printJSString($value, true).'>';
|
||||
$head .= '<meta name="' . $key . '" content=' . printJSString($value, true) . '>';
|
||||
}
|
||||
$body = '<div class="SeoTags" itemprop="video" itemscope itemtype="http://schema.org/VideoObject">';
|
||||
foreach ($tags as $key => $value) {
|
||||
if(empty($value)){
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
$body .= "<{$key}>{$value}</{$key}>";
|
||||
}
|
||||
|
||||
foreach ($itemprops as $key => $value) {
|
||||
if(empty($value)){
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
$body .= "<span itemprop=\"{$key}\" content=".printJSString($value, true)."></span>";
|
||||
$body .= "<span itemprop=\"{$key}\" content=" . printJSString($value, true) . "></span>";
|
||||
}
|
||||
$body .= '</div>';
|
||||
$response = array();
|
||||
$response['assets'] = array('tags'=>$tags, 'meta'=>$meta, 'itemprops'=>$itemprops);
|
||||
$response['assets'] = array('tags' => $tags, 'meta' => $meta, 'itemprops' => $itemprops);
|
||||
$response['head'] = $head;
|
||||
$response['body'] = $body;
|
||||
$_getSeoTags[$videos_id] = $response;
|
||||
//var_dump($_getSeoTags);exit;
|
||||
return $_getSeoTags[$videos_id];
|
||||
}
|
||||
|
||||
public function getEpg_link() {
|
||||
return $this->epg_link;
|
||||
}
|
||||
|
||||
public function setEpg_link($epg_link): void {
|
||||
$this->epg_link = $epg_link;
|
||||
}
|
||||
|
||||
static public function getAllActiveEPGs() {
|
||||
global $config;
|
||||
$sql = "SELECT * FROM `videos` WHERE epg_link IS NOT NULL AND epg_link != '';";
|
||||
$res = sqlDAL::readSql($sql);
|
||||
$fullResult2 = sqlDAL::fetchAllAssoc($res);
|
||||
sqlDAL::close($res);
|
||||
|
||||
$rows = [];
|
||||
if ($res !== false) {
|
||||
foreach ($fullResult2 as $row) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
} else {
|
||||
die($sql . '\nError : (' . $global['mysqli']->errno . ') ' . $global['mysqli']->error);
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
static public function getEPG($videos_id) {
|
||||
global $config, $_getEPG;
|
||||
|
||||
if(!isset($_getEPG)){
|
||||
$_getEPG = array();
|
||||
}
|
||||
|
||||
if(!isset($_getEPG[$videos_id])){
|
||||
$sql = "SELECT * FROM `videos` WHERE id = ? AND epg_link IS NOT NULL AND epg_link != ''";
|
||||
$res = sqlDAL::readSql($sql, 'i', array($videos_id));
|
||||
|
||||
$video = sqlDAL::fetchAssoc($res);
|
||||
sqlDAL::close($res);
|
||||
if(empty($video) || !isValidURL($video['epg_link'])){
|
||||
$_getEPG[$videos_id] = false;
|
||||
}else{
|
||||
$_getEPG[$videos_id] = $video['epg_link'];
|
||||
}
|
||||
}
|
||||
return $_getEPG[$videos_id];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static public function getEPGLink($videos_id) {
|
||||
global $global;
|
||||
$epg = self::getEPG($videos_id);
|
||||
if(!empty($epg)){
|
||||
$url = $global['webSiteRootURL'].'plugin/PlayerSkins/epg.php';
|
||||
$url = addQueryStringParameter($url, 'videos_id', $videos_id);
|
||||
return $url;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ if (!empty($_POST['videoLink'])) {
|
|||
$_POST['videoLinkType'] = "linkVideo";
|
||||
}
|
||||
$obj->setVideoLink($_POST['videoLink']);
|
||||
if(empty($_POST['epg_link']) || isValidURL($_POST['epg_link'])){
|
||||
$obj->setEpg_link($_POST['epg_link']);
|
||||
}
|
||||
|
||||
if (in_array($extension, $audioLinks) || in_array($extension, $videoLinks)) {
|
||||
if (in_array($extension, $audioLinks)) {
|
||||
|
|
|
@ -10,8 +10,8 @@ global $global;
|
|||
require_once $global['systemRootPath'] . 'plugin/Plugin.abstract.php';
|
||||
require_once $global['systemRootPath'] . 'plugin/AD_Server/Objects/VastCampaigns.php';
|
||||
|
||||
class AD_Server extends PluginAbstract
|
||||
{
|
||||
class AD_Server extends PluginAbstract {
|
||||
|
||||
public function getTags() {
|
||||
return [
|
||||
PluginTags::$MONETIZATION,
|
||||
|
@ -98,7 +98,7 @@ class AD_Server extends PluginAbstract
|
|||
return $obj;
|
||||
}
|
||||
|
||||
static function addVideoIdIntoCampaignId($videos_id, $vast_campaigns_id){
|
||||
static function addVideoIdIntoCampaignId($videos_id, $vast_campaigns_id) {
|
||||
if (!empty($vast_campaigns_id)) {
|
||||
$vc = new VastCampaigns($vast_campaigns_id);
|
||||
if (!empty($vc->getName())) {
|
||||
|
@ -175,9 +175,6 @@ class AD_Server extends PluginAbstract
|
|||
$css = '<link href="' . getURL('node_modules/videojs-contrib-ads/dist/videojs.ads.css') . '" rel="stylesheet" type="text/css"/>'
|
||||
. '<link href="' . getURL('node_modules/videojs-ima/dist/videojs.ima.css') . '" rel="stylesheet" type="text/css"/>';
|
||||
|
||||
if (!empty($obj->showMarkers)) {
|
||||
$css .= '<link href="' . getCDN() . 'plugin/AD_Server/videojs-markers/videojs.markers.css" rel="stylesheet" type="text/css"/>';
|
||||
}
|
||||
$css .= '<style>.ima-ad-container{z-index:1000 !important;}</style>';
|
||||
return $css;
|
||||
}
|
||||
|
@ -232,44 +229,26 @@ class AD_Server extends PluginAbstract
|
|||
$vmapURL = self::addVMAPS($vmapURL, $vmaps);
|
||||
//var_dump($vmapURL, $vmaps);exit;
|
||||
PlayerSkins::setIMAADTag($vmapURL);
|
||||
$onPlayerReady = "";
|
||||
|
||||
if (!empty($obj->showMarkers)) {
|
||||
$onPlayerReady .= "
|
||||
player.markers({
|
||||
markerStyle: {
|
||||
'width': '5px',
|
||||
'background-color': 'yellow'
|
||||
},
|
||||
markerTip: {
|
||||
display: true,
|
||||
text: function (marker) {
|
||||
return marker.text;
|
||||
}
|
||||
},
|
||||
markers: [";
|
||||
$rows = array();
|
||||
foreach ($vmaps as $value) {
|
||||
$vastCampaingVideos = new VastCampaignsVideos($value['VAST']['campaing']);
|
||||
$video = new Video("", "", $vastCampaingVideos->getVideos_id());
|
||||
if (!empty($video_length) && $value['timeOffsetSeconds'] >= $video_length) {
|
||||
$value['timeOffsetSeconds'] = $video_length - 5;
|
||||
}
|
||||
|
||||
$onPlayerReady .= "{time: {$value['timeOffsetSeconds']}, text: \"" . addcslashes($video->getTitle(), '"') . "\"},";
|
||||
$rows[] = array('timeInSeconds' => $value['timeOffsetSeconds'], 'name' => $video->getTitle());
|
||||
}
|
||||
$onPlayerReady .= "]});";
|
||||
|
||||
PlayerSkins::createMarker($rows);
|
||||
}
|
||||
|
||||
|
||||
PlayerSkins::getStartPlayerJS($onPlayerReady);
|
||||
$js = '';
|
||||
$js .= '<script src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>';
|
||||
$js .= '<script src="' . getURL('node_modules/videojs-contrib-ads/dist/videojs.ads.min.js') . '" type="text/javascript"></script>';
|
||||
$js .= '<script src="' . getURL('node_modules/videojs-ima/dist/videojs.ima.min.js') . '" type="text/javascript"></script>';
|
||||
|
||||
if (!empty($obj->showMarkers)) {
|
||||
$js .= '<script src="' . getURL('plugin/AD_Server/videojs-markers/videojs-markers.js') . '"></script>';
|
||||
}
|
||||
return $js;
|
||||
}
|
||||
|
||||
|
@ -413,21 +392,22 @@ class AD_Server extends PluginAbstract
|
|||
}
|
||||
|
||||
public function onNewVideo($videos_id) {
|
||||
if(!empty($_REQUEST['return_vars'])){
|
||||
if (!empty($_REQUEST['return_vars'])) {
|
||||
$json = json_decode($_REQUEST['return_vars']);
|
||||
if(!empty($json) && !empty($json->callback)){
|
||||
if (!empty($json) && !empty($json->callback)) {
|
||||
$callback = json_decode(base64_decode($json->callback));
|
||||
if(!empty($callback) && !empty($callback->vast_campaigns_id)){
|
||||
if (!empty($callback) && !empty($callback->vast_campaigns_id)) {
|
||||
return self::addVideoIdIntoCampaignId($videos_id, $callback->vast_campaigns_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class VMAP
|
||||
{
|
||||
class VMAP {
|
||||
|
||||
public $timeOffset;
|
||||
public $timeOffsetSeconds;
|
||||
public $VAST;
|
||||
|
@ -468,10 +448,11 @@ class VMAP
|
|||
$secs = floor($seconds % 60);
|
||||
return sprintf('%02d:%02d:%02d.000', $hours, $mins, $secs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class VAST
|
||||
{
|
||||
class VAST {
|
||||
|
||||
public $id;
|
||||
public $campaing;
|
||||
|
||||
|
@ -484,4 +465,5 @@ class VAST
|
|||
$this->campaing = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,39 +7,7 @@
|
|||
var options = {id: 'mainVideo', adTagUrl: '<?php echo $global['webSiteRootURL'] ?>plugin/AD_Server/VMAP.php?video_length=<?php echo $video_length ?>&vmap_id=<?php echo $vmap_id ?>&random=<?php echo uniqid(); ?>'};
|
||||
player.ima(options);
|
||||
$(document).ready(function () {
|
||||
<?php
|
||||
if (!empty($obj->showMarkers)) {
|
||||
?>
|
||||
$.getScript("<?php echo $global['webSiteRootURL'] ?>plugin/AD_Server/videojs-markers/videojs-markers.js", function (data, textStatus, jqxhr) {
|
||||
|
||||
if (typeof player == 'undefined') {
|
||||
player = videojs('mainVideo'<?php echo PlayerSkins::getDataSetup(); ?>);
|
||||
}
|
||||
player.markers({
|
||||
markerStyle: {
|
||||
'width': '5px',
|
||||
'background-color': 'yellow'
|
||||
},
|
||||
markerTip: {
|
||||
display: true,
|
||||
text: function (marker) {
|
||||
return marker.text;
|
||||
}
|
||||
},
|
||||
markers: [
|
||||
<?php
|
||||
foreach ($vmaps as $value) {
|
||||
$vastCampaingVideos = new VastCampaignsVideos($value->VAST->campaing);
|
||||
$video = new Video("", "", $vastCampaingVideos->getVideos_id()); ?>
|
||||
{time: <?php echo $value->timeOffsetSeconds; ?>, text: "<?php echo addcslashes($video->getTitle(), '"'); ?>"},
|
||||
<?php
|
||||
} ?>
|
||||
]
|
||||
});
|
||||
});
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
// Remove controls from the player on iPad to stop native controls from stealing
|
||||
// our click
|
||||
var contentPlayer = document.getElementById('content_video_html5_api');
|
||||
|
@ -65,3 +33,16 @@ if (!empty($obj->showMarkers)) {
|
|||
}, 100);
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
if (!empty($obj->showMarkers)) {
|
||||
|
||||
$rows = array();
|
||||
foreach ($vmaps as $value) {
|
||||
$vastCampaingVideos = new VastCampaignsVideos($value->VAST->campaing);
|
||||
$video = new Video("", "", $vastCampaingVideos->getVideos_id());
|
||||
$rows[] = array('timeInSeconds'=>$value->timeOffsetSeconds,'name'=>$video->getTitle());
|
||||
}
|
||||
|
||||
PlayerSkins::createMarker($rows);
|
||||
}
|
||||
?>
|
|
@ -24,16 +24,6 @@ class Bookmark extends PluginAbstract {
|
|||
return file_get_contents($filename);
|
||||
}
|
||||
|
||||
|
||||
public function getHeadCode() {
|
||||
if(empty($_GET['videoName'])){
|
||||
return false;
|
||||
}
|
||||
global $global;
|
||||
$css = '<link href="' .getCDN() . 'plugin/AD_Server/videojs-markers/videojs.markers.css" rel="stylesheet" type="text/css"/>';
|
||||
return $css;
|
||||
}
|
||||
|
||||
public function getFooterCode() {
|
||||
if(empty($_GET['videoName'])){
|
||||
return false;
|
||||
|
|
|
@ -1,30 +1,3 @@
|
|||
<script src="<?php echo getCDN() ?>plugin/AD_Server/videojs-markers/videojs-markers.js" type="text/javascript"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
if (typeof player == 'undefined') {
|
||||
player = videojs('mainVideo'<?php echo PlayerSkins::getDataSetup(); ?>);
|
||||
}
|
||||
player.markers({
|
||||
markerStyle: {
|
||||
'width': '10px',
|
||||
'background-color': 'yellow'
|
||||
},
|
||||
markerTip: {
|
||||
display: true,
|
||||
text: function (marker) {
|
||||
return marker.text;
|
||||
}
|
||||
},
|
||||
markers: [
|
||||
<?php
|
||||
foreach ($rows as $value) {
|
||||
?>
|
||||
{time: <?php echo $value['timeInSeconds']; ?>, text: "<?php echo addcslashes($value['name'], '"'); ?>"},
|
||||
<?php
|
||||
}
|
||||
PlayerSkins::createMarker($rows);
|
||||
?>
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
|
@ -527,6 +527,7 @@ class Layout extends PluginAbstract {
|
|||
//return $html;
|
||||
//var_dump(self::$tags['script']);exit;
|
||||
if (!empty(self::$tags['tagcss'])) {
|
||||
self::$tags['tagcss'] = self::removeDuplicated(self::$tags['tagcss']);
|
||||
$html = str_replace('</head>', PHP_EOL.implode(PHP_EOL, array_unique(self::$tags['tagcss'])) . '</head>', $html);
|
||||
}
|
||||
//return $html;
|
||||
|
@ -534,6 +535,7 @@ class Layout extends PluginAbstract {
|
|||
$html = str_replace('</head>', '<style>' . PHP_EOL.implode(PHP_EOL, array_unique(self::$tags['style'])) . '</style></head>', $html);
|
||||
}
|
||||
if (!empty(self::$tags['tagscript'])) {
|
||||
self::$tags['tagscript'] = self::removeDuplicated(self::$tags['tagscript']);
|
||||
usort(self::$tags['tagscript'], "_sortJS");
|
||||
$html = str_replace('</body>', PHP_EOL.implode(PHP_EOL, array_unique(self::$tags['tagscript'])) . '</body>', $html);
|
||||
}
|
||||
|
@ -682,6 +684,31 @@ class Layout extends PluginAbstract {
|
|||
echo $html;
|
||||
}
|
||||
|
||||
static private function removeDuplicated($list) {
|
||||
$cleanList = array();
|
||||
$srcList = array();
|
||||
foreach ($list as $key => $value) {
|
||||
preg_match('/<script.+src=["\']([^"\']+)["\']/i', $value, $matches);
|
||||
if(!empty($matches[1])){
|
||||
if(!in_array($matches[1], $srcList)){
|
||||
$cleanList[] = $value;
|
||||
$srcList[] = $matches[1];
|
||||
}
|
||||
}else{
|
||||
preg_match('/<link.+href=["\']([^"\']+)["\']/i', $value, $matches);
|
||||
if(!empty($matches[1])){
|
||||
if(!in_array($matches[1], $srcList)){
|
||||
$cleanList[] = $value;
|
||||
$srcList[] = $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//var_dump($srcList);exit;
|
||||
return $cleanList;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function _sortJS($a, $b){
|
||||
|
|
|
@ -1,343 +0,0 @@
|
|||
<?php
|
||||
require_once '../../videos/configuration.php';
|
||||
|
||||
require_once $global['systemRootPath'] . 'objects/EpgParser.php';
|
||||
|
||||
$epgs = array();
|
||||
|
||||
$epgs[] = 'https://dy9x7so5g8z3m.cloudfront.net/xmltv/19647868?scheduleId=188';
|
||||
$epgs[] = 'https://app2.evrideo.com/api/reports/epg?channelUid=8808fff1-2262-4c92-8cf4-359adbb692ca&durationHours=96&outputType=xmlTv2&minDurationSecs=300&encodingCodePage=65001&wrapTextInCDATA=false';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/a+_cinema_15.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/americana_television_72.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/blk_cinema_network_256.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/balle_balle_227.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/box_cinema_254.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/box_playlist_63.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/britbash_147.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/christian_life_124.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/cinema_india_257.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/comedy_classics_80.xml';
|
||||
$epgs[] = 'https://sotalcloud.blob.core.windows.net/publicstorage/xmltv/cowboy_classics_58.xml';
|
||||
|
||||
$fontSize = 18;
|
||||
$timeLineElementMinutes = 30;
|
||||
$timeLineElementSize = 150;
|
||||
$paddingSize = 10;
|
||||
$minimumWidth = 10;
|
||||
|
||||
$minuteSize = $timeLineElementSize / $timeLineElementMinutes;
|
||||
$secondSize = $minuteSize / 60;
|
||||
|
||||
$cacheName = 'epg';
|
||||
|
||||
$epgData = ObjectYPT::getCache($cacheName, 3600); // 1 hour
|
||||
|
||||
$channelsList = array();
|
||||
if (empty($epgData)) {
|
||||
foreach ($epgs as $epg) {
|
||||
//var_dump($epg, $_channels);exit;
|
||||
$Parser = new \buibr\xmlepg\EpgParser();
|
||||
$Parser->setURL($epg);
|
||||
$Parser->temp_dir = getCacheDir();
|
||||
try {
|
||||
$Parser->parseURL();
|
||||
$epgData = $Parser->getEpgdata();
|
||||
$channels = $Parser->getChannels();
|
||||
|
||||
//$Parser->setTargetTimeZone('Europe/Skopje');
|
||||
// $Parser->setChannelfilter('prosiebenmaxx.de'); //optional
|
||||
// $Parser->setIgnoreDescr('Keine Details verfügbar.'); //optional
|
||||
foreach ($channels as $key => $value) {
|
||||
$channels[$key]['epgData'] = array();
|
||||
foreach ($epgData as $key2 => $program) {
|
||||
if ($program['channel'] != $value['id']) {
|
||||
continue;
|
||||
}
|
||||
$minutes = getDurationInMinutes(date('Y-d-m 00:00:00'), $program['stop']);
|
||||
if ($minutes > 0) {
|
||||
$channels[$key]['epgData'][] = $program;
|
||||
setMinDate($program['start']);
|
||||
setMaxDate($program['stop']);
|
||||
}
|
||||
unset($epgData[$key2]);
|
||||
}
|
||||
usort($channels[$key]['epgData'], "cmpPrograms");
|
||||
$channelsList[] = $channels[$key];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new \RuntimeException($e);
|
||||
}
|
||||
}
|
||||
usort($channelsList, "cmpChannels");
|
||||
|
||||
$_channels = $channelsList;
|
||||
$_channelsMinDate = $minDate;
|
||||
$_channelsMaxDate = $maxDate;
|
||||
$epgData = new stdClass();
|
||||
$epgData->channels = $_channels;
|
||||
$epgData->channelsMinDate = $_channelsMinDate;
|
||||
$epgData->channelsMaxDate = $_channelsMaxDate;
|
||||
|
||||
//var_dump($epgData);exit;
|
||||
ObjectYPT::setCache($cacheName, $epgData);
|
||||
}
|
||||
//var_dump($epgData);exit;
|
||||
//var_dump($channelsList);exit;
|
||||
function cmpPrograms($a, $b) {
|
||||
$AStartTime = strtotime($a['start']);
|
||||
$BStartTime = strtotime($b['start']);
|
||||
if ($AStartTime == $BStartTime) {
|
||||
return 0;
|
||||
}
|
||||
return ($AStartTime < $BStartTime) ? -1 : 1;
|
||||
}
|
||||
|
||||
function cmpChannels($a, $b) {
|
||||
return strcasecmp($a['display-name'], $b['display-name']);
|
||||
}
|
||||
|
||||
function getDurationInMinutes($start, $stop) {
|
||||
$timeStart = strtotime($start);
|
||||
$timeStop = strtotime($stop);
|
||||
//var_dump(date('Y-m-d H:i:s',$timeStart), date('Y-m-d H:i:s',$timeStop));
|
||||
$seconds = $timeStop - $timeStart;
|
||||
|
||||
$minutes = intval($seconds / 60);
|
||||
return $minutes;
|
||||
}
|
||||
|
||||
function setMaxDate($date) {
|
||||
global $maxDate;
|
||||
|
||||
if (empty($maxDate)) {
|
||||
$maxDate = 0;
|
||||
}
|
||||
|
||||
$newDate = strtotime($date);
|
||||
if ($newDate > $maxDate) {
|
||||
$maxDate = $newDate;
|
||||
}
|
||||
}
|
||||
|
||||
function setMinDate($date) {
|
||||
global $minDate;
|
||||
|
||||
if (empty($minDate)) {
|
||||
$minDate = strtotime('+30 days');
|
||||
}
|
||||
|
||||
$newDate = strtotime($date);
|
||||
if ($newDate < $minDate) {
|
||||
$minDate = $newDate;
|
||||
}
|
||||
}
|
||||
|
||||
function createEPG($channel) {
|
||||
global $minuteSize, $Date;
|
||||
$channel = object_to_array($channel);
|
||||
$displayname = $channel['display-name'];
|
||||
$channelId = $channel['id'];
|
||||
$firstProgram = $channel['epgData'][0];
|
||||
?>
|
||||
<div class="programs">
|
||||
<div class="header">
|
||||
<?php echo $displayname; ?>
|
||||
</div>
|
||||
<div class="list">
|
||||
<?php
|
||||
foreach ($channel['epgData'] as $key => $program) {
|
||||
$minutesSinceZeroTime = getDurationInMinutes("{$Date} 00:00:00", $program['start']);
|
||||
if ($minutesSinceZeroTime < 0) {
|
||||
continue;
|
||||
}
|
||||
$minutes = getDurationInMinutes($program['start'], $program['stop']);
|
||||
$left = ($minuteSize * $minutesSinceZeroTime) + $timeLineElementSize;
|
||||
$width = ($minuteSize * $minutes);
|
||||
if ($width <= $minimumWidth) {
|
||||
$text = "<!-- too small $width -->";
|
||||
} else {
|
||||
$startTime = date('m-d H:i', strtotime($program['start']));
|
||||
$stopTime = date('m-d H:i', strtotime($program['stop']));
|
||||
$text = "{$program['title']}<div><small class=\"duration\">{$minutes} Min</small></div>";
|
||||
}
|
||||
|
||||
echo "<div style=\"width: {$width}px; left: {$left}px;\" start=\"{$program['start']}\" stop=\"{$program['stop']}\" minutes=\"{$minutes}\" minutesSinceZeroTime=\"{$minutesSinceZeroTime}\">{$text}</div>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
$Date = date('Y-m-d');
|
||||
|
||||
$minutes = getDurationInMinutes(date('Y-d-m 00:00:00'), date('Y-d-m H:i:s'));
|
||||
$positionNow = ($minuteSize * $minutes) + $timeLineElementSize;
|
||||
|
||||
$bgColors = array('#feceea', '#fef1d2', '#a9fdd8', '#d7f8ff', '#cec5fa');
|
||||
|
||||
//var_dump($minuteSize, $minutes,$positionNow);exit;
|
||||
?><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>EPG</title>
|
||||
|
||||
<link href="<?php echo getURL('view/bootstrap/css/bootstrap.min.css'); ?>" rel="stylesheet" type="text/css"/>
|
||||
<style>
|
||||
body{
|
||||
background-color: #777;
|
||||
font-size: <?php echo $fontSize; ?>px;
|
||||
}
|
||||
div.list > div,
|
||||
div.header{
|
||||
width: <?php echo $timeLineElementSize; ?>px;
|
||||
padding: 5px <?php echo $paddingSize; ?>px;
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
overflow: hidden;
|
||||
height: <?php echo ($fontSize*3)-2 ;?>px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
background-color: #FFF;
|
||||
}
|
||||
div.timeline > div.list > div{
|
||||
border-right: solid #777 1px;
|
||||
}
|
||||
div.header{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
font-weight: bolder;
|
||||
background-color: #FFF;
|
||||
z-index: 10;
|
||||
padding: 0 10px;
|
||||
}
|
||||
div.timeline{
|
||||
z-index: 20;
|
||||
}
|
||||
div.list{
|
||||
margin-left: <?php echo $timeLineElementSize; ?>px;
|
||||
}
|
||||
div.list > div{
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 1.1;
|
||||
}
|
||||
#positionNow{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
background-color: #FF000077;
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
z-index: 5;
|
||||
}
|
||||
.timeline, #programsList, .programs{
|
||||
position: relative;
|
||||
height: <?php echo ($fontSize*3);?>px;
|
||||
margin: 0;
|
||||
}
|
||||
body > div.container-fluid{
|
||||
padding: 0;
|
||||
}
|
||||
.duration{
|
||||
font-size: 0.8em;
|
||||
}
|
||||
<?php
|
||||
foreach ($bgColors as $key => $value) {
|
||||
$n = $key + 1;
|
||||
echo "div.programs > div.list > div:nth-child({$n}n){"
|
||||
. "background-color: {$value}77;"
|
||||
. "color: #FFF;"
|
||||
//. "font-weight: bolder;"
|
||||
. "text-shadow: 1px 1px 0 {$value},"
|
||||
. "2px 0 0 #000,"
|
||||
. "0 2px 0 #000,"
|
||||
. "-2px -2px 0 #000, "
|
||||
. "-2px 0 0 #000, "
|
||||
. "0 -2px 0 #000, "
|
||||
. "-2px -2px 2px #000, "
|
||||
. "2px 2px 2px #000;"
|
||||
. "}";
|
||||
}
|
||||
?>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="timeline">
|
||||
<div class="list">
|
||||
<?php
|
||||
$lastStopDate = $epgData->channelsMaxDate;
|
||||
//var_dump($lastStopDate);exit;
|
||||
$maxDate = 0;
|
||||
$count = 0;
|
||||
$countElements = 0;
|
||||
while ($lastStopDate > $maxDate && $count < 600) {
|
||||
$tomorrowDate = date('Y-m-d', strtotime("+{$count} days"));
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$hour = $i;
|
||||
$amPm = 'AM';
|
||||
if ($i > 12) {
|
||||
$hour = $i - 12;
|
||||
$amPm = 'PM';
|
||||
}
|
||||
$hour = sprintf("%02d", $hour);
|
||||
|
||||
for ($j = 0; $j < 60; $j += $timeLineElementMinutes) {
|
||||
$minutes = sprintf("%02d", $j);
|
||||
$text = "<small>{$tomorrowDate}</small><div>{$hour}:{$minutes} {$amPm}</div>";
|
||||
$left = ($countElements * $timeLineElementSize) + $timeLineElementSize;
|
||||
echo "<div style=\"width: {$timeLineElementSize}px; left: {$left}px;\">{$text}</div>";
|
||||
|
||||
setMaxDate("$tomorrowDate $i:$minutes:00");
|
||||
$countElements++;
|
||||
if ($lastStopDate < $maxDate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($lastStopDate < $maxDate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="programsList">
|
||||
<?php
|
||||
foreach ($epgData->channels as $channel) {
|
||||
createEPG($channel);
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="positionNow" style="left: <?php echo $positionNow; ?>px;"></div>
|
||||
<script src="<?php echo getURL('node_modules/jquery/dist/jquery.min.js'); ?>" type="text/javascript"></script>
|
||||
<script src="<?php echo getURL('view/bootstrap/js/bootstrap.min.js'); ?>" type="text/javascript"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
setInterval(function () {
|
||||
var left = parseFloat($('#positionNow').css("left"));
|
||||
var newLeft = (left +<?php echo $secondSize; ?>);
|
||||
$('#positionNow').css("left", newLeft + 'px');
|
||||
//console.log('positionNow', newLeft);
|
||||
}, 1000);
|
||||
$(window).scroll(function () {
|
||||
$('div.header').css({
|
||||
'left': $(this).scrollLeft()
|
||||
});
|
||||
$('#positionNow, div.timeline').css({
|
||||
'top': $(this).scrollTop()
|
||||
});
|
||||
});
|
||||
setTimeout(function () {
|
||||
$(document).scrollLeft($('#positionNow').position().left -<?php echo $timeLineElementSize + 50; ?>);
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -5,6 +5,8 @@ require_once $global['systemRootPath'] . 'plugin/AVideoPlugin.php';
|
|||
|
||||
class PlayerSkins extends PluginAbstract {
|
||||
|
||||
static public $hasMarks = false;
|
||||
|
||||
public function getTags() {
|
||||
return array(
|
||||
PluginTags::$FREE,
|
||||
|
@ -264,6 +266,10 @@ class PlayerSkins extends PluginAbstract {
|
|||
$css .= "<link href=\"" . getURL('plugin/PlayerSkins/autoplayButton.css') . "\" rel=\"stylesheet\" type=\"text/css\"/>";
|
||||
}
|
||||
}
|
||||
$videos_id = getVideos_id();
|
||||
if (!empty($videos_id) && Video::getEPG($videos_id)) {
|
||||
$css .= "<link href=\"" . getURL('plugin/PlayerSkins/epgButton.css') . "\" rel=\"stylesheet\" type=\"text/css\"/>";
|
||||
}
|
||||
|
||||
$url = urlencode(getSelfURI());
|
||||
$oembed = '<link href="' . getCDN() . 'oembed/?format=json&url=' . $url . '" rel="alternate" type="application/json+oembed" />';
|
||||
|
@ -315,6 +321,10 @@ class PlayerSkins extends PluginAbstract {
|
|||
$js .= "<!-- PlayerSkins empty(\$_REQUEST['hideAutoplaySwitch']) -->";
|
||||
}
|
||||
}
|
||||
$videos_id = getVideos_id();
|
||||
if (!empty($videos_id) && Video::getEPG($videos_id)) {
|
||||
PlayerSkins::getStartPlayerJS(file_get_contents("{$global['systemRootPath']}plugin/PlayerSkins/epgButton.js"));
|
||||
}
|
||||
}
|
||||
if (isAudio()) {
|
||||
$videos_id = getVideos_id();
|
||||
|
@ -333,6 +343,11 @@ class PlayerSkins extends PluginAbstract {
|
|||
include $global['systemRootPath'] . 'plugin/PlayerSkins/mediaSession.php';
|
||||
PlayerSkins::addOnPlayerReady('if(typeof updateMediaSessionMetadata === "function"){updateMediaSessionMetadata();}');
|
||||
|
||||
if (self::$hasMarks) {
|
||||
$js .= '<link href="' . getURL('plugin/AD_Server/videojs-markers/videojs.markers.css') . '" rel="stylesheet" type="text/css"/>';
|
||||
$js .= '<script src="' . getURL('plugin/AD_Server/videojs-markers/videojs-markers.js') . '"></script>';
|
||||
}
|
||||
|
||||
return $js;
|
||||
}
|
||||
|
||||
|
@ -679,5 +694,61 @@ class PlayerSkins extends PluginAbstract {
|
|||
return array($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $markersList array(array('timeInSeconds'=>10,'name'=>'abc'),array('timeInSeconds'=>20,'name'=>'abc20'),array('timeInSeconds'=>25,'name'=>'abc25')....);
|
||||
* @param type $width
|
||||
* @param type $color
|
||||
*/
|
||||
public static function createMarker($markersList, $width = 10, $color = 'yellow') {
|
||||
global $global;
|
||||
|
||||
$bt = debug_backtrace();
|
||||
$file = str_replace($global['systemRootPath'], '', $bt[0]['file']);
|
||||
|
||||
$onPlayerReady .= " /* {$file} */
|
||||
player.markers({markerStyle: {
|
||||
'width': '{$width}px',
|
||||
'background-color': '{$color}'
|
||||
},
|
||||
markerTip: {
|
||||
display: true,
|
||||
text: function (marker) {
|
||||
return marker.text;
|
||||
}
|
||||
},
|
||||
markers: ";
|
||||
$markers = array();
|
||||
$addedSomething = false;
|
||||
foreach ($markersList as $value) {
|
||||
$obj = new stdClass();
|
||||
$obj->time = $value['timeInSeconds'];
|
||||
$obj->text = $value['name'];
|
||||
if (empty($obj->text)) {
|
||||
continue;
|
||||
}
|
||||
$addedSomething = true;
|
||||
$markers[] = $obj;
|
||||
}
|
||||
|
||||
$onPlayerReady .= json_encode($markers);
|
||||
$onPlayerReady .= "});";
|
||||
if ($addedSomething) {
|
||||
self::$hasMarks = true;
|
||||
PlayerSkins::getStartPlayerJS($onPlayerReady);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getWatchActionButton($videos_id) {
|
||||
global $global, $video;
|
||||
include $global['systemRootPath'] . 'plugin/PlayerSkins/actionButton.php';
|
||||
}
|
||||
|
||||
public function getGalleryActionButton($videos_id) {
|
||||
global $global;
|
||||
include $global['systemRootPath'] . 'plugin/PlayerSkins/actionButtonGallery.php';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
11
plugin/PlayerSkins/actionButton.php
Normal file
11
plugin/PlayerSkins/actionButton.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
$link = Video::getEPGLink($videos_id);
|
||||
if (!empty($link)) {
|
||||
?>
|
||||
<button type="button" class="btn btn-default no-outline" onclick="avideoModalIframeFullTransparent('<?php echo $link; ?>');" data-toggle="tooltip" data-placement="bottom" title="<?php echo __("Electronic Programming Guide"); ?>">
|
||||
<i class="fas fa-list-alt"></i>
|
||||
<?php echo __("EPG"); ?>
|
||||
</button>
|
||||
<?php
|
||||
}
|
||||
?>
|
11
plugin/PlayerSkins/actionButtonGallery.php
Normal file
11
plugin/PlayerSkins/actionButtonGallery.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
$link = Video::getEPGLink($videos_id);
|
||||
if (!empty($link)) {
|
||||
?>
|
||||
<button type="button" class="btn label label-default" onclick="avideoModalIframeFullTransparent('<?php echo $link; ?>');" data-toggle="tooltip" title="<?php echo __("Electronic Programming Guide"); ?>">
|
||||
<i class="fas fa-list-alt"></i>
|
||||
<?php echo __("EPG"); ?>
|
||||
</button>
|
||||
<?php
|
||||
}
|
||||
?>
|
443
plugin/PlayerSkins/epg.php
Normal file
443
plugin/PlayerSkins/epg.php
Normal file
|
@ -0,0 +1,443 @@
|
|||
<?php
|
||||
require_once '../../videos/configuration.php';
|
||||
|
||||
require_once $global['systemRootPath'] . 'objects/EpgParser.php';
|
||||
|
||||
$epgs = array();
|
||||
$minDate = strtotime('+1 year');
|
||||
$maxDate = 0;
|
||||
$videos_id = intval(@$_REQUEST['videos_id']);
|
||||
$videos = Video::getAllActiveEPGs();
|
||||
foreach ($videos as $video) {
|
||||
if (!isValidURL($video['epg_link'])) {
|
||||
continue;
|
||||
}
|
||||
$epgs[] = $video;
|
||||
}
|
||||
//var_dump($epgs);exit;
|
||||
$fontSize = 14;
|
||||
$timeLineElementMinutes = 30;
|
||||
$timeLineElementSize = 200;
|
||||
$paddingSize = 10;
|
||||
$minimumWidth = 50;
|
||||
|
||||
$minuteSize = $timeLineElementSize / $timeLineElementMinutes;
|
||||
$secondSize = $minuteSize / 60;
|
||||
|
||||
$cacheName = 'epg';
|
||||
|
||||
$forceRecreate = false;
|
||||
|
||||
$epgData = ObjectYPT::getCache($cacheName, 3600); // 1 hour
|
||||
|
||||
$channelsList = array();
|
||||
if ($forceRecreate || empty($epgData) || empty($epgData->channels)) {
|
||||
_error_log('EPG expired creating again');
|
||||
foreach ($epgs as $epg) {
|
||||
$videos_id = $epg['id'];
|
||||
$programCacheName = 'program_' . md5($epg['epg_link']);
|
||||
$timeout = random_int(21600, 43200); //6 to 12 hours
|
||||
$programData = ObjectYPT::getCache($programCacheName, $timeout);
|
||||
if ($forceRecreate || empty($programData)) {
|
||||
_error_log("EPG program expired creating again videos_id={$videos_id} " . $programCacheName);
|
||||
//var_dump($epg['epg_link']);exit;
|
||||
$Parser = new \buibr\xmlepg\EpgParser();
|
||||
$Parser->setURL($epg['epg_link']);
|
||||
$Parser->temp_dir = getCacheDir();
|
||||
try {
|
||||
$Parser->parseURL();
|
||||
$epgData = $Parser->getEpgdata();
|
||||
$channels = $Parser->getChannels();
|
||||
//var_dump($channels, $epgData);
|
||||
//$Parser->setTargetTimeZone('Europe/Skopje');
|
||||
// $Parser->setChannelfilter('prosiebenmaxx.de'); //optional
|
||||
// $Parser->setIgnoreDescr('Keine Details verfügbar.'); //optional
|
||||
foreach ($channels as $key => $value) {
|
||||
$channels[$key]['epgData'] = array();
|
||||
foreach ($epgData as $key2 => $program) {
|
||||
if ($program['channel'] != $value['id']) {
|
||||
continue;
|
||||
}
|
||||
$minutes = getDurationInMinutes(date('Y-m-d 00:00:00'), $program['stop']);
|
||||
//var_dump(date('Y-m-d 00:00:00'), $program['stop'], $minutes);
|
||||
if ($minutes > 0) {
|
||||
$channels[$key]['epgData'][] = $program;
|
||||
setMinDate($program['start']);
|
||||
setMaxDate($program['stop']);
|
||||
}
|
||||
unset($epgData[$key2]);
|
||||
}
|
||||
//var_dump($channels[$key]);
|
||||
if (!empty($channels[$key])) {
|
||||
usort($channels[$key]['epgData'], "cmpPrograms");
|
||||
$channels[$key]['videos_id'] = $videos_id;
|
||||
$channelsList[] = $channels[$key];
|
||||
//var_dump($channelsList[0]);exit;
|
||||
}
|
||||
}
|
||||
$file = ObjectYPT::setCache($programCacheName, $channelsList);
|
||||
_error_log("EPG program cache created videos_id={$videos_id} " . json_encode($file));
|
||||
} catch (Exception $e) {
|
||||
throw new \RuntimeException($e);
|
||||
}
|
||||
} else {
|
||||
$channelsList = object_to_array($programData);
|
||||
}
|
||||
}
|
||||
usort($channelsList, "cmpChannels");
|
||||
|
||||
$epgData = new stdClass();
|
||||
$epgData->video = $epg;
|
||||
$epgData->channels = $channelsList;
|
||||
$epgData->channelsMinDate = $minDate;
|
||||
$epgData->channelsMaxDate = $maxDate;
|
||||
|
||||
//var_dump($epgData);exit;
|
||||
$file = ObjectYPT::setCache($cacheName, $epgData);
|
||||
_error_log('EPG cache created ' . json_encode($file));
|
||||
} else {
|
||||
$channelsList = $epgData->channels;
|
||||
}
|
||||
|
||||
//var_dump($epgData);exit;
|
||||
//var_dump($channelsList);exit;
|
||||
function cmpPrograms($a, $b) {
|
||||
$AStartTime = strtotime($a['start']);
|
||||
$BStartTime = strtotime($b['start']);
|
||||
if ($AStartTime == $BStartTime) {
|
||||
return 0;
|
||||
}
|
||||
return ($AStartTime < $BStartTime) ? -1 : 1;
|
||||
}
|
||||
|
||||
function cmpChannels($a, $b) {
|
||||
return strcasecmp($a['display-name'], $b['display-name']);
|
||||
}
|
||||
|
||||
function getDurationInMinutes($start, $stop) {
|
||||
$timeStart = strtotime($start);
|
||||
$timeStop = strtotime($stop);
|
||||
//var_dump(date('Y-m-d H:i:s',$timeStart), date('Y-m-d H:i:s',$timeStop));
|
||||
$seconds = $timeStop - $timeStart;
|
||||
|
||||
$minutes = intval($seconds / 60);
|
||||
return $minutes;
|
||||
}
|
||||
|
||||
function setMaxDate($date) {
|
||||
global $maxDate;
|
||||
|
||||
if (empty($maxDate)) {
|
||||
$maxDate = 0;
|
||||
}
|
||||
|
||||
$newDate = strtotime($date);
|
||||
if ($newDate > $maxDate) {
|
||||
$maxDate = $newDate;
|
||||
}
|
||||
}
|
||||
|
||||
function setMinDate($date) {
|
||||
global $minDate;
|
||||
|
||||
if (empty($minDate)) {
|
||||
$minDate = strtotime('+30 days');
|
||||
}
|
||||
|
||||
$newDate = strtotime($date);
|
||||
if ($newDate < $minDate) {
|
||||
$minDate = $newDate;
|
||||
}
|
||||
}
|
||||
|
||||
function createEPG($channel) {
|
||||
global $minuteSize, $Date, $minimumWidth, $videos_id;
|
||||
$channel = object_to_array($channel);
|
||||
$displayname = $channel['display-name'];
|
||||
$channelId = $channel['id'];
|
||||
$this_videos_id = $channel['videos_id'];
|
||||
$firstProgram = $channel['epgData'][0];
|
||||
|
||||
$class = '';
|
||||
if ($this_videos_id == $videos_id) {
|
||||
$class = 'active';
|
||||
}
|
||||
//var_dump($channel);exit;
|
||||
?>
|
||||
<a href="<?php echo Video::getLinkToVideo($this_videos_id); ?>" target="_top">
|
||||
<div class="programs <?php echo $class; ?>" id="video_<?php echo $this_videos_id; ?>" >
|
||||
<div class="header">
|
||||
<?php echo $displayname; ?>
|
||||
</div>
|
||||
<div class="list">
|
||||
<?php
|
||||
$nowTime = time();
|
||||
foreach ($channel['epgData'] as $key => $program) {
|
||||
$minutesSinceZeroTime = getDurationInMinutes("{$Date} 00:00:00", $program['start']);
|
||||
if ($minutesSinceZeroTime < 0) {
|
||||
continue;
|
||||
}
|
||||
$minutes = getDurationInMinutes($program['start'], $program['stop']);
|
||||
$left = ($minuteSize * $minutesSinceZeroTime) + $timeLineElementSize;
|
||||
$width = ($minuteSize * $minutes);
|
||||
$_stopTime = strtotime($program['stop']);
|
||||
$class = '';
|
||||
if ($width <= $minimumWidth) {
|
||||
$text = "<!-- too small $width -->";
|
||||
} else {
|
||||
$startTime = date('m-d H:i', strtotime($program['start']));
|
||||
$stopTime = date('m-d H:i',$_stopTime);
|
||||
$text = "{$program['title']}<div><small class=\"duration\">{$minutes} Min</small></div>";
|
||||
}
|
||||
if($_stopTime<$nowTime){
|
||||
$class = 'finished';
|
||||
}
|
||||
echo "<div style=\"width: {$width}px; left: {$left}px;\" start=\"{$program['start']}\" stop=\"{$program['stop']}\" minutes=\"{$minutes}\" minutesSinceZeroTime=\"{$minutesSinceZeroTime}\" class=\"{$class}\">"
|
||||
. "{$text}"
|
||||
. "</div>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
$Date = date('Y-m-d');
|
||||
|
||||
$minutes = getDurationInMinutes(date('Y-d-m 00:00:00'), date('Y-d-m H:i:s'));
|
||||
$positionNow = ($minuteSize * $minutes) + $timeLineElementSize;
|
||||
|
||||
$bgColors = array('#feceea', '#fef1d2', '#a9fdd8', '#d7f8ff', '#cec5fa');
|
||||
|
||||
//var_dump($minuteSize, $minutes,$positionNow);exit;
|
||||
?><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>EPG</title>
|
||||
|
||||
<link href="<?php echo getURL('view/bootstrap/css/bootstrap.min.css'); ?>" rel="stylesheet" type="text/css"/>
|
||||
<style>
|
||||
body{
|
||||
background-color: #000000AA;
|
||||
font-size: <?php echo $fontSize; ?>px;
|
||||
}
|
||||
div.list > div,
|
||||
div.header{
|
||||
width: <?php echo $timeLineElementSize; ?>px;
|
||||
padding: 5px <?php echo $paddingSize; ?>px;
|
||||
text-align: center;
|
||||
align-content: center;
|
||||
overflow: hidden;
|
||||
height: <?php echo ($fontSize * 3) - 2; ?>px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
background-color: #000000AA;
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
div.timeline > div.list > div{
|
||||
border-right: solid #777 1px;
|
||||
display:grid;
|
||||
}
|
||||
div.header{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
font-weight: bolder;
|
||||
z-index: 10;
|
||||
padding: 0 10px;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
border: solid #CCC 1px;
|
||||
border-width: 0 1pz 1px 0;
|
||||
}
|
||||
div.timeline{
|
||||
z-index: 20;
|
||||
}
|
||||
div.list{
|
||||
margin-left: <?php echo $timeLineElementSize; ?>px;
|
||||
}
|
||||
div.list > div{
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 1.1;
|
||||
}
|
||||
#positionNow{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
background-color: #FF000077;
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
z-index: 5;
|
||||
}
|
||||
.timeline, #programsList, .programs{
|
||||
position: relative;
|
||||
height: <?php echo ($fontSize * 3); ?>px;
|
||||
margin: 0;
|
||||
}
|
||||
body > div.container-fluid{
|
||||
padding: 0;
|
||||
}
|
||||
.duration{
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.programs{
|
||||
opacity: 0.7;
|
||||
}
|
||||
.programs.active, .programs:hover{
|
||||
opacity: 1;
|
||||
}
|
||||
.programs.active .list > div, .programs.active .header{
|
||||
border: 1px solid green;
|
||||
animation: glowBox 1s infinite alternate;
|
||||
}
|
||||
.programs:hover .list > div, .programs:hover .header{
|
||||
border: 1px solid blue;
|
||||
}
|
||||
.glowBox{
|
||||
animation: glowBox 1s infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes glowBox {
|
||||
from {
|
||||
color: #DFD;
|
||||
box-shadow:
|
||||
0 0 1px #050,
|
||||
0 0 2px #070,
|
||||
0 0 3px #670,
|
||||
0 0 4px #670;
|
||||
}
|
||||
to {
|
||||
color: #FFF;
|
||||
box-shadow:
|
||||
0 0 2px #020,
|
||||
0 0 5px #090,
|
||||
0 0 10px #0F0,
|
||||
0 0 15px #BF0,
|
||||
0 0 20px #B6FF00;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
foreach ($bgColors as $key => $value) {
|
||||
$n = $key + 1;
|
||||
echo "div.programs > div.list > div:nth-child({$n}n){"
|
||||
. "background-color: {$value}77;"
|
||||
. "color: #FFF;"
|
||||
//. "font-weight: bolder;"
|
||||
. "text-shadow: 1px 1px 5px {$value},"
|
||||
. "2px 0 5px #000,"
|
||||
. "0 2px 5px #000,"
|
||||
. "-2px -2px 5px #000, "
|
||||
. "-2px 0 5px #000, "
|
||||
. "0 -2px 5px #000, "
|
||||
. "-2px -2px 5px #000, "
|
||||
. "2px 2px 5px #000;"
|
||||
. "}";
|
||||
}
|
||||
?>
|
||||
.finished{
|
||||
opacity: 0.4;
|
||||
background-color: #00000077 !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="timeline">
|
||||
<div class="list">
|
||||
<?php
|
||||
$lastStopDate = $epgData->channelsMaxDate;
|
||||
//var_dump($lastStopDate);exit;
|
||||
$maxDate = 0;
|
||||
$count = 0;
|
||||
$countElements = 0;
|
||||
while ($lastStopDate > $maxDate && $count < 600) {
|
||||
$tomorrowDate = date('Y-m-d', strtotime("+{$count} days"));
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$hour = $i;
|
||||
$amPm = 'AM';
|
||||
if ($i > 12) {
|
||||
$hour = $i - 12;
|
||||
$amPm = 'PM';
|
||||
}
|
||||
$hour = sprintf("%02d", $hour);
|
||||
|
||||
for ($j = 0; $j < 60; $j += $timeLineElementMinutes) {
|
||||
$minutes = sprintf("%02d", $j);
|
||||
if(empty($count)){
|
||||
$text = "<div>{$hour}:{$minutes} {$amPm}</div>";
|
||||
}else{
|
||||
$text = "<small>{$tomorrowDate}</small><div>{$hour}:{$minutes} {$amPm}</div>";
|
||||
}
|
||||
$left = ($countElements * $timeLineElementSize) + $timeLineElementSize;
|
||||
echo "<div style=\"width: {$timeLineElementSize}px; left: {$left}px;\">{$text}</div>";
|
||||
|
||||
setMaxDate("$tomorrowDate $i:$minutes:00");
|
||||
$countElements++;
|
||||
if ($lastStopDate < $maxDate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($lastStopDate < $maxDate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="programsList">
|
||||
<?php
|
||||
foreach ($epgData->channels as $channel) {
|
||||
createEPG($channel);
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="positionNow" style="left: <?php echo $positionNow; ?>px;"></div>
|
||||
<script src="<?php echo getURL('node_modules/jquery/dist/jquery.min.js'); ?>" type="text/javascript"></script>
|
||||
<script src="<?php echo getURL('view/bootstrap/js/bootstrap.min.js'); ?>" type="text/javascript"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
setPositionNow();
|
||||
setInterval(function () {
|
||||
setPositionNow();
|
||||
}, 1000);
|
||||
$(window).scroll(function () {
|
||||
$('div.header').css({
|
||||
'left': $(this).scrollLeft()
|
||||
});
|
||||
$('#positionNow, div.timeline').css({
|
||||
'top': $(this).scrollTop()
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
setTimeout(function () {
|
||||
//$(document).scrollLeft($('#positionNow').position().left -<?php echo $timeLineElementSize + 50; ?>);
|
||||
$('html, body').animate({
|
||||
scrollLeft: ($('#positionNow').position().left -<?php echo $timeLineElementSize + 50; ?>),
|
||||
<?php
|
||||
if (!empty($videos_id)) {
|
||||
?>
|
||||
scrollTop: (($("#video_<?php echo $videos_id; ?>").offset().top) - 100)
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
}, 1000);
|
||||
}, 200);
|
||||
|
||||
});
|
||||
|
||||
function setPositionNow(){
|
||||
var left = parseFloat($('#positionNow').css("left"));
|
||||
var newLeft = (left +<?php echo $secondSize; ?>);
|
||||
$('#positionNow').css("left", newLeft + 'px');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
14
plugin/PlayerSkins/epgButton.css
Normal file
14
plugin/PlayerSkins/epgButton.css
Normal file
|
@ -0,0 +1,14 @@
|
|||
.EPG-button{
|
||||
outline: none;
|
||||
}
|
||||
.EPG-button:before {
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
text-rendering: auto;
|
||||
content: "\f022";
|
||||
font-size: 1.2em;
|
||||
line-height: 1.0em;
|
||||
font-family: "Font Awesome\ 5 Free";
|
||||
font-weight: 900;
|
||||
}
|
20
plugin/PlayerSkins/epgButton.js
Normal file
20
plugin/PlayerSkins/epgButton.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
var Button = videojs.getComponent('Button');
|
||||
|
||||
var EPGButton = videojs.extend(Button, {
|
||||
//constructor: function(player, options) {
|
||||
constructor: function () {
|
||||
Button.apply(this, arguments);
|
||||
this.addClass('EPG-button');
|
||||
this.controlText("EPG");
|
||||
setTimeout(function(){avideoTooltip(".EPG-button","EPG");},1000);
|
||||
},
|
||||
handleClick: function () {
|
||||
var url = webSiteRootURL+'plugin/PlayerSkins/epg.php';
|
||||
url = addQueryStringParameter(url, 'videos_id', mediaId);
|
||||
console.log('epg clicked');
|
||||
avideoModalIframeFullTransparent(url);
|
||||
}
|
||||
});
|
||||
|
||||
videojs.registerComponent('EPGButton', EPGButton);
|
||||
player.getChild('controlBar').addChild('EPGButton', {}, getPlayerButtonIndex('fullscreenToggle') - 1);
|
13
updatedb/updateDb.v12.1.sql
Normal file
13
updatedb/updateDb.v12.1.sql
Normal file
|
@ -0,0 +1,13 @@
|
|||
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
|
||||
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
|
||||
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
|
||||
|
||||
ALTER TABLE `videos`
|
||||
ADD COLUMN `epg_link` VARCHAR(400) NULL DEFAULT NULL,
|
||||
ADD INDEX `index_epg_link` (`epg_link` ASC);
|
||||
|
||||
UPDATE configurations SET version = '12.1', modified = now() WHERE id = 1;
|
||||
|
||||
SET SQL_MODE=@OLD_SQL_MODE;
|
||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
|
@ -1048,7 +1048,8 @@ li.dropdown-submenu > ul > li > a{
|
|||
.swal-modal.swal-modal-iframe-xsmall .swal-content,
|
||||
.swal-modal.swal-modal-iframe-small .swal-content,
|
||||
.swal-modal.swal-modal-iframe-large .swal-content,
|
||||
.swal-modal.swal-modal-iframe-full .swal-content{
|
||||
.swal-modal.swal-modal-iframe-full .swal-content,
|
||||
.swal-modal.swal-modal-iframe-full-transparent .swal-content{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
@ -1056,7 +1057,8 @@ li.dropdown-submenu > ul > li > a{
|
|||
.swal-modal.swal-modal-iframe-xsmall iframe,
|
||||
.swal-modal.swal-modal-iframe-small iframe,
|
||||
.swal-modal.swal-modal-iframe-large iframe,
|
||||
.swal-modal.swal-modal-iframe-full iframe{
|
||||
.swal-modal.swal-modal-iframe-full iframe,
|
||||
.swal-modal.swal-modal-iframe-full-transparent iframe{
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
|
@ -1086,7 +1088,8 @@ li.dropdown-submenu > ul > li > a{
|
|||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
.swal-modal-iframe-full {
|
||||
.swal-modal-iframe-full,
|
||||
.swal-modal-iframe-full-transparent {
|
||||
margin: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -1096,17 +1099,26 @@ li.dropdown-submenu > ul > li > a{
|
|||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
.swal-modal.swal-modal-iframe-full iframe{
|
||||
.swal-modal.swal-modal-iframe-full iframe,
|
||||
.swal-modal.swal-modal-iframe-full-transparent iframe{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.swal-modal-iframe-full #avideoModalIframeDiv{
|
||||
.swal-modal-iframe-full-transparent iframe,
|
||||
.swal-modal-iframe-full-transparent .swal-content,
|
||||
.swal-modal-iframe-full-transparent{
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.swal-modal-iframe-full #avideoModalIframeDiv,
|
||||
.swal-modal-iframe-full-transparent #avideoModalIframeDiv{
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.swal-modal.swal-modal-iframe-large .swal-content,
|
||||
.swal-modal.swal-modal-iframe-full .swal-content{
|
||||
.swal-modal.swal-modal-iframe-full .swal-content,
|
||||
.swal-modal-iframe-full-transparent .swal-content{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
@ -1421,6 +1421,10 @@ function avideoModalIframeFullScreen(url) {
|
|||
avideoModalIframeWithClassName(url, 'swal-modal-iframe-full', true);
|
||||
}
|
||||
|
||||
function avideoModalIframeFullTransparent(url) {
|
||||
avideoModalIframeWithClassName(url, 'swal-modal-iframe-full-transparent', false);
|
||||
}
|
||||
|
||||
function avideoModalIframeFullScreenClose() {
|
||||
if (typeof swal === 'function') {
|
||||
$('.swal-overlay iframe').attr('src', 'about:blank');
|
||||
|
@ -1566,7 +1570,7 @@ function avideoModalIframeWithClassName(url, className, updateURL) {
|
|||
clearTimeout(avideoModalIframeWithClassNameTimeout);
|
||||
avideoModalIframeWithClassNameTimeout = setTimeout(function () {
|
||||
if (!$('#avideoModalIframe').contents().find("body").length) {
|
||||
//console.log('avideoModalIframeWithClassName content loaded 5');
|
||||
console.log('avideoModalIframeWithClassName content NOT loaded');
|
||||
// is not loaded
|
||||
url = addGetParam(url, 'avideoIframe', 0);
|
||||
if (isSameDomain(url)) {
|
||||
|
@ -1608,6 +1612,8 @@ function avideoModalIframeIsVisible() {
|
|||
modal = $('.swal-modal-iframe-large');
|
||||
} else if ($('.swal-modal-iframe-full').length) {
|
||||
modal = $('.swal-modal-iframe-full');
|
||||
} else if ($('.swal-modal-iframe-full-transparent').length) {
|
||||
modal = $('.swal-modal-iframe-full-transparent');
|
||||
} else {
|
||||
modal = $('.swal-modal-iframe');
|
||||
}
|
||||
|
|
|
@ -737,6 +737,7 @@ if (empty($advancedCustomUser->userCanNotChangeUserGroup) || Permissions::canAdm
|
|||
isArticle = 0;
|
||||
if ((row.type === 'embed') || (row.type === 'linkVideo') || (row.type === 'linkAudio')) {
|
||||
$('#videoLink').val(row.videoLink);
|
||||
$('#epg_link').val(row.epg_link);
|
||||
$('#videoLinkType').val(row.type);
|
||||
} else {
|
||||
$('#videoLinkContent').slideUp();
|
||||
|
@ -1003,6 +1004,7 @@ echo AVideoPlugin::getManagerVideosAddNew();
|
|||
"trailer1": $('#inputTrailer').val(),
|
||||
"video_password": $('#inputVideoPassword').val(),
|
||||
"videoLink": $('#videoLink').val(),
|
||||
"epg_link": $('#epg_link').val(),
|
||||
"videoLinkType": $('#videoLinkType').val(),
|
||||
"clean_title": $('#inputCleanTitle').val(),
|
||||
<?php
|
||||
|
@ -1157,6 +1159,7 @@ if (empty($advancedCustom->disableHTMLDescription)) {
|
|||
$('#videoIsAdControl, #videoExtraDetails, #videoLinkContent').slideUp();
|
||||
$('#postersImage').slideDown();
|
||||
$('#videoLink').val('');
|
||||
$('#epg_link').val('');
|
||||
$('#videoStartSecond').val('00:00:00');
|
||||
$('#videoLinkType').val("article");
|
||||
<?php
|
||||
|
@ -1407,6 +1410,7 @@ if (empty($advancedCustom->disableHTMLDescription)) {
|
|||
$('#postersImage, #videoIsAdControl, .titles').slideUp();
|
||||
$('#videoLinkContent').slideDown();
|
||||
$('#videoLink').val('');
|
||||
$('#epg_link').val('');
|
||||
$('#videoStartSecond').val('00:00:00');
|
||||
$('#videoLinkType').val("linkVideo");
|
||||
<?php
|
||||
|
|
|
@ -385,11 +385,18 @@
|
|||
|
||||
</div>
|
||||
<div id="videoLinkContent">
|
||||
<label class="control-label" for="videoLink" ><?php echo __("Video Link"); ?></label>
|
||||
<input type="text" id="videoLink" class="form-control" placeholder="<?php echo __("Video Link"); ?> http://www.your-embed-link.com/video" required>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<label class="control-label" for="videoLink" ><?php echo __("Video Link"); ?></label>
|
||||
<input type="text" id="videoLink" class="form-control" placeholder="<?php echo __("Video Link"); ?> http://www.your-embed-link.com/video" required>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="control-label" for="epg_link" ><?php echo __("EMP XML Link"); ?></label>
|
||||
<input type="url" id="epg_link" class="form-control" placeholder="<?php echo __("EMP XML Link"); ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
F
|
||||
<div class="modal-footer">
|
||||
<div class="row">
|
||||
<div class="col-xs-7 col-sm-9">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue