Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560 [2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85 [3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50 [4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13 [5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
| Server IP : 94.177.8.99 / Your IP : 216.73.217.165 Web Server : Apache/2.4.58 (Ubuntu) System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/hopeinstoughton_www/wp-content/plugins/video-archive/ |
Upload File : |
<?php
/*
Plugin Name: Video Archive
Plugin URI: http://hostz.org/
Description: Videos over the last 14 years
Version: 1.0.0
Author: Phil Young
Author URI: http://hostz.org/
License: Whatever
*/
class video_archive_class {
// jsTree 1.0-rc3 has problems with [dicarding] spaces on input fields - with the hotkeys plugin - .bind("keydown", "space", function (e) {
// the latest version, 3.2.1 does not appear to work with our data
const EXHORT = 364;
private $x_poster = NULL;
function __construct() {
add_action('wp_enqueue_scripts', array($this, 'add_css' ));
add_action('admin_enqueue_scripts', array($this, 'add_css' ));
add_shortcode('videoplayer', array($this, '_shortcode_handler' ));
add_shortcode('video_list', array($this, '_shortcode_handler_list' ));
add_shortcode('videoduration', array($this, '_shortcode_handler_total' ));
add_shortcode('currentservice', [$this, '_shortcode_handler_current' ]);
add_shortcode('memorialservice', [$this, '_shortcode_handler_memorial' ]);
add_action( 'wp_loaded', array($this, 'check_thumbnail') );
add_filter( 'wp_video_shortcode', array($this, '_add_cross_origin'), 10, 5);
add_action( 'wp_ajax_videoarchive', [$this, '__videodetails'] );
add_action( 'wp_ajax_nopriv_videoarchive', [$this, '__videodetails'] );
$this->includedir = ABSPATH . 'file_up/inc';
$this->DATA = NULL;
}
// get current sunday service, but if missing locate previous sunday
static
public function getLastSundayService($thumb = FALSE) {
// if today is not a sunday, get last sunday
$dow = date('w') + 0;
$sunday = time();
if ($dow > 0) $sunday -= $dow * 86400;
$limit = 4;
do {
// do we have sunday stuff?
$date = date('Y.m.d', $sunday);
$auth = MediaSource::GenerateServiceAuth($date);
$curl = new WP_Http_Curl;
$args = [
'redirection' => 5,
'user-agent' => '',
'stream' => FALSE,
'filename' => '',
'decompress' => TRUE,
'_redirection' => 5,
];
// from the media site, get the names of the names of the vtt, jpeg and mp4 files
// and return the json for the specified day
// if we have a xml file, but not a json, convert it
// but if it is today, and data missing, return last weeks instead
$uri = 'https://media.hopeinstoughton.org/service-info/' . $auth;
$uri .= '?thumb=' . ($thumb ? 1 : 0);
$response = $curl->request($uri, $args);
if (is_a($response, 'WP_Error')) {
$current = [
'error' => 'Unable to find display content' ,
'media' => [],
];
} else {
$current = json_decode($response['body'], TRUE);
}
$limit--;
$ok = count($current['media'] ?? []);
if (!$ok) $sunday -= 7 * 86400;
if ($limit < 0 && !$ok) {
return FALSE; // nothing found
};
} while (!$ok);
return [
'date' => $date,
'speaker' => $current['speaker'],
'thumb' => 'https://media.hopeinstoughton.org/service/' . $auth . '/' . $date . '.60.jpg',
];
}
function _add_cross_origin( $html, $atts, $video, $post_id, $library ) {
$html = str_replace('<video', '<video crossorigin="anonymous"', $html);
if (strpos($html, 'http://localhost/') !== FALSE) { //
$html = str_replace('http://localhost/', $this->x_poster, $html);
}
return $html;
}
function _loaddata() {
if ($this->DATA === NULL) {
$this->DATA = $this->_getClips();
}
}
function check_thumbnail() {
$cache = $_SERVER['REQUEST_URI'];
if (preg_match('~^/thumbnail/(\d+)[:_-](\d+)$~', $cache, $matches)) {
$name = substr($matches[1], 0, 4) . '.' . substr($matches[1], 4, 2) . '.' . substr($matches[1], 6, 2);
$this->DisplayThumbnail($name . '_' . $matches[2]);
exit;
}
if (preg_match('~^/thumbnail/(\d+)\.(\d+)\.(\d+)[:_-](\d+)$~', $cache, $matches)) {
$name = $matches[1] . '.' . $matches[2] . '.' . $matches[3];
$this->DisplayThumbnail($name . '_' . $matches[4]);
exit;
}
}
function DisplayThumbnail($filename) {
$filename = $this->includedir . '/../media/' . $filename . '.jpg';
if (!file_exists($filename)) {
header('Content-type: text/plain');
echo "Thumbnail not available - $filename\n";
return;
}
header('Content-type: image/jpeg');
readfile($filename);
}
function _shortcode_handler($atts) {
$this->_loaddata();
$output = '';
$filename = isset($atts['file']) ? trim($atts['file']) : '';
$poster = isset($atts['poster']) ? trim($atts['poster']) : '';
$src = isset($atts['src']) ? trim($atts['src']) : '';
$title = isset($atts['title']) ? trim($atts['title']) : '';
$width = isset($atts['width']) ? intval($atts['width']) : 0;
$height = isset($atts['height']) ? intval($atts['height']) : 0;
$order = isset($atts['order']) ? strtolower(trim($atts['order'])) : '';
$cc = empty($atts['cc']) ? '' : $atts['cc'];
if (!$width) $width = 720;
if (!$height) $height = 480;
$this->order = $order; // remember the setting for the video_list
if ($title != '') $output .= '<h3>' . $title . '</h3>';
$xfilename = str_replace(array('/', '.'), '-', $filename);
$date = preg_match('~\d{4}-\d{2}-\d{2}~', $xfilename, $match) ? $match[0] : '';
if ($date != '') {
$dt = strtotime($date);
$date = date('l, F j, Y', $dt);
}
if ($order == 'date') {
$this->PrepareDateOrder();
return $this->display_archive_item($width, $height);
}
if ($order == 'speaker') {
$this->PrepareSpeakerOrder();
return $this->display_archive_item($width, $height);
}
$prefix = (($p = strpos($filename, '/')) !== FALSE) ? substr($filename, 0, $p) : '';
if ($prefix == 'exhort' || $prefix == 'classes' || $prefix == 'current' || $prefix == 'other') {
$base = '/av/' . dirname($filename);
} else {
$base = "https://biblealive.us/video/$prefix"; // this does not exist
}
$filename = rawurlencode(basename($filename));
if ($cc != '') {
$cc = str_replace('*', $base, $cc);
$content = '<track srclang="en" label="English" kind="subtitles" src="' . $cc .'" />';
} else {
$content = '';
}
if ($poster == '') $poster = "$base/{$filename}.jpg";
if ($src == '') $src = "$base/{$filename}.mp4";
$attr = [
'width' => $width,
'height' => $height,
'mp4' => $src,
'poster' => $poster,
];
$output .= wp_video_shortcode($attr, $content);
if ($date != '') $output .= "<p>$date</p>";
return $output;
}
private function __AsSpeaker($item) {
$value = trim($item->ms_lastname . ', ' . $item->ms_firstname);
if (!empty($item->ms_suffix)) $value .= ', ' . $item->ms_suffix;
return $value;
}
function display_archive_item($width, $height) {
if (!empty($_GET['video-id'])) { // this will only accepts items of type 'ex'
$this->CURRENT = $_GET['video-id'];
$mediaitem = media_manager_class::Load($_GET['video-id']);
if (is_object($mediaitem) && $mediaitem->mi_type != 'ex') {
$mediaitem = NULL;
}
} else {
// is this from the new system?
$mediaitem = media_manager_class::Load($this->CURRENT);
}
$active = $this->AsSpeaker($this->CURRENT, 1); // full version - with speaker deets
$thmb = str_replace(':', '-', $active['g']);
$attr = [
'width' => $width,
'height' => $height,
'mp4' => "https://media.hopeinstoughton.org/av/exhort/video/{$active['f']}",
'poster' => "/thumbnail/{$thmb}",
];
if (is_object($mediaitem)) {
$mi_id = $mediaitem->mi_id;
$attr['poster'] = apply_filters('mm_generate_link', '', $mi_id, $mi_id. '.jpg', $mediaitem->present_jpg);
$attr['mp4'] = apply_filters('mm_generate_link', '', $mi_id, $mi_id. '.mp4', $mediaitem->present_mp4);
if ($mediaitem->present_vtt) {
$active['v'] = apply_filters('mm_generate_link', '', $mi_id, $mi_id. '.vtt', $mediaitem->present_vtt);
$active['cc'] = 1;
if (strpos($active['v'], '?') === FALSE) {
$active['v'] .= '?short=1';
} else {
$active['v'] .= '&short=1';
}
}
// $active['s'] is the summary - speaker, date, duration, qrcode
// $active['sh'] is the shareable barcode
}
$content = '';
if ($active['cc']) { // closed captions present
$content = '<track srclang="en" label="English" kind="subtitles" src="' . $active['v'] .'" />';
}
$video = wp_video_shortcode($attr, $content);
return <<<BLOCK
{$video}
<div class="video-table">
<div class="video-row">
<div class="video-column col1">
{$active['s']}
</div>
<div class="video-column col2">
<div class="videoupdate-container">
{$active['sh']}
</div>
</div>
</div>
</div>
<div class="xp-transcript" style="display:none;margin-bottom:30px">
<h3>Transcript</h3>
<span id="transcription"></span>
</div>
BLOCK;
}
function add_css() {
wp_enqueue_style('video_archive', plugins_url('video-archive.css', __FILE__), [], '1.1');
// add .js files
wp_enqueue_script('video_archive_3', plugins_url('video-archive.js', __FILE__), ['jquery'], '1.0.7' );
wp_enqueue_script('video_archive_4', plugins_url('jquery.cookie.js', __FILE__), [], '' );
// wp_enqueue_script('video_archive_5', plugins_url('jquery.hotkeys.js', __FILE__), [], '' );
wp_enqueue_script('video_archive_6', plugins_url('jquery.jstree.js', __FILE__), [], '3.2.1' );
wp_localize_script('video_archive_3',
'video_archive',
array(
'ajaxurl' => admin_url('admin-ajax.php'),
)
);
}
function PrepareDateOrder() {
uasort($this->DATA, [$this, 'descendingsort']);
$this->TREE = [];
$last = -1;
$this->CURRENT = NULL;
foreach($this->DATA as $key => $item) {
list($tyy, $tmm, $tdd) = explode('.', $item['date']);
$yy = intval($tyy, 10); $mm = intval($tmm, 10);
$this->TREE[$yy][$mm][] = $key;
$current = $yy * 12 + $mm;
if ($current > $last) { // make a note of the last speaker
$last = $current;
$this->CURRENT = $key;
}
}
}
function PrepareSpeakerOrder() {
uasort($this->DATA, [$this, 'descendingsort']);
$this->TREE = array();
$last = -1;
$this->CURRENT = NULL;
foreach($this->DATA as $key => $item) {
$item = $this->DATA[$key];
$name = trim($item['n']);
$this->TREE[$name][] = $key;
}
ksort($this->TREE);
// get first one
reset($this->TREE);
$name = key($this->TREE);
$this->CURRENT = $this->TREE[$name][0];
}
function _shortcode_handler_list($atts) {
$this->_loaddata();
$order = $this->order ?? '';
if ($order == '') {
return '';
} elseif ($order == 'date' || $order == 'speaker') {
$ly = ''; $lm = 0;
$active = array('y' => '', 'm' => '', 'f' => '', 's' => '<span id="summary"></span>');
if ($this->order == 'date') {
$treehtml = $this->GenerateTree($active);
} else {
$treehtml = $this->GenerateTree_Speaker($active);
}
$first = '"' . $active['y'] . '", "' . $active['m'] . '"';
$javascript = <<<BLOCK
<script type="text/javascript">
let $ = jQuery.noConflict();
$('#vidnav').jstree({
"types" : {
"types" : {
"default" : {
"select_node" : function(e) {
this.toggle_node(e);
return false;
}
}
}
},
"themes": {
"theme": "default",
"url":"/wp-content/plugins/video-archive/style.css",
},
// the `plugins` array allows you to configure the active plugins on this instance
"plugins" : ["themes","html_data","types","ui","crrm"],
"core" : { "initially_open" : [ $first ], html_titles : true }
});
videoarchive_service();
</script>
BLOCK;
return $treehtml. $javascript;
// "plugins" : ["themes","html_data","types","ui","crrm","hotkeys"],
}
return '(unknown)';
}
function descendingsort($a, $b) {
return strcasecmp($b['date'], $a['date']);
}
function AsSpeaker($entry, $full = 0) {
global $SHAREABLE, $MEDIASEARCH;
$item = $this->DATA[$entry]; // $entry => hash
list($tyy, $tmm, $tdd) = explode('.', $item['date']);
// $event = $item['e'];
$base = rawurlencode($item['base']);
$cc = empty($item['cc']) ? '' : ' ccap';
$dname = htmlspecialchars($item['n']);
$param = "class=\"videoselect$cc\"";
$dentry = isset($item['id']) ? $item['id'] : $entry;
if ($full == 2) {
$dt = strtotime("$tyy-$tmm-$tdd 12:00");
$desc = date('F j, Y', $dt);
return "<li id=\"$dentry\"><a href=\"#\" $param>{$desc}</a></li>";
}
if ($full) {
$first = [];
$first['cc'] = $item['cc'];
$first['f'] = $base . '.mp4';
$first['g'] = $entry;
// $first['v'] = "/av/exhort/vtt/{$base}.vtt";
$first['sh'] = '';
$first['s'] = <<<BLOCK
<span id="summary">Speaker: <b>{$dname}</b><br>
Date: <b>$tmm/$tdd/$tyy</b><br>
Duration: <b>{$item['len']}</b><br>
<span class="bind-service" data-dt="{$item['date']}" data-dt="{$item['date']}" data-tp="{$item['e']}"></span>
</span>
BLOCK;
//Audio: <a href="https://media.hopeinstoughton.org/av/exhort/audio/{$base}.mp3">download mp3</a></span>
if (isset($SHAREABLE) && is_object($SHAREABLE)) {
$node = [
'date' => '',
'e' => 0,
'id' => $item['id'],
];
$first['sh'] = $SHAREABLE->asQRcode($node);
}
if (isset($MEDIASEARCH) && is_object($MEDIASEARCH)) {
$MEDIASEARCH->ActiveHash($entry);
}
return $first;
}
return "<li id=\"{$dentry}\"><a href=\"#\" $param>$tdd. {$item['n']}</a></li>";
}
function GenerateTree(&$first) {
$monthnames = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
$output = '';
foreach($this->TREE as $year => $yeardata) {
$yeartext = '';
$yearcount = 0;
foreach($yeardata as $month => $monthdata) {
$monthtext = '';
$monthcount = 0;
foreach($monthdata as $entry) {
$line = $this->AsSpeaker($entry, 0);
$monthtext .= $line;
$yearcount++; $monthcount++;
}
$temp = $monthnames[$month - 1];
$monthtext = "<li id=\"y$year.$month\" style=\"display:none\"><a href=\"#\">$temp <span>($monthcount)</span></a><ul>" . $monthtext . "</ul></li>";
if ($first['m'] == '') $first['m'] = "y$year.$month";
$yeartext .= $monthtext;
}
$output .= "<li id=\"y$year\"><a href=\"#\">$year <span>($yearcount)</span></a><ul>" . $yeartext . "</ul></li>";
if ($first['y'] == '') $first['y'] = "y$year";
}
return "<div id=\"vidnav\"><ul>{$output}</ul></div>";
}
function GenerateTree_Speaker(&$first) {
$output = '';
foreach($this->TREE as $speaker => $entries) {
$speakertext = '';
foreach($entries as $entry) {
$line = $this->AsSpeaker($entry, 2);
$speakertext .= $line;
}
$count = count($entries);
$dspeaker = htmlspecialchars($speaker);
$m = crc32($speaker);
$output .= "<li id=\"y$m\"><a href=\"#\">$dspeaker <span>($count)</span></a><ul>" . $speakertext . "</ul></li>";
if ($first['y'] == '') $first['y'] = "y$m";
}
return "<div id=\"vidnav\"><ul>{$output}</ul></div>";
}
private function _videodetails_programEntry($program, $type) {
foreach($program as $item) {
if ($item['type'] == $type) return $item;
}
return NULL;
}
static
private function asHMS($duration) {
$hours = floor($duration / 3600);
$duration %= 3600;
$duration = sprintf('%d:%02d:%02d', $hours, floor($duration / 60), $duration % 60);
return $duration;
}
public function __videodetails() {
global $wpdb;
$service = trim($_POST['service'] ?? '');
$id = trim($_POST['id'] ?? '');
$node = [];
if ($service != '') {
$auth = MediaSource::GenerateServiceAuth($service);
$curl = new WP_Http_Curl;
$args = [
'redirection' => 5,
'user-agent' => '',
'stream' => FALSE,
'filename' => '',
'decompress' => TRUE,
'_redirection' => 5,
];
// from the media site, get the names of the names of the vtt, jpeg and mp4 files
// and return the json for the specified day
// if we have a xml file, but not a json, convert it
// but if it is today, and data missing, return last weeks instead
$uri = 'https://media.hopeinstoughton.org/service-info/' . $auth;
$response = $curl->request($uri, $args);
if (is_a($response, 'WP_Error')) {
$node['error'] = 'Unable to find display content';
} else {
$current = json_decode($response['body'], TRUE);
if (isset($current['media'])) {
$media = $current['media'];
$mp4 = $media['mp4'] ?? '';
$program = $current['program'];
$entry = $this->_videodetails_programEntry($program, 30);
if (!is_null($entry)) { // add reading
$node['ref'] = $entry['title'];
$node['ref_start'] = static::asHMS($entry['mark_in']);
}
if ($mp4 == $service . '.mp4') {
$node['link'] = '/members/memorial-service/?date=' . $service;
// add reading link
}
}
$tp = intval($_POST['e'] ?? '0');
if ($tp && isset($current['transcript'][$tp])) {
// add transcription
$node['transcript'] = $current['transcript'][$tp];
}
}
} elseif ($id != '') {
$info = $this->_getClips($id);
reset($info);
$id = key($info);
$node = $info[$id];
$mediaitem = media_manager_class::Load($id);
if (is_object($mediaitem)) {
$mi_id = $mediaitem->mi_id;
$node['poster'] = apply_filters('mm_generate_link', '', $mi_id, $mi_id. '.jpg', $mediaitem->present_jpg);
$node['mp4'] = apply_filters('mm_generate_link', '', $mi_id, $mi_id. '.mp4', $mediaitem->present_mp4);
if ($mediaitem->present_vtt) {
$node['cap'] = apply_filters('mm_generate_link', '', $mi_id, $mi_id. '.vtt', $mediaitem->present_vtt);
$node['cc'] = empty($node['cap']) ? 0 : 1;
if (strpos($node['cap'], '?') === FALSE) {
$node['cap'] .= '?short=1';
} else {
$node['cap'] .= '&short=1';
}
}
$dt = str_replace('.', '', $node['date']);
$node['type'] = $mediaitem->mixe_sequence == $dt ? 60 : 100;
}
// $node['sql'] = $sql;
unset($node['dur']);
}
header('Content-type: application/json');
die(json_encode($node, JSON_UNESCAPED_SLASHES));
}
function _shortcode_handler_total($atts) {
$this->_loaddata();
$totalduration = 0;
foreach($this->DATA as $key => $item) {
$totalduration += $item['dur'];
}
$hours = intval(($totalduration / 60 / 60) * 10) / 10;
return $hours;
}
// display specific service
public function _shortcode_handler_memorial($atts) {
$date = $_GET['date'] ?? '';
if ($date == '') {
// get the last sunday, or today, if it is a sunday
$now = time();
[$yy, $mm, $dd, $dow] = explode(',', date('Y,n,j,w', $now));
} else {
if (strpos($date, '.') === FALSE) {
$now = $date * 86400 + 43200;
} else {
[$yy, $mm, $dd] = explode('.', $date);
$now = mktime(12, 0, 0, intval($mm, 10), intval($dd, 10), $yy);
}
$dow = date('w', $now);
if ($dow) {
echo "<hr style=\"margin-top:60px\"><h4>Invalid Date Specified</h4><hr style=\"margin-bottom:60px\">";
return;
}
}
$now -= $dow * 86400;
$date = date('Y.m.d', $now);
$dow = date('w', $now);
// create an authentication code
$auth = MediaSource::GenerateServiceAuth($date);
$curl = new WP_Http_Curl;
$args = [
'redirection' => 5,
'user-agent' => '',
'stream' => FALSE,
'filename' => '',
'decompress' => TRUE,
'_redirection' => 5,
];
// from the media site, get the names of the names of the vtt, jpeg and mp4 files
// and return the json for the specified day
// if we have a xml file, but not a json, convert it
// but if it is today, and data missing, return last weeks instead
$uri = 'https://media.hopeinstoughton.org/service-info/' . $auth;
$response = $curl->request($uri, $args);
if (is_a($response, 'WP_Error')) {
echo "<p>Unable to display content</p>";
return;
}
// thumbnail and cc timeout = 60s; mp4 = 1.5hr
$current = json_decode($response['body'], TRUE);
// echo '<pre>' . htmlspecialchars(var_export($current, 1)) . '</pre>';
$url = "https://media.hopeinstoughton.org/service/{$auth}/";
$title = date('F j, Y', $current['date']) . ': ' . $current['speaker'];
$current['title'] = $title;
$param = [
'src' => $url . $current['media']['mp4'],
'title' => $title,
'width' => 900,
'height' => 506,
];
$sourcevtt = $current['media']['vtt'] ?? '';
if ($sourcevtt != '') {
$param['cc'] = $url . $sourcevtt;
}
$sourcevtt = $current['media']['jpg'] ?? '';
$this->x_poster = NULL;
if ($sourcevtt != '') {
$param['poster'] = $url . $sourcevtt;
} elseif (isset($current['thumb'])) {
$param['poster'] = 'http://localhost/';
$this->x_poster = 'data:image/jpeg;base64,' . $current['thumb'];
}
$player = $this->_shortcode_handler($param)
. $this->_current_footer_text($current);
echo $player;
}
private function _current_footer_text($current) {
$program = $extras = $player = '';
foreach($current['program'] as $item) {
if (empty($item['category'])) continue;
$line = "<a href=\"#\" class=\"audio-waypoint\" data-ts=\"{$item['mark_in']}\">{$item['title']}</a>";
if ($item['category'] == 'X') {
if (!empty($item['subtitle'])) {
$line .= '<em> — ' . $item['subtitle'] . '</em>';
}
$extras .= '<li class="notag">' . $line . '</li>';
} elseif ($item['category'] != 'P') {
if (!empty($item['subtitle'])) {
$line .= '<em> — ' . $item['subtitle'] . '</em>';
} elseif (!empty($item['first'])) {
$line .= '<em> — "' . $item['first'] . '"</em>';
}
$program .= '<li class="notag">' . $line . '</li>';
}
}
$player .= <<<BLOCK
<h3>Program</h3>
<ul>$program</ul>
BLOCK;
if ($extras != '') {
$player .= <<<BLOCK
<h3>Extras</h3>
<ul>$extras</ul>
BLOCK;
}
return $player;
}
// display current service
public function _shortcode_handler_current($atts) {
$x = static::getLastSundayService();
if ($x !== FALSE) {
$_GET['date'] = $x['date'];
return $this->_shortcode_handler_memorial($atts);
}
return '';
}
private function _getClips($id = NULL) {
global $wpdb;
$num = static::EXHORT;
if (is_null($id)) {
$where = "mi_type=\"ex\" and mixe_event=$num";
} else {
$did = '"' . esc_sql($id) . '"';
$where = "mi_id=$did";
}
$sql = <<<BLOCK
select mixe_item,mi_date,mixe_sequence,
present_vtt,
ms_firstname,ms_lastname,ms_suffix,
max(m.mm_duration) as duration,
max(m.mm_filesize) as filesize,
max(m.mm_framesize) as framesize
from `mm_item_x_event` as x
inner join `mm_item` as i on x.mixe_item = i.mi_id
left join mm_speaker as s on s.ms_id = i.mi_speaker
left join mm_media as m on m.mm_hash = x.mixe_item and m.mm_type="mp4"
where not m.mm_source is NULL and $where
group by x.mixe_item
BLOCK;
$result = [];
$items = $wpdb->get_results($sql);
foreach($items as $item) {
$this_node = $this->_node($item);
$result[$item->mixe_item] = $this_node;
}
return $result;
}
private function _node($item) {
global $SHAREABLE;
$item->x_date = str_replace('-', '.', $item->mi_date);
unset($item->mi_other);
list($yy,$mm,$dd) = explode('.', $item->x_date);
$yy = intval($yy);
$mm = intval($mm, 10);
$dd = intval($dd, 10);
$sequence = $yy * 10000 + $mm * 100 + $dd;
$e = ($item->mixe_sequence == $sequence) ? 60 : 100;
$date = $item->x_date;
$dur = empty($item->duration) ? 0 : $item->duration;
$name = trim($item->ms_firstname . ' ' . $item->ms_lastname);
if (!empty($item->ms_suffix)) {
$name .= ' ' . ucfirst($item->ms_suffix);
}
$node = [
'id' => $item->mixe_item,
'e' => $e,
'date' => $date,
'n' => $this->__AsSpeaker($item),
'cc' => (int) $item->present_vtt ? 1 : 0,
'dim' => empty($item->framesize) ? '1280x720' : $item->framesize,
'dur' => (int) $dur,
'len' => intval($dur / 60) . ':' . sprintf('%02d', ($dur % 60)),
'base' => "{$date} {$name}",
];
// if the Shareable module is loaded, create the shareable hashes
if (isset($SHAREABLE) && is_object($SHAREABLE)) {
$node['hash'] = $SHAREABLE->AddHash($node);
}
//}
return $node;
}
}
new video_archive_class();