/**
  * @param $data
  * @param $form
  * @throws ValidationException
  * @throws null
  */
 public function setasfeatured($data, $form)
 {
     foreach (PresentationVideo::get()->filter('Featured', true) as $v) {
         $v->Featured = false;
         $v->write();
     }
     $this->Featured = true;
     $this->write();
     return 'This is now the featured video';
 }
 /**
  *
  */
 public function run()
 {
     SapphireTransactionManager::getInstance()->transaction(function () {
         $pageToken = null;
         while (true) {
             if ($this->videosUpdated >= SummitVideoApp::config()->popular_video_limit) {
                 break;
             }
             // Prevent an infinite loop if the YouTube service is acting strange
             if ($this->sanityCheck === 5) {
                 $e = new Exeception('Task has run too many times. Seems to be an infinite loop. Could be something wrong with the YouTube service?');
                 SS_Log::log($e, SS_Log::ERR);
                 throw $e;
             }
             try {
                 $response = $this->api->getPopularVideos($pageToken);
             } catch (\Exception $e) {
                 SS_Log::log("YouTube Search failed" . $e->getMessage(), SS_Log::ERR);
             }
             $this->sanityCheck++;
             $body = $response->getBody()->getContents();
             $data = Convert::json2array($body);
             $nextPageToken = @$data['nextPageToken'];
             $ids = [];
             foreach ($data['items'] as $item) {
                 if ($item['id']['kind'] === 'youtube#video') {
                     $ids[] = $item['id']['videoId'];
                 }
             }
             try {
                 $response = $this->api->getVideoStatsById($ids);
             } catch (\Exception $e) {
                 SS_Log::log("YouTube video stats failed" . $e->getMessage(), SS_Log::ERR);
             }
             $body = $response->getBody()->getContents();
             $data = Convert::json2array($body);
             foreach ($data['items'] as $v) {
                 $video = PresentationVideo::get()->filter(['YouTubeID' => $v['id']])->first();
                 if ($video) {
                     $video->Views = $v['statistics']['viewCount'];
                     $video->write();
                     $this->videosUpdated++;
                 }
             }
             // If there are no more pages, then bail
             if ($nextPageToken === $pageToken) {
                 break;
             }
             $pageToken = $nextPageToken;
         }
         echo "{$this->videosUpdated} videos updated.\n";
     });
 }
 /**
  *
  */
 public function run()
 {
     SapphireTransactionManager::getInstance()->transaction(function () {
         $unprocessedVideos = PresentationVideo::get()->filter(['Processed' => false])->limit(50);
         if (!$unprocessedVideos->exists()) {
             return;
         }
         $summit = Summit::get_active();
         $dateUTC = $summit->convertDateFromTimeZone2UTC(SS_DateTime::now()->Rfc2822());
         $dateUTCTimestamp = strtotime($dateUTC);
         $maxAge = SummitVideoApp::config()->abandon_unprocessed_videos_after;
         $ids = [];
         foreach ($unprocessedVideos as $video) {
             $age = $dateUTCTimestamp - strtotime($video->DateUploaded);
             if ($age > $maxAge) {
                 SS_Log::log("Video {$video->Title} has been unprocessed for a long time. ({$age} seconds). It should be deleted.", SS_Log::WARN);
                 continue;
             }
             $ids[] = $video->YouTubeID;
         }
         try {
             $response = $this->api->getVideoStatusById($ids);
         } catch (\Exception $e) {
             SS_Log::log("YouTube check for status failed" . $e->getMessage(), SS_Log::ERR);
             return;
         }
         $body = $response->getBody()->getContents();
         $data = Convert::json2array($body);
         $items = $data['items'];
         if (empty($items)) {
             echo "No videos are marked as processing. Exiting.\n";
             return;
         }
         foreach ($items as $item) {
             $currentStatus = $item['status']['uploadStatus'];
             if ($currentStatus == 'processed') {
                 $video = PresentationVideo::get()->filter(['YouTubeID' => $item['id']])->first();
                 if (!$video) {
                     SS_Log::log("Tried to update processing status for " . $item['id'] . " but no PresentationVideo with that YouTubeID was found.", SS_Log::WARN);
                     continue;
                 }
                 $video->Processed = true;
                 $video->write();
                 $this->videosUpdated++;
             }
         }
         echo "{$this->videosUpdated} videos updated.\n";
     });
 }
 /**
  * @param Summit $s
  * @return array
  */
 protected function createSummitJSON(Summit $s)
 {
     $page = SummitPage::get()->filter('SummitID', $s->ID)->first();
     $image = null;
     if ($page) {
         $image = $page->SummitImage()->Image();
     }
     return ['id' => $s->ID, 'title' => $s->Title, 'dates' => $s->getSummitDateRange(), 'videoCount' => PresentationVideo::get()->filter(['DisplayOnSite' => true, 'Processed' => true, 'PresentationID' => $s->Presentations()->column('ID')])->count(), 'imageURL' => $image && $image->exists() && Director::fileExists($image->Filename) ? $image->CroppedImage(263, 148)->URL : 'summit-video-app/production/images/placeholder-image.jpg'];
 }
 /**
  * Create a PresentationVideo object for a presentation from a VideoPresentation
  * @param  Presentation $p
  * @param  VideoPresentation $v
  * @return PresentationVideo
  */
 private function createLegacyVideoMaterial(Presentation $p, VideoPresentation $v)
 {
     return PresentationVideo::create(['PresentationID' => $p->ID, 'Name' => $v->Name, 'DisplayOnSite' => $v->DisplayOnSite, 'YouTubeID' => trim($v->YouTubeID), 'Featured' => $v->Featured, 'Created' => $v->LastEdited, 'LastEdited' => $v->LastEdited, 'DateUploaded' => $p->StartDate ?: $p->Summit()->SummitBeginDate]);
 }
 public function handleApplyVideo(SS_HTTPRequest $r)
 {
     if (!Permission::check('VIDEO_UPLOADER')) {
         return $this->httpError(403, 'You do not have permission to use this method');
     }
     // Only allow one writeable property here
     if ($youTube = $r->postVar('youtubeid')) {
         $video = $this->presentation->Materials()->filter('ClassName', 'PresentationVideo')->first();
         if (!$video) {
             $video = PresentationVideo::create();
         }
         $dateUTC = $this->presentation->Summit()->convertDateFromTimeZone2UTC(SS_DateTime::now()->Rfc2822());
         $video->PresentationID = $this->presentation->ID;
         $video->DateUploaded = $dateUTC;
         $video->Name = $this->presentation->Title;
         $video->DisplayOnSite = true;
         $video->YouTubeID = $youTube;
         $video->write();
         return new SS_HTTPResponse("OK", 200);
     }
     return $this->httpError(400, "You must provide a youtubeid parameter in the POST request");
 }
 public function MetaTags()
 {
     $page = $this->request->param('Page');
     $id = $this->request->param('ID');
     $summit = Summit::get()->filter('Slug', $page)->first();
     if ($summit && $id) {
         $video = PresentationVideo::get()->filter(['Presentation.Slug' => $id, 'DisplayOnSite' => true, 'Processed' => true])->first();
         if (!is_null($video)) {
             return $video->MetaTags();
         } else {
             return parent::MetaTags();
         }
     }
     return parent::MetaTags();
 }
 /**
  * @param Summit $s
  * @return array
  */
 protected function createSummitJSON(Summit $s)
 {
     $page = SummitPage::get()->filter('SummitID', $s->ID)->first();
     $image = null;
     if ($page) {
         $image = $page->SummitImage()->Image();
     }
     $tracks = array_map(function ($t) {
         return ['id' => $t->ID, 'slug' => $t->Slug, 'title' => $t->Title, 'has_videos' => 0];
     }, $s->Categories()->toArray());
     $videos = PresentationVideo::get()->filter(['DisplayOnSite' => true, 'Processed' => true])->sort('DateUploaded', 'DESC')->innerJoin('Presentation', 'Presentation.ID = PresentationMaterial.PresentationID')->innerJoin('SummitEvent', 'SummitEvent.ID = PresentationMaterial.PresentationID')->filter('SummitEvent.SummitID', $s->ID);
     $videos_groupedby_track = GroupedList::create($videos)->groupBy('Track');
     foreach ($tracks as &$track) {
         if (array_key_exists($track['title'], $videos_groupedby_track)) {
             $track['has_videos'] = 1;
         }
     }
     return ['id' => $s->ID, 'title' => $s->Title, 'dates' => $s->getSummitDateRange(), 'videoCount' => PresentationVideo::get()->filter(['DisplayOnSite' => true, 'Processed' => true, 'PresentationID' => $s->Presentations()->column('ID')])->count(), 'imageURL' => $image && $image->exists() && Director::fileExists($image->Filename) ? $image->CroppedImage(263, 148)->URL : 'summit-video-app/production/images/placeholder-image.jpg', 'slug' => $s->Slug, 'tracks' => $tracks];
 }
 /**
  * Tests if only recently uploaded videos get the processing check
  */
 public function testItUpdatesRecentUnprocessedVideos()
 {
     global $statusResponse;
     DB::query('UPDATE PresentationVideo SET Processed=0 WHERE YouTubeID%2 = 0');
     DB::query('UPDATE PresentationVideo SET DateUploaded = DATE(NOW())');
     DB::query("UPDATE Summit SET Active = 1, Timezone = 279 WHERE Title = 'Tokyo'");
     $mockService = $this->createMockYouTubeService('getVideoStatusByID', $this->returnValue(Convert::array2json($statusResponse)));
     $mockService->expects($this->once())->method('getVideoStatusByID')->with($this->logicalAnd($this->contains(2), $this->contains(4), $this->contains(6), $this->contains(8), $this->contains(10), $this->contains(12)));
     $task = new SummitVideoProcessingTask($mockService);
     $task->run();
     foreach (PresentationVideo::get()->filter(['YouTubeID' => [2, 6, 10]]) as $video) {
         $this->assertEquals(1, $video->Processed);
     }
     foreach (PresentationVideo::get()->filter(['YouTubeID' => [4, 8, 12]]) as $video) {
         $this->assertEquals(0, $video->Processed);
     }
     $this->assertEquals(3, $task->getVideosUpdated());
 }
 /**
  * Tests if the video gets stamped even when the YouTube service fails
  */
 public function testItWillUpdateTheLastViewsUpdatedWhenServiceFails()
 {
     Config::inst()->update('SummitVideoApp', 'video_view_staleness', 3600);
     $video1 = $this->objFromFixture('PresentationVideo', 'Video1');
     $video1->Views = 10;
     $video1->ViewsLastUpdated = date('Y-m-d H:i:s', strtotime('-2 hours'));
     $video1->write();
     $mockService = $this->createMockYouTubeService(['getVideoStatsByID' => function ($self) {
         return $self->once();
     }], $this->returnValue(new Exception('It failed spectacularly')));
     $mockService->expects($this->once())->method('getVideoStatsByID')->with($this->equalTo($video1->YouTubeID));
     $backend = new SummitVideoAppBackend($mockService);
     $videoDetail = $backend->getVideoDetail($video1->ID);
     $video1 = PresentationVideo::get()->filter('YouTubeID', $video1->YouTubeID)->first();
     $this->assertEquals(10, $video1->Views);
     // In all likelihood, the diff should be 0, here. Timestamp is set to now.
     // But for testing we'll have a bit of tolerance.
     $diff = strtotime(SS_DateTime::now()->Rfc2822()) - strtotime($video1->ViewsLastUpdated);
     $this->assertLessThan(10, $diff);
 }