/**
  * Get the current program object or load it if it hasn't been loaded yet
  * @return VideoPageToolProgram
  */
 public function getProgram()
 {
     if (!$this->program) {
         $lang = F::App()->wg->LanguageCode;
         $this->program = VideoPageToolProgram::loadProgramNearestDate($lang);
     }
     return $this->program;
 }
 /**
  * Edit program assets given a language (region), program date and page section
  * @requestParam string language
  * @requestParam string date [timestamp]
  * @requestParam string section [featured/category/fan]
  * @responseParam string result [ok/error]
  * @responseParam string msg - result message
  */
 public function edit()
 {
     JSMessages::enqueuePackage('VideoPageTool', JSMessages::EXTERNAL);
     $time = $this->getVal('date', time());
     $language = $this->getVal('language', VideoPageToolHelper::DEFAULT_LANGUAGE);
     $section = $this->getVal('section', VideoPageToolHelper::DEFAULT_SECTION);
     $action = $this->getVal('action', '');
     // for save message
     $success = $this->getVal('success', '');
     $helper = new VideoPageToolHelper();
     // get date
     $date = strtotime(date('Y-M-d', $time));
     // validate section - set to DEFAULT_SECTION if not exists
     $sections = $helper->getSections();
     if (!array_key_exists($section, $sections)) {
         $section = VideoPageToolHelper::DEFAULT_SECTION;
     }
     // get left menu items
     $leftMenuItems = $helper->getLeftMenuItems($section, $sections, $language, $date);
     $program = VideoPageToolProgram::newProgram($language, $date);
     // get program assets. VPT needs a program object for each request. It first checks if one already exists for
     // that language and date. If one doesn't, it creates a new one. It then uses that program to pull the
     // associated assets. If it's a new program, it won't have any assets yet created. To help the user, we
     // grab the assets from the the last saved program and use those as the default assets for this new program.
     $assets = $program->getAssetsBySection($section);
     if (empty($assets)) {
         $latestProgram = VideoPageToolProgram::loadProgramNearestDate($language, $date);
         if (!empty($latestProgram)) {
             $assets = $latestProgram->getAssetsBySection($section);
         }
     }
     $publishDate = null;
     $publishedBy = null;
     if ($program->isPublished()) {
         $publishDate = $program->getPublishDate();
         $publishedBy = $program->getPublishedBy();
     } else {
         if (isset($latestProgram) && $latestProgram->isPublished()) {
             $publishDate = $latestProgram->getPublishDate();
             $publishedBy = $latestProgram->getPublishedBy();
         }
     }
     if ($publishedBy) {
         // Translate user id into username
         $publishedBy = User::newFromId($publishedBy)->getName();
     }
     $lastSavedOn = 0;
     $savedBy = null;
     // get asset data
     $videos = array();
     if (empty($assets)) {
         // get default assets
         $videos = $helper->getDefaultValuesBySection($section);
     } else {
         // Override defaults so we always show a lightbox in the admin pages
         $thumbOptions = ['noLightbox' => false];
         // Saved on and saved by data are saved on a per asset basis, therefore it's necessary to loop through each
         // asset to make sure we're using the latest saved information.
         foreach ($assets as $order => $asset) {
             /** @var VideoPageToolAsset $asset */
             $videos[$order] = $asset->getAssetData($thumbOptions);
             if ($asset->getUpdatedAt() > $lastSavedOn) {
                 $lastSavedOn = $asset->getUpdatedAt();
                 $savedBy = $asset->getUpdatedBy();
             }
         }
         $savedBy = User::newFromId($savedBy)->getName();
     }
     $result = '';
     $msg = '';
     if ($this->request->wasPosted()) {
         // publish program
         if ($action == 'publish') {
             $response = $this->sendSelfRequest($action, array('date' => $date, 'language' => $language));
             $msg = $response->getVal('msg', '');
             $result = $response->getVal('result', '');
             if ($result == 'ok') {
                 // redirect to Special:VideoPageAdmin
                 $url = SpecialPage::getTitleFor('VideoPageAdmin')->getLocalURL();
                 $msg = wfMessage('videopagetool-success-publish')->plain();
                 BannerNotificationsController::addConfirmation($msg, BannerNotificationsController::CONFIRMATION_CONFIRM);
                 $this->getContext()->getOutput()->redirect($url);
                 return false;
             }
             // save assets
         } else {
             $formValues = $this->request->getParams();
             $errMsg = '';
             // use displayTitle field to get required rows
             $requiredRows = $helper->getRequiredRows($section, $formValues);
             $data = $program->formatFormData($section, $requiredRows, $formValues, $errMsg);
             // Add blank records so $data is the same length as $assets.
             // This ensures the old assets are removed from DB if they were removed from the input form
             for ($i = count($data) + 1; $i <= count($assets); $i++) {
                 $data[$i] = [];
             }
             if (empty($errMsg)) {
                 $status = $program->saveAssetsBySection($section, $data);
                 if ($status->isGood()) {
                     $nextUrl = $helper->getNextMenuItemUrl($leftMenuItems) . '&success=1';
                     $this->getContext()->getOutput()->redirect($nextUrl);
                     return false;
                 } else {
                     $result = 'error';
                     $msg = $status->getMessage();
                 }
             } else {
                 // update original asset data
                 foreach ($data as $order => $row) {
                     foreach ($row as $name => $value) {
                         $videos[$order][$name] = $value;
                         // replace alternative thumbnail
                         if ($name == 'altThumbTitle' && array_key_exists('altThumbKey', $videos[$order]) && $videos[$order]['altThumbKey'] != $value) {
                             $videos[$order] = $helper->replaceThumbnail($videos[$order], $value);
                         }
                     }
                 }
                 $result = 'error';
                 $msg = $errMsg;
             }
         }
         // save successfully
     } else {
         if (!empty($success)) {
             $result = 'ok';
             $msg = wfMessage('videopagetool-success-save')->plain();
         }
     }
     // add default values if the number of assets is less than number of rows that needed to be shown
     $defaultValues = array_pop($helper->getDefaultValuesBySection($section, 1));
     for ($i = count($videos) + 1; $i <= $helper->getRequiredRowsMax($section); $i++) {
         $videos[$i] = $defaultValues;
     }
     $this->result = $result;
     $this->msg = $msg;
     $this->leftMenuItems = $leftMenuItems;
     $this->moduleView = $this->app->renderView('VideoPageAdminSpecial', $section, array('videos' => $videos, 'date' => $date, 'language' => $language));
     $this->publishButton = $program->isPublishable(array_keys($sections)) ? '' : 'disabled';
     $this->publishUrl = $this->wg->Title->getLocalURL(array('date' => $date, 'language' => $language));
     $this->programDate = $program->getFormattedPublishDate();
     $this->section = $section;
     $this->language = $language;
     $this->lastSavedOn = $lastSavedOn;
     $this->savedBy = $savedBy;
     $this->publishDate = $publishDate;
     $this->publishedBy = $publishedBy;
 }