/** * Determines whether the token is still valid (from days since it was created). * * @return bool */ public function isExpired() { $createdSeconds = strtotime($this->Created); $validForSeconds = (int) $this->ValidForDays * 24 * 60 * 60; $nowSeconds = strtotime(SS_DateTime::now()->Format("Y-m-d H:i:s")); return $createdSeconds + $validForSeconds <= $nowSeconds; }
/** * @return SS_HTTPRequest */ public function backup() { $name = 'assets_' . SS_DateTime::now()->Format('Y-m-d') . '.zip'; $tmpName = TEMP_FOLDER . '/' . $name; $zip = new ZipArchive(); if (!$zip->open($tmpName, ZipArchive::OVERWRITE)) { user_error('Asset Export Extension: Unable to read/write temporary zip archive', E_USER_ERROR); return; } $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(ASSETS_PATH, RecursiveDirectoryIterator::SKIP_DOTS)); foreach ($files as $file) { $local = str_replace(ASSETS_PATH . '/', '', $file); $zip->addFile($file, $local); } if (!$zip->status == ZipArchive::ER_OK) { user_error('Asset Export Extension: ZipArchive returned an error other than OK', E_USER_ERROR); return; } $zip->close(); if (ob_get_length()) { @ob_flush(); @flush(); @ob_end_flush(); } @ob_start(); $content = file_get_contents($tmpName); unlink($tmpName); return SS_HTTPRequest::send_file($content, $name); }
/** * Creates a guestbook entry with default values. * @return \GuestbookEntry */ public static function create() { $entry = new GuestbookEntry(); $entry->Date = SS_DateTime::now()->getValue(); $entry->IpAddress = $_SERVER['REMOTE_ADDR']; $entry->Host = gethostbyaddr($entry->IpAddress); return $entry; }
/** * @param string $queue * @return null|QueuedJobDescriptor */ protected function getNextJobDescriptorWithoutMutex($queue) { $list = QueuedJobDescriptor::get()->filter('JobType', $queue)->sort('ID', 'ASC'); $descriptor = $list->filter('JobStatus', QueuedJob::STATUS_WAIT)->first(); if ($descriptor) { return $descriptor; } return $list->filter('JobStatus', QueuedJob::STATUS_NEW)->where(sprintf('"StartAfter" < \'%s\' OR "StartAfter" IS NULL', SS_DateTime::now()->getValue()))->first(); }
public function spellcheck(SS_HTTPRequest $request) { $this->owner->request->addHeader('Content-Type', 'text/plain'); $this->owner->request->addHeader('Content-Encoding', 'UTF-8'); $this->owner->request->addHeader('Expires', 'Mon, 26 Jul 1007 05:00:00 GMT'); $this->owner->request->addHeader('Last-Modified', SS_DateTime::now()->Format('D, d M Y H:i:s') . ' GMT'); $this->owner->request->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate'); $this->owner->request->addHeader('Cache-Control', 'post-check=0, pre-check=0'); $this->owner->request->addHeader('Pragma', 'no-cache'); $engine = self::$engine; $shell = self::$shell; if (!defined('SPELLCHECK_POST_SS3')) { $engine = Config::inst()->get('CMSSpellChecker', 'engine') ?: $engine; $shell = Config::inst()->get('CMSSpellChecker', 'shell') ?: $shell; } if (!defined('PSPELL_FAST')) { define('PSPELL_FAST', 1); } # Fast mode (least number of suggestions) if (!defined('PSPELL_NORMAL')) { define('PSPELL_NORMAL', 2); } # Normal mode (more suggestions) if (!defined('PSPELL_BAD_SPELLERS')) { define('PSPELL_BAD_SPELLERS', 3); } # Slow mode (a lot of suggestions) $config['general.engine'] = $engine; $config['PSpell.mode'] = PSPELL_FAST; $config['PSpell.spelling'] = ''; $config['PSpell.jargon'] = ''; $config['PSpell.encoding'] = ''; $config['PSpellShell.mode'] = PSPELL_FAST; $config['PSpellShell.aspell'] = $shell; $config['PSpellShell.tmp'] = '/tmp'; $output = array('id' => null, 'result' => null, 'error' => null); $raw = $request->requestVar('json_data') ?: ''; if (!$raw) { $raw = '' . file_get_contents('php://input'); } if (!$raw) { $output['error'] = array('errstr' => 'Could not get raw post data', 'errfile' => '', 'errline' => null, 'errcontext' => '', 'level' => 'FATAL'); echo json_encode($output); exit; } $input = json_decode($raw, true); if (isset($config['general.engine'])) { $spellchecker = new $config['general.engine']($config); $result = call_user_func_array(array($spellchecker, $input['method']), $input['params']); } $output['id'] = $input['id']; $output['result'] = $result; echo json_encode($output); }
/** * */ 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"; }); }
/** * Check the current job queues and see if any of the jobs currently in there should be started. If so, * return the next job that should be executed * * @param string $type Job type * @return QueuedJobDescriptor */ public function getNextPendingJob($type = null) { // Filter jobs by type $type = $type ?: QueuedJob::QUEUED; $list = QueuedJobDescriptor::get()->filter('JobType', $type)->sort('ID', 'ASC'); // see if there's any blocked jobs that need to be resumed $waitingJob = $list->filter('JobStatus', QueuedJob::STATUS_WAIT)->first(); if ($waitingJob) { return $waitingJob; } // If there's an existing job either running or pending, the lets just return false to indicate // that we're still executing $runningJob = $list->filter('JobStatus', array(QueuedJob::STATUS_INIT, QueuedJob::STATUS_RUN))->first(); if ($runningJob) { return false; } // Otherwise, lets find any 'new' jobs that are waiting to execute $newJob = $list->filter('JobStatus', QueuedJob::STATUS_NEW)->where(sprintf('"StartAfter" < \'%s\' OR "StartAfter" IS NULL', SS_DateTime::now()->getValue()))->first(); return $newJob; }
/** * @param $id * @return array */ public function getVideoDetail($id) { $video = PresentationVideo::get()->filter(['Presentation.Slug' => $id, 'DisplayOnSite' => true, 'Processed' => true])->first(); if (!$video) { $video = PresentationVideo::get()->filter(['ID' => $id, 'DisplayOnSite' => true, 'Processed' => true])->first(); } if ($video) { $cutoff = time() - SummitVideoApp::config()->video_view_staleness; $videoStaleness = strtotime($video->ViewsLastUpdated); // Refresh the views if they're not of acceptable staleness if (!$video->ViewsLastUpdated || $videoStaleness < $cutoff) { // Set the last updated regardless of the outcome, so we don't get // unthrottled failures. $video->ViewsLastUpdated = SS_DateTime::now()->Rfc2822(); try { $response = $this->youTube->getVideoStatsById($video->YouTubeID); if ($response) { $data = Convert::json2array($response->getBody()->getContents()); if (!empty($data['items'])) { $videoData = $data['items'][0]; $video->Views = $videoData['statistics']['viewCount']; } } } catch (Exception $e) { SS_Log::log("Summit video app tried to get video {$video->YouTubeID}: {$e->getMessage()}", SS_Log::ERR); } $video->write(); } $json = $this->createVideoJSON($video); $json['description'] = $video->Presentation()->ShortDescription ?: $video->Presentation()->Description; return $json; } }
/** * Get the items, per month/year/author * If no month or year is set, current month/year is assumed * @todo cleanup the month-method maybe? * @return Array $filter Filtering for the allNews getter */ public function generateAddedFilter() { $mapping = self::$url_handlers; $params = $this->getURLParams(); /** @var array $filter Generic/default filter */ $filter = array('Live' => 1); if (isset($params['Action'])) { switch ($mapping[$params['Action']]) { /** Archive */ case 'archive': if (!isset($params['ID'])) { $month = SS_DateTime::now()->Format('m'); $year = SS_DateTime::now()->Format('Y'); } elseif (!isset($params['OtherID']) && isset($params['ID'])) { $year = $params['ID']; $month = ''; } else { $year = $params['ID']; $month = date_parse('01-' . $params['OtherID'] . '-1970'); $month = str_pad((int) $month['month'], 2, "0", STR_PAD_LEFT); } $filter['PublishFrom:PartialMatch'] = $year . '-' . $month; break; /** Author */ /** Author */ case 'author': $filter['AuthorHelper.URLSegment:ExactMatch'] = $params['ID']; break; } } return $filter; }
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 activeNews() { $now = SS_DateTime::now()->Format('Y-m-d'); return $this->News()->filter(array('Live' => true))->exclude(array('PublishFrom:GreaterThan' => $now)); }
/** * {@inheritdoc} */ public function onAfterWrite() { parent::onAfterWrite(); $siteConfig = SiteConfig::current_site_config(); /** * This is related to another module of mine. * Check it at my repos: Silverstripe-Social. * It auto-tweets your new Newsitem. If the TwitterController exists ofcourse. * It doesn't auto-tweet if the publish-date is in the future. Also, it won't tweet when it's that date! * @todo refactor this to a facebook/twitter oAuth method that a dev spent more time on developing than I did on my Social-module. */ if (class_exists('TwitterController')) { $date = SS_DateTime::now()->Format('Y-m-d'); if ($this->Live && $this->PublishDate <= $date && !$this->Tweeted && $siteConfig->TweetOnPost) { $this->Tweeted = true; $this->write(); } } }
/** * 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); }
/** * @return SS_HTTPRequest */ public function export() { // get folder $folder = $this->owner->currentPage(); $fn = $folder->exists() && $folder->getFilename() ? str_replace(ASSETS_DIR, '', $folder->getFilename()) : ''; $path = realpath(ASSETS_PATH . $fn); // init zip $fn = preg_replace('/-+/', '-', 'assets-' . preg_replace('/[^a-zA-Z0-9]+/', '-', $fn) . '-' . SS_DateTime::now()->Format('Y-m-d') . '.zip'); $tmpName = TEMP_FOLDER . '/' . $fn; $zip = new ZipArchive(); // create zip file for writing if ($zip->open($tmpName, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) { user_error('Asset Export Extension: Unable to read/write temporary zip archive', E_USER_ERROR); return; } // get whitelisted files $files = $this->getDirContents($path); // build zip foreach ($files as $file) { $local = trim(str_replace($path, '', $file), '/'); $zip->addFile($file, $local); } // check the status if (!$zip->status == ZipArchive::ER_OK) { user_error('Asset Export Extension: ZipArchive returned an error other than OK', E_USER_ERROR); return; } $zip->close(); if (ob_get_length()) { @ob_flush(); @flush(); @ob_end_flush(); } @ob_start(); $content = file_get_contents($tmpName); unlink($tmpName); return SS_HTTPRequest::send_file($content, $fn); }