public function isBroken() : bool { global $Database; if (isset($this->not_broken_at)) { $nb = strtotime($this->not_broken_at); if ($nb + Time::$IN_SECONDS['hour'] * 2 > time()) { return false; } } $url = VideoProvider::getEmbed($this, VideoProvider::URL_ONLY); if ($this->provider === 'yt') { $url = "http://www.youtube.com/oembed?url={$url}"; } $broken = !CoreUtils::isURLAvailable($url); if (!$broken) { $this->not_broken_at = date('c'); $Database->whereEp($this->season, $this->episode)->where('provider', $this->provider)->where('id', $this->id)->update('episodes__videos', array('not_broken_at' => $this->not_broken_at)); } return $broken; }
/** * Format log entry details * * @param array $MainEntry Main log entry * @param array $data Data to process (sub-log entry) * * @return array */ static function formatEntryDetails($MainEntry, $data) { global $Database, $CGDb; $details = array(); $reftype = $MainEntry['reftype']; switch ($reftype) { case "rolechange": /** @var $target User */ $target = $Database->where('id', $data['target'])->getOne('users'); $details = array(array('Target user', $target->getProfileLink()), array('Old group', Permission::ROLES_ASSOC[$data['oldrole']]), array('New group', Permission::ROLES_ASSOC[$data['newrole']])); break; case "episodes": $details[] = array('Action', self::$ACTIONS[$data['action']]); $details[] = array('Name', (new Episode($data))->formatTitle()); if ($data['season'] === 0) { $details[] = array('Overall', "#{$data['episode']}"); } if (!empty($data['airs'])) { $details[] = array('Air date', Time::tag($data['airs'], Time::TAG_EXTENDED, Time::TAG_STATIC_DYNTIME)); } $details[] = array('Two parts', !empty($data['twoparter'])); break; case "episode_modify": $link = $data['target']; $EpData = Episodes::parseID($data['target']); if (!empty($EpData)) { $Episode = Episodes::getActual($EpData['season'], $EpData['episode'], Episodes::ALLOW_MOVIES); if (!empty($Episode)) { $link = "<a href='" . $Episode->formatURL() . "'>" . $Episode->formatTitle(AS_ARRAY, 'id') . "</a>"; } } $details[] = array('Episode', $link); if (empty($Episode)) { $details[] = array('Still exists', false); } unset($data['entryid'], $data['target']); $newOld = self::_arrangeNewOld($data); if (!empty($newOld['airs'])) { $newOld['airs']['old'] = Time::tag($newOld['airs']['old'], Time::TAG_EXTENDED, Time::TAG_STATIC_DYNTIME); $newOld['airs']['new'] = Time::tag($newOld['airs']['new'], Time::TAG_EXTENDED, Time::TAG_STATIC_DYNTIME); } if (isset($newOld['title']['old']) && isset($newOld['title']['new'])) { $details[] = array('Title', self::charDiff($newOld['title']['old'], $newOld['title']['new'])); unset($newOld['title']); } foreach ($newOld as $thing => $ver) { $details[] = array("Old {$thing}", $ver['old']); $details[] = array("New {$thing}", $ver['new']); } break; case "userfetch": $details[] = array('User', Users::get($data['userid'])->getProfileLink()); break; case "banish": case "un-banish": $details[] = array('User', Users::get($data['target'])->getProfileLink()); $details[] = array('Reason', CoreUtils::escapeHTML($data['reason'])); break; case "post_lock": $Post = $Database->where('id', $data['id'])->getOne("{$data['type']}s"); self::_genericPostInfo($Post, $data, $details); break; case "color_modify": $details[] = array('Appearance', self::_getAppearanceLink($data['ponyid'])); $details[] = array('Reason', CoreUtils::escapeHTML($data['reason'])); break; case "req_delete": $details[] = array('Request ID', $data['id']); $typeNames = array('chr' => 'Character', 'obj' => 'Object', 'bg' => 'Background'); $details[] = array('Description', CoreUtils::escapeHTML($data['label'])); $details[] = array('Type', $typeNames[$data['type']]); $IDstr = "S{$data['season']}E{$data['episode']}"; $details[] = array('Episode', "<a href='/episode/{$IDstr}'>{$IDstr}</a>"); $details[] = array('Posted', Time::tag($data['posted'], Time::TAG_EXTENDED, Time::TAG_STATIC_DYNTIME)); if (!empty($data['requested_by'])) { $details[] = array('Requested by', Users::get($data['requested_by'])->getProfileLink()); } if (!empty($data['reserved_by'])) { $details[] = array('Reserved by', Users::get($data['reserved_by'])->getProfileLink()); } $details[] = array('Finished', !empty($data['deviation_id'])); if (!empty($data['deviation_id'])) { $details[] = array('Deviation', self::_link("http://fav.me/{$data['deviation_id']}")); $details[] = array('Approved', $data['lock']); } break; case "img_update": $Post = $Database->where('id', $data['id'])->getOne("{$data['thing']}s"); $data['type'] = $data['thing']; self::_genericPostInfo($Post, $data, $details); $details[] = array('Old image', "<a href='{$data['oldfullsize']}' target='_blank'>Full size</a><div><img src='{$data['oldpreview']}'></div>"); $details[] = array('New image', "<a href='{$data['newfullsize']}' target='_blank'>Full size</a><div><img src='{$data['newpreview']}'></div>"); break; case "res_overtake": $Post = $Database->where('id', $data['id'])->getOne("{$data['type']}s"); self::_genericPostInfo($Post, $data, $details); $details[] = array('Previous reserver', Users::get($data['reserved_by'])->getProfileLink()); $details[] = array('Previously reserved at', Time::tag($data['reserved_at'], Time::TAG_EXTENDED, Time::TAG_STATIC_DYNTIME)); $diff_text = ''; $diff = Time::difference(strtotime($MainEntry['timestamp']), strtotime($data['reserved_at'])); foreach (array_keys(Time::$IN_SECONDS) as $unit) { if (empty($diff[$unit])) { continue; } $diff_text .= CoreUtils::makePlural($unit, $diff[$unit], PREPEND_NUMBER) . ' '; } $details[] = array('In progress for', rtrim($diff_text)); break; case "appearances": $details[] = array('Action', self::$ACTIONS[$data['action']]); $PonyGuide = empty($data['ishuman']); $details[] = array('Guide', $PonyGuide ? 'Pony' : 'EQG'); $details[] = array('ID', self::_getAppearanceLink($data['id'])); $details[] = array('Label', $data['label']); if (!empty($data['order'])) { $details[] = array('Ordering index', $data['order']); } if (!empty($data['notes'])) { $details[] = array('Notes', '<div>' . nl2br($data['notes']) . '</div>'); } if (!empty($data['cm_favme'])) { $details[] = array('CM Submission', self::_link("http://fav.me/{$data['cm_favme']}")); $details[] = array('CM Orientation', CGUtils::$CM_DIR[$data['cm_dir']]); if (!empty($data['cm_preview'])) { $details[] = array('Custom CM Preview', "<img src='" . CoreUtils::aposEncode($data['cm_preview']) . "'>"); } } if (!empty($data['usetemplate'])) { $details[] = array('Template applied', true); } $details[] = array('Private', !empty($data['private'])); if (!empty($data['added'])) { $details[] = array('Added', Time::tag($data['added'], Time::TAG_EXTENDED, Time::TAG_STATIC_DYNTIME)); } break; case "res_transfer": $Post = $Database->where('id', $data['id'])->getOne("{$data['type']}s"); self::_genericPostInfo($Post, $data, $details); $details[] = array('New reserver', Users::get($data['to'])->getProfileLink()); break; case "cg_modify": $details[] = array('Appearance', self::_getAppearanceLink($data['ponyid'])); $CG = $CGDb->where('groupid', $data['groupid'])->getOne('colorgroups'); if (empty($CG)) { $details[] = array('Color group ID', '#' . $data['groupid']); $details[] = array('Still exists', false); } else { $details[] = array('Group', "{$CG['label']} (#{$data['groupid']})"); } if (isset($data['newlabel'])) { $details[] = array('Label', self::charDiff($data['oldlabel'] ?? '', $data['newlabel'])); } if (isset($data['newcolors'])) { $details[] = array('Colors', self::charDiff($data['oldcolors'] ?? '', $data['newcolors'], 'block')); } break; case "cgs": $details[] = array('Action', self::$ACTIONS[$data['action']]); $details[] = array('Color group ID', '#' . $data['groupid']); $details[] = array('Label', $data['label']); $details[] = array('Appearance', self::_getAppearanceLink($data['ponyid'])); if (isset($data['order'])) { $details[] = array('Ordering index', $data['order']); } break; case "cg_order": $details[] = array('Appearance', self::_getAppearanceLink($data['ponyid'])); $details[] = array('Order', self::charDiff($data['oldgroups'], $data['newgroups'], 'block')); break; case "appearance_modify": $details[] = array('Appearance', self::_getAppearanceLink($data['ponyid'])); $changes = JSON::decode($data['changes']); $newOld = self::_arrangeNewOld($changes); if (isset($newOld['label']['new'])) { $details[] = array('Label', self::charDiff($newOld['label']['old'], $newOld['label']['new'], 'block')); } if (isset($newOld['notes']['new']) || isset($newOld['notes']['old'])) { $details[] = array('Notes', self::charDiff($newOld['notes']['old'] ?? '', $newOld['notes']['new'] ?? '', 'block smaller')); } if (isset($newOld['cm_favme']['old'])) { $details[] = array('Old CM Submission', self::_link('http://fav.me/' . $newOld['cm_favme']['old'])); } else { if (isset($newOld['cm_favme']['new'])) { $details[] = array('Old CM Submission', null); } } if (isset($newOld['cm_favme']['new'])) { $details[] = array('New CM Submission', self::_link('http://fav.me/' . $newOld['cm_favme']['new'])); } else { if (isset($newOld['cm_favme']['old'])) { $details[] = array('New CM Submission', null); } } $olddir = isset($newOld['cm_dir']['old']) ? CGUtils::$CM_DIR[$newOld['cm_dir']['old']] : ''; $newdir = isset($newOld['cm_dir']['new']) ? CGUtils::$CM_DIR[$newOld['cm_dir']['new']] : ''; if ($olddir || $newdir) { $details[] = array('CM Orientation', self::charDiff($olddir, $newdir, 'inline', new FineDiff\Granularity\Paragraph())); } if (isset($newOld['private']['new'])) { $details[] = array('<span class="typcn typcn-lock-' . ($newOld['private']['new'] ? 'closed' : 'open') . '"></span> ' . ($newOld['private']['new'] ? 'Marked private' : 'No longer private'), self::SKIP_VALUE, self::KEYCOLOR_INFO); } if (isset($newOld['cm_preview']['new'])) { $details[] = array('New Custom CM Preview', "<img src='" . CoreUtils::aposEncode($newOld['cm_preview']['new']) . "'>"); } else { if (isset($newOld['cm_preview']['old'])) { $details[] = array('New Custom CM Preview', null); } } break; case "da_namechange": $User = Users::get($data['id'], 'id', 'name'); $newIsCurrent = $User->name === $data['new']; $details[] = array('User', $User->getProfileLink()); if ($newIsCurrent) { $details[] = array('Old name', $data['old']); } else { $details[] = array('Name', Logs::charDiff($data['old'], $data['new'])); } break; case "video_broken": $IDstr = "S{$data['season']}E{$data['episode']}"; $details[] = array('Episode', "<a href='/episode/{$IDstr}'>{$IDstr}</a>"); $url = VideoProvider::getEmbed(new EpisodeVideo(array('provider' => $data['provider'], 'id' => $data['id'])), VideoProvider::URL_ONLY); $details[] = array('Link', "<a href='{$url}'>{$url}</a>"); break; default: $details[] = array('<span class="typcn typcn-warning"></span> Couldn\'t process details', 'No data processor defined for this entry type', self::KEYCOLOR_ERROR); $details[] = array('Raw details', '<pre>' . var_export($data, true) . '</pre>'); break; } return array('details' => $details); }
if (!$Database->insert('episodes__votes', array('season' => $Episode->season, 'episode' => $Episode->episode, 'user' => $currentUser->id, 'vote' => $vote))) { Response::dbError(); } $Episode->updateScore(); Response::done(array('newhtml' => Episodes::getSidebarVoting($Episode))); break; case "videos": Response::done(Episodes::getVideoEmbeds($Episode)); break; case "getvideos": $return = array('twoparter' => $Episode->twoparter, 'vidlinks' => array(), 'fullep' => array(), 'airs' => date('c', strtotime($Episode->airs))); /** @var $Vids EpisodeVideo[] */ $Vids = $Database->whereEp($Episode)->get('episodes__videos'); foreach ($Vids as $part => $vid) { if (!empty($vid->id)) { $return['vidlinks']["{$vid->provider}_{$vid->part}"] = VideoProvider::getEmbed($vid, VideoProvider::URL_ONLY); } if ($vid->fullep) { $return['fullep'][] = $vid->provider; } } Response::done($return); break; case "setvideos": foreach (array('yt', 'dm') as $provider) { for ($part = 1; $part <= ($Episode->twoparter ? 2 : 1); $part++) { $set = null; $PostKey = "{$provider}_{$part}"; if (!empty($_POST[$PostKey])) { $Provider = Episodes::$VIDEO_PROVIDER_NAMES[$provider]; try {
/** * Renders the HTML of the "Watch the Episode" section along with the buttons/links * * @param Episode $Episode * @param bool $wrap * * @return string */ static function getVideosHTML($Episode, bool $wrap = WRAP) : string { global $Database; $HTML = ''; /** @var $Videos EpisodeVideo[] */ $Videos = $Database->whereEp($Episode)->orderBy('provider', 'ASC')->orderBy('part', 'ASC')->get('episodes__videos'); if (!empty($Videos)) { $fullep = $Episode->twoparter ? 'Full episode' : ''; if (count($Videos) === 1 && $Videos[0]->provider === 'yt') { $airtime = strtotime($Episode->airs); $modified = $Videos[0]->modified; if (!empty($modified) && $airtime > strtotime($modified)) { $fullep = 'Livestream'; $Episode = $Episode->addAiringData(); if ($Episode->aired) { $fullep .= ' recording'; } if (!$Episode->twoparter) { $fullep = " ({$fullep})"; } } } $HTML = ($wrap ? "<section class='episode'>" : '') . "<h2>Watch the " . ($Episode->isMovie ? 'Movie' : 'Episode') . "</h2><p class='align-center actions'>"; foreach ($Videos as $v) { $url = VideoProvider::getEmbed($v, VideoProvider::URL_ONLY); $partText = $Episode->twoparter ? !$v->fullep ? " (Part {$v->part})" : " ({$fullep})" : $fullep; $HTML .= "<a class='btn typcn " . self::$PROVIDER_BTN_CLASSES[$v->provider] . "' href='{$url}' target='_blank'>" . self::$VIDEO_PROVIDER_NAMES[$v->provider] . "{$partText}</a>"; } $HTML .= "<button class='green typcn typcn-eye showplayers'>Show on-site player</button><button class='orange typcn typcn-flag reportbroken'>Report broken video</button></p>"; if ($wrap) { $HTML .= '</section>'; } } return $HTML; }