/** * Returns the stream URL for the media. A direct link will be returned if * the user is on a mobile device or if the "singleFilePlaylist" setting * is enabled, otherwise the media playlist URL will be returned * @return string the stream URL */ protected function getStreamUrl() { if (count($this->_links) === 1 && (Setting::getBoolean('singleFilePlaylist') || (Browser::isMobile() || Browser::isTablet()))) { return $this->_links[0]->url; } else { return $this->getPlayListAction(); } }
/** * Displays a flash if the backend doesn't support streaming * @param CFilterChain $filterChain the filter chain */ public function filterCheckBackendCanStream($filterChain) { // Check backend version and warn about incompatibilities if (!Yii::app()->xbmc->meetsMinimumRequirements() && !Setting::getBoolean('disableFrodoWarning')) { Yii::app()->user->setFlash('info', Yii::t('Misc', 'Streaming of video files is not possible from XBMC 12 "Frodo" backends')); } $filterChain->run(); }
/** * Generates a nicely formatted help block, useful to explain what a form or * a page does. Nothing is rendered if the "showHelpBlocks" setting is set * to false. * @param string $content the block content * @return string the HTML for the help block */ public static function helpBlock($content) { if (!Setting::getBoolean('showHelpBlocks')) { return; } $output = CHtml::openTag('p', array('class' => 'form-help')); $output .= TbHtml::icon(TbHtml::ICON_EXCLAMATION_SIGN); $output .= $content; $output .= CHtml::closeTag('p'); return $output; }
/** * Returns the absolute URL to the specified path using the proxy location * specified * @param string $path a path returned from an API call * @return string the URL */ private function getProxiedUrl($path) { // Only use HTTPS if user has explicitly enabled it $scheme = 'http://'; if (Setting::getBoolean('useHttpsForVfsUrls') && Yii::app()->request->isSecureConnection) { $scheme = 'https://'; } // Remove the beginning "vfs/" from the path $path = substr($path, 4); return $scheme . $_SERVER['HTTP_HOST'] . $this->_backend->proxyLocation . '/' . $path; }
/** * Initiates a library update and redirects the user to his previous * location */ public function actionUpdateLibrary() { // Update the library. There will be no indication if success/failure // so we have to assume it worked Yii::app()->xbmc->sendNotification('VideoLibrary.Scan'); Yii::app()->user->setFlash('success', Yii::t('Misc', 'Library update has been initiated')); // Remind users that they'll have to flush their cache if (Setting::getBoolean('cacheApiCalls')) { Yii::app()->user->setFlash('info', Yii::t('Misc', "You'll have to flush the API call cache to see any newly scanned content")); } $this->redirectToPrevious(Yii::app()->homeUrl); }
/** * Encodes the return value of the callable as JavaScript and returns that. * If cacheApiCalls is enabled, the result will be fetched from cache * whenever possible. * @param string $cacheId the cache ID * @param callable $callable a closure that returns the typeahead source * @return string JavaScript encoded string representing the data */ private function getTypeaheadSource($cacheId, callable $callable) { // Bust caches that were made when the data stored was still encoded // with CJavaScript::encode() $cacheId .= '_v2'; // Cache the encoded JavaScript if the "cache API calls" setting is enabled if (Setting::getBoolean('cacheApiCalls')) { $typeaheadData = Yii::app()->apiCallCache->get($cacheId); if ($typeaheadData === false) { $typeaheadData = json_encode($callable()); Yii::app()->apiCallCache->set($cacheId, $typeaheadData); } } else { $typeaheadData = json_encode($callable()); } return $typeaheadData; }
/** * Wrapper for performRequestInternal(). It caches the results indefinitely * if the "cacheApiCalls" setting is enabled. * @param string $method * @param mixed $params * @param integer $id */ public function performRequest($method, $params = null, $id = 0) { if (Setting::getBoolean('cacheApiCalls')) { // Calculate a unique cache ID for this API call to this backend $cacheId = md5(serialize($this->_backend->attributes) . serialize($method) . serialize($params) . serialize($id) . 1); // increment to invalidate all previous caches $result = Yii::app()->apiCallCache->get($cacheId); // Not found in cache if ($result === false) { $result = $this->performRequestUncached($method, $params, $id); // Store the raw response instead of the object Yii::app()->apiCallCache->set($cacheId, $result->getRawResponse()); } else { // Recreate the full object based on the stored JSON $result = new SimpleJsonRpcClient\Response\Response($result); } return $result; } else { return $this->performRequestUncached($method, $params, $id); } }
if ($currentBackend !== null && $currentBackend->id == $backend->id) { $label = TbHtml::icon(TbHtml::ICON_OK) . ' ' . $label; } $backendItems[] = array('label' => $label, 'url' => array('backend/change', 'id' => $backend->id)); } $rightItems[] = array('label' => Yii::t('Menu', 'Change backend'), 'items' => $backendItems, 'linkOptions' => array('class' => 'fa fa-cloud')); } // Add the "Settings" menu for administrators if (Yii::app()->user->role == User::ROLE_ADMIN) { $rightItems[] = array('label' => Yii::t('Menu', 'Settings'), 'items' => array(array('label' => Yii::t('Menu', 'Settings')), array('label' => Yii::t('Menu', 'Manage'), 'url' => array('setting/admin')), array('label' => Yii::t('Menu', 'Backends')), array('label' => Yii::t('Menu', 'Manage'), 'url' => array('backend/admin')), array('label' => Yii::t('Menu', 'Create new'), 'url' => array('backend/create')), array('label' => Yii::t('Menu', 'Users')), array('label' => Yii::t('Menu', 'Manage'), 'url' => array('user/admin')), array('label' => Yii::t('Menu', 'Create new'), 'url' => array('user/create')), array('label' => Yii::t('Menu', 'System log')), array('label' => Yii::t('Menu', 'Browse'), 'url' => array('log/'))), 'linkOptions' => array('class' => 'fa fa-cogs')); } // Add the "Actions" menu $changeLanguageItem = array('label' => Yii::t('Menu', 'Change language'), 'url' => '#', 'linkOptions' => array('data-toggle' => 'modal', 'data-target' => '#change-language-modal')); $actions = array(array('label' => Yii::t('Menu', 'Interface')), $changeLanguageItem, array('label' => Yii::t('Menu', 'System'))); // Only show "Flush cache" if cacheApiCalls is enabled if (Setting::getBoolean('cacheApiCalls')) { $actions[] = array('label' => Yii::t('Menu', 'Flush cache'), 'url' => array('site/flushCache'), 'linkOptions' => array('confirm' => Yii::t('Misc', 'Are you sure you want to flush the cache?'))); } $actions[] = array('label' => Yii::t('Menu', 'Update library'), 'url' => array('backend/updateLibrary'), 'linkOptions' => array('confirm' => Yii::t('Misc', "Are you sure you want to update the backend's library?"))); if (Yii::app()->powerOffManager->getAllowedActions()) { $actions[] = array('label' => Yii::t('Menu', 'Power off'), 'url' => '#', 'linkOptions' => array('data-toggle' => 'modal', 'data-target' => '#power-off-modal')); } // user-related actions $actions = array_merge($actions, array(array('label' => Yii::t('Menu', 'User')), array('label' => Yii::t('Menu', 'Change password'), 'url' => array('user/changePassword')), array('label' => Yii::t('Menu', 'Log out'), 'url' => array('site/logout')))); $rightItems[] = array('label' => Yii::t('Menu', 'Actions'), 'items' => $actions, 'linkOptions' => array('class' => 'fa fa-tasks')); // Completely override the items when the application hasn't been configured yet if (Yii::app()->backendManager->getCurrent() === null) { $leftItems = array(); $rightItems = array(array('label' => Yii::t('Menu', 'Settings'), 'items' => array($changeLanguageItem, array('label' => Yii::t('Menu', 'Backends')), array('label' => Yii::t('Menu', 'Create new'), 'url' => array('backend/create')), array('label' => Yii::t('Menu', 'System log')), array('label' => Yii::t('Menu', 'Browse'), 'url' => array('log/')), array('label' => Yii::t('Menu', 'User')), array('label' => Yii::t('Menu', 'Log out'), 'url' => array('site/logout'))), 'linkOptions' => array('class' => 'fa fa-cogs'))); } // Construct the menu
/** * Adds the specified sort method to the request parameters. The sort * method defaults to "label": * @param array $params the parameters * @param string $sortMethod the sort method to use */ private static function addDefaultSort(&$params, $sortMethod = 'label') { if (!isset($params['sort'])) { $params['sort'] = array('order' => self::SORT_ORDER_ASCENDING, 'ignorearticle' => Setting::getBoolean('ignoreArticle'), 'method' => $sortMethod); } }
/** * Encodes the return value of the callable as JavaScript and returns that. * If cacheApiCalls is enabled, the result will be fetched from cache * whenever possible. * @param string $cacheId the cache ID * @param callable $callable a closure that returns the typeahead source * @return string JavaScript encoded string representing the data */ protected function getTypeaheadSource($cacheId, callable $callable) { // Cache the encoded JavaScript if the "cache API calls" setting is enabled if (Setting::getBoolean('cacheApiCalls')) { $typeaheadData = Yii::app()->apiCallCache->get($cacheId); if ($typeaheadData === false) { $typeaheadData = CJavaScript::encode($callable()); Yii::app()->apiCallCache->set($cacheId, $typeaheadData); } } else { $typeaheadData = CJavaScript::encode($callable()); } return $typeaheadData; }
/** * Triggers a library update over a WebSocket connection and blocks the * request until the update has finished */ public function actionWaitForLibraryUpdate() { $backend = $this->getCurrent(); // Create a library update listener $listener = new LibraryUpdateListener($backend); // Log when the scan was started and finished $listener->onScanStarted = function () use($backend) { $this->log('Library update started on %s', $backend->name); }; $listener->onScanFinished = function () use($backend) { $this->log('Library update finished on %s', $backend->name); }; // Wait for the library update to finish $listener->blockUntil(LibraryUpdateListener::METHOD_ON_SCAN_FINISHED); Yii::app()->user->setFlash('success', Yii::t('Misc', 'Library update completed')); // Flush the cache so potential new content will be available if (Setting::getBoolean('cacheApiCalls')) { Yii::app()->apiCallCache->flush(); } }
<?php // Only use a cached version if there is just one backend configured, otherwise // the cache invalidation gets too complicated if (count(Backend::model()->findAll()) === 1) { $cacheDependency = new CFileCacheDependency(realpath(__DIR__ . '/_navbar.php')); $cacheDuration = 60 * 60 * 24 * 365; if ($this->beginCache('MainMenu', array('dependency' => $cacheDependency, 'duration' => $cacheDuration, 'varyByExpression' => function () { return implode('_', array(Yii::app()->user->role, intval(Setting::getBoolean('cacheApiCalls')), intval(Yii::app()->powerOffManager->getAllowedActions()), intval(Yii::app()->backendManager->getCurrent() === null), Yii::app()->language, Yii::app()->baseUrl)); }))) { $this->renderPartial('//layouts/_navbar'); $this->endCache(); } } else { $this->renderPartial('//layouts/_navbar'); }
/** * Returns the absolute URL to the specified API path * @param string $path a path returned from an API call * @param boolean $omitCredentials whether to omit the XBMC credentials in * the generated URLs * @return string */ public function getAbsoluteVfsUrl($path, $omitCredentials = false) { $backend = Yii::app()->backendManager->getCurrent(); // Use reverse proxy for vfs:// paths (if specified) $proxyLocation = $backend->proxyLocation; if (!empty($proxyLocation) && substr($path, 0, 3) === 'vfs') { // Only use HTTPS if user has explicitly enabled it $scheme = 'http://'; if (Setting::getBoolean('useHttpsForVfsUrls') && Yii::app()->request->isSecureConnection) { $scheme = 'https://'; } // Remove the beginning "vfs/" from the path $path = substr($path, 4); return $scheme . $_SERVER['HTTP_HOST'] . $proxyLocation . '/' . $path; } else { $url = 'http://{credentials}' . Backend::normalizeAddress($backend->hostname) . ':' . $backend->port . '/' . $path; if ($omitCredentials) { $url = str_replace('{credentials}', '', $url); } else { $url = str_replace('{credentials}', $backend->username . ':' . $backend->password . '@', $url); } return $url; } }