false
);
}
class PresentationEditorPage_Controller extends Page_Controller
{
public static $allowed_actions = array(
'Show',
'SetMainTopic',
'Category',
'Delete',
'Restore',
'Next',
'Previous',
'SearchForm',
'FlagForm',
'CleanTalks',
'CleanSpeakers',
'EmailSpeakers',
'EmailSubmitters',
'SpeakersWithoutEmail' => 'ADMIN',
'TalkStatus' => 'ADMIN',
'SendAdminEmails' => 'ADMIN',
'SendSpeakerEmails' => 'ADMIN',
'SpeakerList' => 'ADMIN',
'AdjustSpeakers' => 'ADMIN',
'SpeakersForSched' => 'ADMIN',
'ScheduleForSched' => 'ADMIN',
'SpeakerCleanup' => 'ADMIN',
'AcceptedSpeakersWithoutEmails' => 'ADMIN',
'AcceptedSpeakersNotContacted' => 'ADMIN',
'AcceptedSpeakersNotConfirmed' => 'ADMIN',
'AcceptedTalksWithoutSpeakers' => 'ADMIN',
'FullSpeakerReport' => 'ADMIN',
'FullTalksReport' => 'ADMIN',
'FullTalksReportSpeakerDetails' => 'ADMIN',
'SendFirstEmail' => 'ADMIN',
'SpeakersWithTalksInSummit' => 'ADMIN',
'SpeakerVerify' => 'ADMIN',
'SpeakersWithUnassignedTalks' => 'ADMIN',
'SpeakerCompanyReport' => 'ADMIN',
'SpeakerSpreadsheetExport' => 'ADMIN',
'ExportTalks' => 'ADMIN',
'SetSpeakerOrgs' => 'ADMIN'
);
function init()
{
if (!Permission::check("ADMIN")) Security::permissionFailure();
parent::init();
}
function Show()
{
// Grab member ID from the URL
$Talk = $this->findTalk();
if ($Talk) {
if ($CategoryID = Session::get('CategoryID')) {
$Talks = $this->PresentationsByCategory($CategoryID);
if ($Talks) $data["Presentations"] = True;
$data["PresentationList"] = $Talks;
} else {
$Talks = $this->PresentationList();
if ($Talks) $data["Presentations"] = True;
$data["PresentationList"] = $Talks;
}
$data["Presentation"] = $Talk;
Session::set('TalkID', $Talk->ID);
//return our $Data to use on the page
return $this->Customise($data);
} else {
//Talk not found
return $this->httpError(404, 'Sorry that talk could not be found');
}
}
function FindTalk()
{
$TalkId = NULL;
// Grab member ID from the URL or the session
if ($this->request->param("ID") != NULL && $this->request->param("Action") == 'Show') {
$TalkId = Convert::raw2sql($this->request->param("ID"));
} elseif (Session::get('TalkID') != NULL) {
$TalkId = Session::get('TalkID');
}
// Check to see if the ID is numeric
if (is_numeric($TalkId)) {
Session::set('TalkID', $TalkId);
return $Talk = Talk::get()->byID($TalkId);
} else {
return $Talk = $this->PresentationList()->first();
}
}
// Find a talk given an id
function PresentationList()
{
return Talk::get()->filter(array('MarkedToDelete' => 0))->sort('PresentationTitle', 'ASC');
}
//Show the details of a talk
function PresentationsByCategory($CategoryID)
{
if ((1 <= $CategoryID) && ($CategoryID <= 10)) {
$Categories = $this->CategoryList();
$CategoryName = $Categories[$CategoryID - 1]['Name'];
$Talks = Talk::get()->filter(array('MainTopic' => $CategoryName, 'MarkedToDelete' => 0))->sort('PresentationTitle', 'ASC');
} elseif ($CategoryID == 'All') {
$Talks = Talk::get()->filter(array('MarkedToDelete' => 0))->sort('PresentationTitle', 'ASC');
} elseif ($CategoryID == 'Deleted') {
$Talks = Talk::get()->filter(array('MarkedToDelete' => 1))->sort('PresentationTitle', 'ASC');
} elseif ($CategoryID == 'None') {
$Talks = Talk::get()->filter(array('MarkedToDelete' => 0))->where('MainTopic IS NULL')->sort('PresentationTitle', 'ASC');
}
return $Talks;
}
function CategoryList()
{
return array(
array('Name' => 'Getting Started', 'Number' => '1'),
array('Name' => 'Operations', 'Number' => '2'),
array('Name' => 'Related OSS Projects', 'Number' => '3'),
array('Name' => 'Workshops', 'Number' => '4'),
array('Name' => 'Apps on OpenStack', 'Number' => '5'),
array('Name' => 'Strategy', 'Number' => '6'),
array('Name' => 'Products & Services', 'Number' => '7'),
array('Name' => 'Techincal Deep Dive', 'Number' => '8'),
array('Name' => 'Community Building', 'Number' => '9'),
array('Name' => 'Growing An OpenStack Business', 'Number' => '10'),
array('Name' => 'General Session', 'Number' => '11')
);
}
function Category()
{
$CategoryID = Convert::raw2sql($this->request->param("ID"));
Session::set('CategoryID', $CategoryID);
$Talks = $this->PresentationsByCategory($CategoryID);
if ($Talks) {
$Talk = $Talks->first();
$data["Presentation"] = $Talk;
Session::set('TalkID', $Talk->ID);
$data["Presentations"] = True;
$data["PresentationList"] = $Talks;
} else {
$data["Presentations"] = FALSE;
$Talk = $this->findTalk();
}
return $this->Customise($data);
}
//Used to list presentations from a specific category
function NumTalksWithNoCategory()
{
return $this->CountCategoryMembers('No Category Assigned');
}
function CountCategoryMembers($Category)
{
if ($Category == 'No Category Assigned') {
$TalksInCategory = Talk::get()->where("MainTopic IS NULL");
} else {
$TalksInCategory = Talk::get()->filter('MainTopic', $Category);
}
if ($TalksInCategory) {
return $TalksInCategory->count();
} else {
return 0;
}
}
function CategoryButtons()
{
$Talk = $this->findTalk();
$items = new ArrayList();
$Categories = $this->CategoryList();
foreach ($Categories as $Category) {
$Category['Count'] = $this->CountCategoryMembers($Category['Name']);
if (stripos($Talk->Topic, $Category['Name']) !== false) $Category['Class'] = 'user-selected';
if (stripos($Talk->MainTopic, $Category['Name']) !== false) $Category['Class'] = 'main-topic';
$items->push(new ArrayData($Category));
}
return $items;
}
// Render category buttons
function SetMainTopic()
{
// Grab IDs from the URL
$TopicID = Convert::raw2sql($this->request->param("OtherID"));
$TalkID = Convert::raw2sql($this->request->param("ID"));
$Categories = $this->CategoryList();
if ((1 <= $TopicID) && ($TopicID <= 11)) {
$CategoryName = $Categories[$TopicID - 1]['Name'];
$Talk = Talk::get()->byID($TalkID);
if ($Talk) {
if ($Talk->MainTopic != $CategoryName) {
$Talk->MainTopic = $CategoryName;
$CategorySelected = SummitCategory::get()->filter('Name', $CategoryName)->first();
if ($CategorySelected) $Talk->SummitCategoryID = $CategorySelected->ID;
$SummitSelectedTalkList = SummitSelectedTalkList::get()->filter('SummitCategoryID', $Talk->SummitCategoryID)->first();
// if a summit talk list doens't exist for this category, create it
if (!$SummitSelectedTalkList) {
$SummitSelectedTalkList = new SummitSelectedTalkList();
$SummitSelectedTalkList->SummitCategoryID = $Talk->SummitCategoryID;
$SummitSelectedTalkList->write();
}
$SelectionsToRemove = SummitSelectedTalk::get()->filter('TalkID', $Talk->ID);
// start reassigning by removing any current selections
if ($SelectionsToRemove) {
foreach ($SelectionsToRemove as $Selection) {
$Selection->delete();
}
// Create a new selection in the new category if needed
$SelectedTalk = new SummitSelectedTalk();
$SelectedTalk->SummitSelectedTalkListID = $SummitSelectedTalkList->ID;
$SelectedTalk->TalkID = $Talk->ID;
$SelectedTalk->MemberID = Member::CurrentUser()->ID;
$SelectedTalk->write();
}
}
$Talk->write();
}
}
$this->redirectBack();
}
function Delete()
{
$TalkID = Convert::raw2sql($this->request->param("ID"));
if (is_numeric($TalkID)) {
$Talk = Talk::get()->byID($TalkID);
$Talk->MarkedToDelete = TRUE;
$Talk->write();
$this->Next();
}
}
function Next()
{
$Talks = $this->TalksForNav('next');
if ($Talks) {
$NextTalk = $Talks->first();
$this->redirect($this->Link() . 'Show/' . $NextTalk->ID);
} else {
// Last talk
$this->redirectBack();
}
}
function TalksForNav($PrevOrNext)
{
if ($PrevOrNext == 'next') $Order = '>';
if ($PrevOrNext == 'prev') $Order = '<';
if ($PrevOrNext == 'next') $Sort = 'ASC';
if ($PrevOrNext == 'prev') $Sort = 'DESC';
// Check to see if we're in a category
// If so, we'll add that to our SQL query to filter the results
$Category = $this->CurrentCategory();
$TalkID = Session::get('TalkID');
$Talk = Talk::get()->byID($TalkID);
$Title = Convert::raw2sql($Talk->PresentationTitle);
if ($Category && $Category != 'All Categories' && $Category != 'No Category Assigned' && $Category != 'Deleted') {
$WhereClause = "PresentationTitle " . $Order . " '" . $Title . "' AND `MainTopic` = '" . $Category . "' AND `MarkedToDelete` = FALSE";
} else {
$WhereClause = "PresentationTitle " . $Order . " '" . $Title . "' AND `MarkedToDelete` = FALSE";
}
if ($Category == 'Deleted') {
$WhereClause = "PresentationTitle " . $Order . " '" . $Title . "' AND `MarkedToDelete` = TRUE";
}
if ($Category == 'No Category Assigned') {
$WhereClause = "PresentationTitle " . $Order . " '" . $Title . "' AND `MainTopic` IS NULL AND `MarkedToDelete` = FALSE";
}
$Talks = Talk::get()->where($WhereClause)->sort('PresentationTitle', $Sort);
return $Talks;
}
function CurrentCategory()
{
$CategoryID = Session::get('CategoryID');
if ((1 <= $CategoryID) && ($CategoryID <= 10)) {
$Categories = $this->CategoryList();
return $Categories[$CategoryID - 1]['Name'];
} elseif ($CategoryID == 'Deleted') {
return 'Deleted Presentations';
} elseif ($CategoryID == 'None') {
return 'No Category Assigned';
} else {
return 'All Categories';
}
}
function Restore()
{
$TalkID = Convert::raw2sql($this->request->param("ID"));
if (is_numeric($TalkID)) {
$Talk = Talk::get()->byID($TalkID);
$Talk->MarkedToDelete = FALSE;
$Talk->write();
$this->redirectBack();
}
}
function Previous()
{
$Talks = $this->TalksForNav('prev');
if ($Talks) {
$NextTalk = $Talks->first();
$this->redirect($this->Link() . 'Show/' . $NextTalk->ID);
} else {
// First talk
$this->redirectBack();
}
}
function SearchForm()
{
$SearchForm = new PresentationSearchForm($this, 'SearchForm');
$SearchForm->disableSecurityToken();
return $SearchForm;
}
function doSearch($data, $form)
{
$Talks = NULL;
if ($data['Search']) {
$query = Convert::raw2sql($data['Search']);
$Talks = Talk::get()->filter('PresentationTitle:PartialMatch', $query);
}
if ($Talks) $data["Presentations"] = True;
$data["PresentationList"] = $Talks;
$Talk = $this->findTalk();
$data["Presentation"] = $Talk;
return $this->Customise($data);
}
function FlagForm()
{
$FlagForm = new PresentationFlagForm($this, 'FlagForm');
$FlagForm->disableSecurityToken();
$Talk = $this->findTalk();
if ($Talk) $FlagForm->loadDataFrom($Talk->data());
return $FlagForm;
}
function doFlag($data, $form)
{
$Talk = $this->findTalk();
if ($data['FlagComment']) {
$Talk->FlagComment = $data['FlagComment'];
} else {
$Talk->FlagComment = NULL;
}
$Talk->write();
$this->redirectBack();
}
function CleanTalks()
{
// Set up HTML Purifier
$config = HTMLPurifier_Config::createDefault();
// Remove any CSS or inline styles
$config->set('CSS.AllowedProperties', array());
$config->set('HTML.AllowedAttributes', 'a.href,img.src');
$config->set('HTML.Allowed', 'br,b,strong,li,ol,ul,a,p,img');
$purifier = new HTMLPurifier($config);
$Talks = Talk::get();
foreach ($Talks as $Talk) {
if ($Talk->Abstract) {
$Talk->Abstract = $purifier->purify($Talk->Abstract);
$Talk->write();
}
}
}
function CleanSpeakers()
{
// Set up HTML Purifier
$config = HTMLPurifier_Config::createDefault();
// Remove any CSS or inline styles
$config->set('CSS.AllowedProperties', array());
$config->set('HTML.AllowedAttributes', 'a.href,img.src');
$config->set('HTML.Allowed', 'br,b,strong,li,ol,ul,a,p,img');
$purifier = new HTMLPurifier($config);
$Speakers = Speaker::get();
foreach ($Speakers as $Speaker) {
if ($Speaker->Bio) {
$Speaker->Bio = $purifier->purify($Speaker->Bio);
$Speaker->write();
}
}
}
public function EmailSubmitters()
{
$Talks = Talk::get()->filter(array('BeenEmailed' => 0, 'MarkedToDelete' => 0))->limit(10);
if (!$Talks->count()) {
echo 'no talks match criteria.';
return;
}
foreach ($Talks as $Talk) {
echo '
Woring on talkID ' . $Talk->ID . '
';
//Send email about submission
$To = $Talk->Owner()->Email;
$CurrentSpeaker = $Talk->Speakers('MemberID = ' . $Talk->OwnerID . ' AND TalkID = ' . $Talk->ID);
// Email the admin if :
// the admin is not a speaker,
// or if there is more than one speaker,
// or if there are any speakers wihtout email accounts
if (!$CurrentSpeaker || $Talk->Speakers()->count() > 1 || $this->SpeakerWithoutEmail($Talk)) {
if (!$CurrentSpeaker) echo 'Not one of the speakers.
';
if ($Talk->Speakers()->count() > 1) echo 'More than one speaker.
';
$Subject = "OpenStack Summit Presentation Voting";
$email = EmailFactory::getInstance()->buildEmail(OS_SUMMIT_PRESENTATION_VOTING_FROM_EMAIL, $To, $Subject);
$email->setTemplate("VotingLiveToAdmins");
$email->populateTemplate($Talk);
$email->send();
echo 'Email sent to ' . $Talk->Owner()->Email . '
';
}
$Talk->BeenEmailed = TRUE;
$Talk->write();
}
}
public function EmailSpeakers()
{
$Talks = Talk::get()->filter(array('MarkedToDelete' => 0, 'BeenEmailed' => 0))->sort('PresentationTitle')->limit(50);
if (!$Talks->count()) {
echo 'no talks match criteria.';
return;
}
foreach ($Talks as $Talk) {
//Send email about submission
$Subject = "Your OpenStack Summit Speaking Submission";
if ($Talk->HasSpeaker()) {
foreach ($Talk->Speakers() as $Speaker) {
if ($Speaker->Member()->Email && $this->validEmail($Speaker->Member()->Email)) {
$To = $Speaker->Member()->Email;
$email = EmailFactory::getInstance()->buildEmail(OS_SUMMIT_SPEAKING_SUBMISSION_FROM_EMAIL, $To, $Subject);
$email->setTemplate("VotingAnnounceEmail");
$email->populateTemplate($Talk);
$email->send();
echo 'Email sent to ' . $Speaker->Member()->Email . '
';
}
}
$Talk->BeenEmailed = TRUE;
$Talk->write();
} else {
if ($Talk->Owner()->Email && $this->validEmail($Talk->Owner()->Email)) {
$To = $Talk->Owner()->Email;
$email = EmailFactory::getInstance()->buildEmail(OS_SUMMIT_SPEAKING_SUBMISSION_FROM_EMAIL, $To, $Subject);
$email->setTemplate("VotingAnnounceEmail");
$email->populateTemplate($Talk);
$email->send();
$Talk->BeenEmailed = TRUE;
$Talk->write();
echo 'Email sent to ' . $Talk->Owner()->Email . '
';
}
}
}
}
/**
* Validate an email address.
* Provide email address (raw input)
* Returns true if the email address has the email
* address format and the domain exists.
*/
function validEmail($email)
{
$isValid = true;
$atIndex = strrpos($email, "@");
if (is_bool($atIndex) && !$atIndex) {
$isValid = false;
} else {
$domain = substr($email, $atIndex + 1);
$local = substr($email, 0, $atIndex);
$localLen = strlen($local);
$domainLen = strlen($domain);
if ($localLen < 1 || $localLen > 64) {
// local part length exceeded
$isValid = false;
} else if ($domainLen < 1 || $domainLen > 255) {
// domain part length exceeded
$isValid = false;
} else if ($local[0] == '.' || $local[$localLen - 1] == '.') {
// local part starts or ends with '.'
$isValid = false;
} else if (preg_match('/\\.\\./', $local)) {
// local part has two consecutive dots
$isValid = false;
} else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
// character not valid in domain part
$isValid = false;
} else if (preg_match('/\\.\\./', $domain)) {
// domain part has two consecutive dots
$isValid = false;
} else if
(!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',
str_replace("\\\\", "", $local))
) {
// character not valid in local part unless
// local part is quoted
if (!preg_match('/^"(\\\\"|[^"])+"$/',
str_replace("\\\\", "", $local))
) {
$isValid = false;
}
}
if ($isValid && !(checkdnsrr($domain, "MX") || checkdnsrr($domain, "A"))) {
// domain not found in DNS
$isValid = false;
}
}
return $isValid;
}
function TalkStatus()
{
$Talks = Talk::get();
foreach ($Talks as $Talk) {
echo $Talk->ID . " called " . $Talk->PresentationTitle . "
";
}
}
function AcceptedSpeakersWithoutEmails()
{
$Speakers = Talk::get();
foreach ($Speakers as $Speaker) {
$AcceptedTalks = $Speaker->AcceptedTalks();
$UnacceptedTalks = $Speaker->UnacceptedTalks();
$AlternateTalks = $Speaker->AlternateTalks();
if (($AcceptedTalks->count() || $AlternateTalks->count()) && $Speaker->Member()->Email == NULL) {
echo $Speaker->ID . ' ' . $Speaker->FirstName . ' ' . $Speaker->Surname . ' was accepted but deos not have an email.
';
}
}
}
function AcceptedSpeakersNotContacted()
{
$Speakers = Speaker::get();
foreach ($Speakers as $Speaker) {
$AcceptedTalks = $Speaker->AcceptedTalks();
$UnacceptedTalks = $Speaker->UnacceptedTalks();
$AlternateTalks = $Speaker->AlternateTalks();
if (($AcceptedTalks->count() || $AlternateTalks->count()) && $Speaker->BeenEmailed == 0) {
echo $Speaker->ID . ' ' . $Speaker->FirstName . ' ' . $Speaker->Surname . ' was accepted but has not been contacted.
';
}
}
}
function AcceptedSpeakersNotConfirmed()
{
$Speakers = Speaker::get();
foreach ($Speakers as $Speaker) {
$AcceptedTalks = $Speaker->AcceptedTalks();
$UnacceptedTalks = $Speaker->UnacceptedTalks();
$AlternateTalks = $Speaker->AlternateTalks();
if (($AcceptedTalks->count() || $AlternateTalks->count()) && $Speaker->Confirmed == 0) {
echo $Speaker->ID . ' ' . $Speaker->FirstName . ' ' . $Speaker->Surname . ' was accepted but has not confirmed.
';
}
}
}
function AcceptedTalksWithoutSpeakers()
{
$Talks = Talk::get();
foreach ($Talks as $Talk) {
if ($Talk->Speakers()->count() == 0 && ($Talk->Status() == 'accepted' || $Talk->Status() == 'alternate')) {
echo $Talk->PresentationTitle . '(' . $Talk->SummitCategory()->Name . ') from ' . $Talk->Owner()->FirstName . ' ' . $Talk->Owner()->Surname . ' ' . $Talk->Owner()->Email . ' was accepted but has no speakers.
';
}
}
}
function AllAcceptedOrALternateSpeakers()
{
$Speakers = Speaker::get();
$ReturnSet = new ArrayList();
foreach ($Speakers as $Speaker) {
if ($Speaker->AcceptedTalks()->count() || $Speaker->AlternateTalks()->count()) {
$ReturnSet->push($Speaker);
}
}
return $ReturnSet;
}
function AllUnAcceptedSpeakers()
{
$Speakers = Speaker::get();
$ReturnSet = new ArrayList();
foreach ($Speakers as $Speaker) {
$DuplicateSpeakers = Speaker::get()->filter(array('FirstName' => $Speaker->FirstName, 'Surname' => $Speaker->Surname, 'ID:not' => $Speaker->ID));
if (!$DuplicateSpeakers->count() && $Speaker->AcceptedTalks()->count() == 0 && $Speaker->AlternateTalks()->count() == 0) {
$ReturnSet->push($Speaker);
}
}
return $ReturnSet;
}
function AllTalks()
{
return Talk::get()->filter('SummitCategoryID', 29);
}
function SpeakersForSched()
{
$Speakers = Speaker::get();
foreach ($Speakers as $Speaker) {
$AcceptedTalks = $Speaker->AcceptedTalks();
$AlternateTalks = $Speaker->AlternateTalks();
$PhotoURL = "";
if ($Speaker->PhotoID != 0) $PhotoURL = 'http://www.openstack.org' . $Speaker->Photo()->getURL();
if ($Speaker->Bio == NULL) {
$SpeakerWithBio = Speaker::get()->filter('MemberID', $Speaker->MemberID)->where('BIO IS NOT NULL');
if ($SpeakerWithBio->count()) $Speaker->Bio = $SpeakerWithBio->first()->Bio;
}
if ($AcceptedTalks->count()) {
echo '"' . $Speaker->ID . '"|"' . utf8_decode($Speaker->FirstName) . ' ' . utf8_decode($Speaker->Surname) . '"|"' . utf8_decode($Speaker->Title) . '"|"' . $Speaker->Member()->Email . '"|"' . $PhotoURL . '"|"' . htmlspecialchars(utf8_decode($Speaker->Bio)) . '"
';
}
}
}
function ScheduleForSched()
{
$SummitCategories = SummitCategory::get()->filter('SummitID', 3);
foreach ($SummitCategories as $Category) {
// Grab the track chairs selections for the category
$SelectedTalkList = SummitSelectedTalkList::get()->filter('SummitCategoryID', $Category->ID)->first();
// Loop through each selected talk to output the details
// Note that a SummitSelectedTalk is really just a cross-link table that also contains the priority the talk was given
foreach ($SelectedTalkList->SortedTalks() as $Selection) {
$Talk = $Selection->Talk();
echo '"' . $Talk->ID . '"|"' . utf8_decode($Talk->PresentationTitle) . '"|"' . $Talk->SummitCategory()->Name . '"|"' . htmlspecialchars(utf8_decode($Talk->Abstract)) . '"|';
// Speaker column
echo '"';
foreach ($Talk->Speakers() as $Speaker) {
echo utf8_decode($Speaker->FirstName);
echo " ";
echo utf8_decode($Speaker->Surname);
echo ',';
}
echo '"
';
}
}
}
function SpeakersWithUnassignedTalks()
{
$Speakers = Speaker::get();
foreach ($Speakers as $Speaker) {
$Talks = $Speaker->Talks('SummitCategoryID = 25');
if ($Talks->count()) {
echo 'Speaker: ' . $Speaker->FirstName . ' ' . $Speaker->Surname . '
';
if ($Speaker->AcceptedTalks()->count() || $Speaker->AlternateTalks()->count()) {
echo 'Has other accepted / alternate talks
';
}
foreach ($Talks as $Talk) {
echo $Talk->PresentationTitle . '
';
}
echo '
';
}
}
}
function SpeakerCompanyReport()
{
$Speakers = Speaker::get()->filter('Email:PartialMatch', 'cisco')->leftJoin('Member', 'Member ON Speaker.MemberID = Member.I')->limit(800);
echo 'Speaker Count: ' . $Speakers->count() . '
';
foreach ($Speakers as $Speaker) {
$AcceptedTalks = $Speaker->AcceptedTalks();
$UnacceptedTalks = $Speaker->UnacceptedTalks();
$AlternateTalks = $Speaker->AlternateTalks();
if ($Speaker->HasTalksInCurrentSummit()) {
echo '