PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/youtube/library/X/VlcShares/Plugins/Youtube.php

http://vlc-shares.googlecode.com/
PHP | 1145 lines | 755 code | 215 blank | 175 comment | 132 complexity | 0db32e04b382045d054cdb7bebccdcc0 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. require_once 'X/VlcShares/Plugins/Abstract.php';
  3. require_once 'Zend/Dom/Query.php';
  4. require_once 'Zend/Gdata/YouTube.php';
  5. require_once 'Zend/Gdata/YouTube/VideoEntry.php';
  6. /**
  7. * Add youtube site as a video source
  8. * @author ximarx
  9. *
  10. */
  11. class X_VlcShares_Plugins_Youtube extends X_VlcShares_Plugins_Abstract implements X_VlcShares_Plugins_ResolverInterface, X_VlcShares_Plugins_BackuppableInterface {
  12. const VERSION = '0.2.1';
  13. const VERSION_CLEAN = '0.2.1';
  14. const MODE_LIBRARY = "l";
  15. const MODE_ACCOUNTS = "a";
  16. const A_UPLOADED = 'aup';
  17. const A_SUBSCRIPTIONS = 'ass';
  18. const A_FAVORITES = 'afa';
  19. const A_ACTIVITIES = 'aac';
  20. const A_PLAYLISTS = 'apl';
  21. public function __construct() {
  22. $this->setPriority('gen_beforeInit')
  23. ->setPriority('getCollectionsItems')
  24. ->setPriority('preRegisterVlcArgs')
  25. ->setPriority('getShareItems')
  26. ->setPriority('preGetModeItems')
  27. ->setPriority('getModeItems')
  28. ->setPriority('preGetSelectionItems')
  29. ->setPriority('getSelectionItems')
  30. ->setPriority('registerVlcArgs')
  31. ->setPriority('getIndexManageLinks')
  32. ->setPriority('getIndexMessages')
  33. ->setPriority('getTestItems');
  34. }
  35. //========================
  36. // API TRIGGERS
  37. //========================
  38. /**
  39. * Inizialize translator for this plugin
  40. * @param Zend_Controller_Action $controller
  41. */
  42. function gen_beforeInit(Zend_Controller_Action $controller) {
  43. $this->helpers()->language()->addTranslation(__CLASS__);
  44. $this->helpers()->registerHelper('youtube', new X_VlcShares_Plugins_Helper_Youtube());
  45. $this->helpers()->hoster()->registerHoster(new X_VlcShares_Plugins_Helper_Hoster_Youtube());
  46. }
  47. /**
  48. * Add the main link for youtube library
  49. * @param Zend_Controller_Action $controller
  50. */
  51. public function getCollectionsItems(Zend_Controller_Action $controller) {
  52. X_Debug::i("Plugin triggered");
  53. $link = new X_Page_Item_PItem($this->getId(), X_Env::_('p_youtube_collectionindex'));
  54. $link->setIcon('/images/youtube/logo.png')
  55. ->setDescription(X_Env::_('p_youtube_collectionindex_desc'))
  56. ->setType(X_Page_Item_PItem::TYPE_CONTAINER)
  57. ->setLink(
  58. array(
  59. 'controller' => 'browse',
  60. 'action' => 'share',
  61. 'p' => $this->getId(),
  62. ), 'default', true
  63. );
  64. return new X_Page_ItemList_PItem(array($link));
  65. }
  66. /**
  67. * Get item list
  68. * @param unknown_type $provider
  69. * @param unknown_type $location
  70. * @param Zend_Controller_Action $controller
  71. */
  72. public function getShareItems($provider, $location, Zend_Controller_Action $controller) {
  73. // this plugin add items only if it is the provider
  74. if ( $provider != $this->getId() ) return;
  75. X_Debug::i("Plugin triggered");
  76. $urlHelper = $controller->getHelper('url');
  77. $items = new X_Page_ItemList_PItem();
  78. //try to disable SortItems plugin, so link are listed as in html page
  79. X_VlcShares_Plugins::broker()->unregisterPluginClass('X_VlcShares_Plugins_SortItems');
  80. X_Debug::i("Requested location: $location");
  81. $exploded = $location != '' ? explode('/', $location) : array(null, null, null, null);
  82. @list($mode, $submode, $page, $id) = $exploded;
  83. if ( $page !== null && $page > 0 ) {
  84. // need to insert a back one page button as first here
  85. $items->append($this->back($mode, $submode, $page, $id));
  86. }
  87. switch ($mode) {
  88. // accounts
  89. case self::A_UPLOADED:
  90. $this->uploadedMenu($items, $submode, $page);
  91. break;
  92. case self::A_SUBSCRIPTIONS:
  93. $this->subscriptionsMenu($items, $submode, $page);
  94. break;
  95. case self::A_PLAYLISTS:
  96. $this->playlistsMenu($items, $submode, $page);
  97. break;
  98. case self::A_FAVORITES:
  99. $this->favoritesMenu($items, $submode, $page);
  100. break;
  101. case self::A_ACTIVITIES:
  102. $this->activitiesMenu($items, $submode, $page);
  103. break;
  104. case self::MODE_ACCOUNTS:
  105. $this->accountsMenu($items, $submode);
  106. break;
  107. // library
  108. case self::MODE_LIBRARY:
  109. $this->libraryMenu($items, $submode);
  110. break;
  111. default:
  112. $this->mainMenu($items);
  113. break;
  114. }
  115. return $items;
  116. }
  117. /**
  118. * Add button -watch youtube stream directly-
  119. *
  120. * @param string $provider
  121. * @param string $location
  122. * @param Zend_Controller_Action $controller
  123. */
  124. public function preGetModeItems($provider, $location, Zend_Controller_Action $controller) {
  125. if ( $provider != $this->getId()) return;
  126. X_Debug::i("Plugin triggered");
  127. // i have to remove default sub provider
  128. // and install the newer one in getModeItems
  129. X_VlcShares_Plugins::broker()->unregisterPluginClass('X_VlcShares_Plugins_FileSubs');
  130. $url = $this->resolveLocation($location);
  131. if ( $url ) {
  132. // i have to check for rtsp videos, wiimc can't handle them
  133. if ( X_Env::startWith($url, 'rtsp') && $this->helpers()->devices()->isWiimc() ) {
  134. return;
  135. }
  136. $link = new X_Page_Item_PItem('core-directwatch', X_Env::_('p_youtube_watchdirectly'));
  137. $link->setIcon('/images/icons/play.png')
  138. ->setType(X_Page_Item_PItem::TYPE_PLAYABLE)
  139. ->setLink($url);
  140. // add tag wiimcplus_subtitle for subtitle in direct watching
  141. if ( $this->config('closedcaption.enabled', true ) ) {
  142. /* @var $request Zend_Controller_Request_Http */
  143. $request = $controller->getRequest();
  144. $sub = false;
  145. $lc = $request->getParam($this->getId().':sub', false);
  146. if ( $lc !== false ) {
  147. @list(, , , $videoId) = explode('/', $location);
  148. $sub = array(
  149. 'controller' => 'youtube',
  150. 'action' => 'convert',
  151. 'v' => $videoId,
  152. 'l' => $lc,
  153. 'f' => 'file.srt',
  154. );
  155. }
  156. /* @var $urlHelper Zend_Controller_Action_Helper_Url */
  157. $urlHelper = $controller->getHelper('url');
  158. if ( $sub !== false ) {
  159. $link->setCustom('subtitle', X_Env::completeUrl($urlHelper->url($sub, 'default', true)));
  160. X_Debug::i("CC-XML to SRT Url: ".X_Env::completeUrl($urlHelper->url($sub, 'default', true)));
  161. }
  162. }
  163. @list(, , , $videoId) = explode('/', $location);
  164. $link2 = new X_Page_Item_PItem('core-directwatch', "Watch throught WIIMC");
  165. $link2->setIcon('/images/icons/play.png')
  166. ->setType(X_Page_Item_PItem::TYPE_PLAYABLE)
  167. ->setLink("http://www.youtube.com/watch?v={$videoId}");
  168. return new X_Page_ItemList_PItem(array($link, $link2));
  169. } else {
  170. // if there is no link, i have to remove start-vlc button
  171. // and replace it with a Warning button
  172. X_Debug::i('Setting priority to filterModeItems');
  173. $this->setPriority('filterModeItems', 99);
  174. $link = new X_Page_Item_PItem('youtube-warning', X_Env::_('p_youtube_invalidyoutube'));
  175. $link->setIcon('/images/msg_error.png')
  176. ->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  177. ->setLink(array (
  178. 'controller' => 'browse',
  179. 'action' => 'share',
  180. 'p' => $this->getId(),
  181. 'l' => X_Env::encode($this->getParentLocation($location)),
  182. ), 'default', true);
  183. return new X_Page_ItemList_PItem(array($link));
  184. }
  185. }
  186. /**
  187. * Add the link for closed caption language change
  188. *
  189. * @param string $provider
  190. * @param string $location
  191. * @param Zend_Controller_Action $controller
  192. * @return X_Page_ItemList_PItem
  193. */
  194. public function getModeItems($provider, $location, Zend_Controller_Action $controller) {
  195. if ( $provider != $this->getId() ) return;
  196. if ( $this->config('closedcaption.enabled', true ) ) {
  197. X_Debug::i('Plugin triggered');
  198. $urlHelper = $controller->getHelper('url');
  199. $subLabel = X_Env::_('p_youtube_subselection_none');
  200. $subParam = $controller->getRequest()->getParam($this->getId().':sub', false);
  201. if ( $subParam !== false ) {
  202. $subParam = X_Env::decode($subParam);
  203. //list($type, $source) = explode(':', $subParam, 2);
  204. $subLabel = X_Env::_("p_youtube_langcode_$subParam");
  205. if ( $subLabel == "p_youtube_langcode_$subParam" ) {
  206. $subLabel = $subParam;
  207. }
  208. }
  209. $link = new X_Page_Item_PItem($this->getId(), X_Env::_('p_youtube_subselected').": $subLabel");
  210. $link->setIcon('/images/youtube/closedcaption.png')
  211. ->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  212. ->setLink(array(
  213. 'action' => 'selection',
  214. 'pid' => $this->getId()
  215. ), 'default', false);
  216. return new X_Page_ItemList_PItem(array($link));
  217. }
  218. }
  219. /**
  220. * Remove vlc-play button if location is invalid
  221. * @param X_Page_Item_PItem $item,
  222. * @param string $provider
  223. * @param Zend_Controller_Action $controller
  224. */
  225. public function filterModeItems(X_Page_Item_PItem $item, $provider,Zend_Controller_Action $controller) {
  226. X_Debug::i('plugin triggered');
  227. if ( $item->getKey() == 'core-play') {
  228. X_Debug::w('core-play flagged as invalid because youtube link is invalid');
  229. return false;
  230. }
  231. }
  232. /**
  233. * Set the header of selection page if needed
  234. * @param string $provider
  235. * @param string $location
  236. * @param string $pid
  237. * @param Zend_Controller_Action $controller
  238. * @return X_Page_ItemList_PItem
  239. */
  240. public function preGetSelectionItems($provider, $location, $pid, Zend_Controller_Action $controller) {
  241. // we want to expose items only if pid is this plugin and provider is this plugin
  242. if ( $this->getId() != $pid || $this->getId() != $provider ) return;
  243. X_Debug::i('Plugin triggered');
  244. $urlHelper = $controller->getHelper('url');
  245. $link = new X_Page_Item_PItem($this->getId().'-header', X_Env::_('p_youtube_subselection_title'));
  246. $link->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  247. ->setLink(X_Env::completeUrl($urlHelper->url()));
  248. return new X_Page_ItemList_PItem();
  249. }
  250. /**
  251. * Show a list of valid subs for the selected location
  252. * @param string $provider
  253. * @param string $location
  254. * @param string $pid
  255. * @param Zend_Controller_Action $controller
  256. * @return X_Page_ItemList_PItem
  257. */
  258. public function getSelectionItems($provider, $location, $pid, Zend_Controller_Action $controller) {
  259. // we want to expose items only if pid is this plugin
  260. if ( $this->getId() != $pid || $this->getId() != $provider ) return;
  261. X_Debug::i('Plugin triggered');
  262. $urlHelper = $controller->getHelper('url');
  263. // i try to mark current selected sub based on $this->getId() param
  264. // in $currentSub i get the name of the current profile
  265. $currentSub = $controller->getRequest()->getParam($this->getId().':sub', false);
  266. if ( $currentSub !== false ) $currentSub = X_Env::decode($currentSub);
  267. $return = new X_Page_ItemList_PItem();
  268. $item = new X_Page_Item_PItem($this->getId().'-none', X_Env::_('p_youtube_subselection_none'));
  269. $item->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  270. ->setLink(array(
  271. 'action' => 'mode',
  272. $this->getId().':sub' => null, // unset this plugin selection
  273. 'pid' => null
  274. ), 'default', false)
  275. ->setHighlight($currentSub === false);
  276. $return->append($item);
  277. // check if infile support is enabled
  278. // by default infile.enabled is true
  279. if ( $this->config('closedcaption.enabled', true ) ) {
  280. // check for closed captions
  281. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  282. $helper = $this->helpers('youtube');
  283. @list(, , , $videoId) = explode('/', $location);
  284. $subs = $helper->getSubtitlesNOAPI($videoId);
  285. //X_Debug::i(var_export($infileSubs, true));
  286. foreach ($subs as $lc => $sub) {
  287. X_Debug::i("Valid ccaption-sub: [{$lc}] {$sub['name']} ({$sub['lang_translated']})");
  288. $subLabel = X_Env::_("p_youtube_langcode_$lc");
  289. if ( $subLabel == "p_youtube_langcode_$lc" ) {
  290. $subLabel = $lc;
  291. }
  292. if ( $sub['name'] != '' ) $subLabel .= ' ['.$sub['name'].']';
  293. $item = new X_Page_Item_PItem($this->getId().'-'.$sub['id'], $subLabel);
  294. $item->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  295. ->setCustom(__CLASS__.':sub', $lc)
  296. ->setLink(array(
  297. 'action' => 'mode',
  298. 'pid' => null,
  299. $this->getId().':sub' => X_Env::encode($lc) // set this plugin selection as stream:$streamId
  300. ), 'default', false)
  301. ->setHighlight($currentSub == $lc);
  302. $return->append($item);
  303. }
  304. }
  305. return $return;
  306. }
  307. private $cachedLocation = array();
  308. public function resolveLocation($location = null) {
  309. if ( $location == null || $location == false || $location == '') return false;
  310. if ( array_key_exists($location, $this->cachedLocation) && array_key_exists('url', $this->cachedLocation[$location]) ) {
  311. return $this->cachedLocation[$location]['url'];
  312. } else {
  313. $exploded = $location != '' ? explode('/', $location) : array(null, null, null, null);
  314. @list($mode, $submode, $page, $id) = $exploded;
  315. // prepare cache info
  316. $toBeCached = array();
  317. if ( array_key_exists($location, $this->cachedLocation) ) {
  318. $toBeCached = $this->cachedLocation[$location];
  319. }
  320. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  321. $helper = $this->helpers('youtube');
  322. /* @var $foundVideo Zend_Gdata_YouTube_VideoEntry */
  323. $foundVideo = false;
  324. try {
  325. switch ( $mode ) {
  326. case self::MODE_ACCOUNTS:
  327. case self::A_ACTIVITIES:
  328. case self::A_FAVORITES:
  329. case self::A_PLAYLISTS:
  330. case self::A_SUBSCRIPTIONS:
  331. case self::A_UPLOADED:
  332. if ( $id !== null ) {
  333. // the youtube video url is inside the id
  334. //$foundVideo = $helper->getVideo($id);
  335. $foundVideo = $id;
  336. }
  337. break;
  338. case self::MODE_LIBRARY:
  339. if ( $id !== null ) {
  340. $video = new Application_Model_YoutubeVideo();
  341. Application_Model_YoutubeVideosMapper::i()->find($id, $video);
  342. if ( $video->getId() != null ) {
  343. //$foundVideo = $helper->getVideo($video->getIdYoutube());
  344. $foundVideo = $video->getIdYoutube();
  345. }
  346. }
  347. break;
  348. }
  349. } catch ( Exception $e) {
  350. // WTF: video query is invalid!!!
  351. X_Debug::e('Error in video query: '.$e->getMessage());
  352. return false;
  353. }
  354. //X_Debug::i("Video debug info: ". print_r($helper->getVideo($foundVideo), true));
  355. if ( $foundVideo !== false && $foundVideo !== null) {
  356. //$content = $foundVideo->getMediaGroup()->getContent();
  357. //print_r($foundVideo);
  358. //$content = $content[0];
  359. /* @var $content Zend_Gdata_YouTube_Extension_MediaContent */
  360. $formats = $helper->getFormatsNOAPI($foundVideo/*->getVideoId()*/);
  361. $returned = null;
  362. $qualityPriority = explode('|', $this->config('quality.priority', '5|34|18|35'));
  363. foreach ($qualityPriority as $quality) {
  364. if ( array_key_exists($quality, $formats)) {
  365. $returned = $formats[$quality];
  366. X_Debug::i('Video format selected: '.$quality);
  367. break;
  368. }
  369. }
  370. if ( $returned === null ) {
  371. // for valid video id but video with restrictions
  372. // alternatives formats can't be fetched by youtube page.
  373. // i have to fallback to standard api url
  374. X_Debug::i("Getting video url from standard api");
  375. $apiVideo = $helper->getVideo($foundVideo);
  376. foreach ($apiVideo->mediaGroup->content as $content) {
  377. if ($content->type === "video/3gpp") {
  378. $returned = $content->url;
  379. X_Debug::w('Content restricted video, fallback to api url:'.$returned);
  380. break;
  381. }
  382. }
  383. if ( $returned === null ) {
  384. X_Debug::e("No video link found in api too");
  385. $returned = false;
  386. }
  387. }
  388. $toBeCached['url'] = $returned;
  389. $this->cachedLocation[$location] = $toBeCached;
  390. return $returned;
  391. }
  392. }
  393. }
  394. /**
  395. * This hook can be used to add low priority args in vlc stack
  396. *
  397. * @param X_Vlc $vlc vlc wrapper object
  398. * @param string $provider id of the plugin that should handle request
  399. * @param string $location to stream
  400. * @param Zend_Controller_Action $controller the controller who handle the request
  401. */
  402. public function preRegisterVlcArgs(X_Vlc $vlc, $provider, $location, Zend_Controller_Action $controller) {
  403. // this plugin inject params only if this is the provider
  404. if ( $provider != $this->getId() ) return;
  405. // i need to register source as first, because subtitles plugin use source
  406. // for create subfile
  407. X_Debug::i('Plugin triggered');
  408. $dLocation = $this->resolveLocation($location);
  409. if ( $location !== null ) {
  410. // TODO adapt to newer api when ready
  411. $vlc->registerArg('source', "\"$dLocation\"");
  412. } else {
  413. X_Debug::e("No source o_O");
  414. return;
  415. }
  416. // Now, it's time to check for sub parameter
  417. $request = $controller->getRequest();
  418. $sub = $request->getParam($this->getId().':sub', false);
  419. if ( $sub !== false ) {
  420. $sub = X_Env::decode($sub);
  421. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  422. $helper = $this->helpers('youtube');
  423. list(, , , $videoId) = explode('/', $location);
  424. $sub = $helper->getSubtitleNOAPI($videoId, $sub);
  425. $urlHelper = $controller->getHelper('url');
  426. $subFile = X_Env::completeUrl($urlHelper->url($sub['srt_url'],'default', true));
  427. $vlc->registerArg('subtitles', "--sub-file=\"{$subFile}\"");
  428. }
  429. }
  430. /**
  431. * Add the link for -manage-megavideo-
  432. * @param Zend_Controller_Action $this
  433. * @return X_Page_ItemList_ManageLink
  434. */
  435. public function getIndexManageLinks(Zend_Controller_Action $controller) {
  436. $link = new X_Page_Item_ManageLink($this->getId(), X_Env::_('p_youtube_mlink'));
  437. $link->setTitle(X_Env::_('p_youtube_managetitle'))
  438. ->setIcon('/images/youtube/logo.png')
  439. ->setLink(array(
  440. 'controller' => 'youtube',
  441. 'action' => 'index',
  442. ), 'default', true);
  443. return new X_Page_ItemList_ManageLink(array($link));
  444. }
  445. public function getParentLocation($location = null) {
  446. //return false;
  447. @list($mode, $submode, $page, $videoId) = explode('/', $location);
  448. if ( $videoId != null ) {
  449. return implode('/', array($mode, $submode, $page));
  450. }
  451. if ( $page != null && $page > 0 ) {
  452. // need to be insered the back one page button
  453. //return implode('/', array($mode, $submode, $page - 1 ));
  454. // mayve we should revert to $mode, $submode only
  455. }
  456. switch ($mode) {
  457. case self::MODE_LIBRARY:
  458. case self::MODE_ACCOUNTS:
  459. return $submode ? $mode : null;
  460. case self::A_ACTIVITIES:
  461. case self::A_FAVORITES:
  462. case self::A_PLAYLISTS:
  463. case self::A_SUBSCRIPTIONS:
  464. case self::A_UPLOADED:
  465. if ( $submode ) {
  466. $exploded = explode(',', $submode);
  467. //X_Debug::i(print_r($exploded, true));
  468. if ( count($exploded) >= 2 ) {
  469. array_pop($exploded);
  470. return implode('/', array($mode,implode(',', $exploded)));
  471. } else {
  472. return implode('/', array(self::MODE_ACCOUNTS,implode(',', $exploded)));
  473. }
  474. } else {
  475. return null;
  476. }
  477. default:
  478. return false;
  479. }
  480. }
  481. function getBackupItems() {
  482. $return = array('videos' => array(), 'accounts' => array(), 'categories' => array());
  483. $videos = Application_Model_YoutubeVideosMapper::i()->fetchAll();
  484. foreach ($videos as $model) {
  485. /* @var $model Application_Model_YoutubeVideo */
  486. $return['videos']['video-'.$model->getId()] = array(
  487. 'id' => $model->getId(),
  488. 'idYoutube' => $model->getIdYoutube(),
  489. 'description' => $model->getDescription(),
  490. 'idCategory' => $model->getIdCategory(),
  491. 'label' => $model->getLabel(),
  492. 'thumbnail' => $model->getThumbnail()
  493. );
  494. }
  495. $categories = Application_Model_YoutubeCategoriesMapper::i()->fetchAll();
  496. foreach ($categories as $model) {
  497. /* @var $model Application_Model_YoutubeCategory */
  498. $return['categories']['category-'.$model->getId()] = array(
  499. 'id' => $model->getId(),
  500. 'label' => $model->getLabel(),
  501. 'thumbnail' => $model->getThumbnail()
  502. );
  503. }
  504. $accounts = Application_Model_YoutubeAccountsMapper::i()->fetchAll();
  505. foreach ($accounts as $model) {
  506. /* @var $model Application_Model_YoutubeAccount */
  507. $return['accounts']['account-'.$model->getId()] = array(
  508. 'id' => $model->getId(),
  509. 'label' => $model->getLabel(),
  510. 'thumbnail' => $model->getThumbnail()
  511. );
  512. }
  513. return $return;
  514. }
  515. /**
  516. * Restore backupped videos
  517. * This is not a trigger of plugin API. It's called by Backupper plugin
  518. */
  519. function restoreItems($items) {
  520. //return parent::restoreItems($items);
  521. // cleaning up all videos
  522. $models = Application_Model_YoutubeVideosMapper::i()->fetchAll();
  523. foreach ($models as $model) {
  524. Application_Model_YoutubeVideosMapper::i()->delete($model);
  525. }
  526. // cleaning up all categories
  527. $models = Application_Model_YoutubeCategoriesMapper::i()->fetchAll();
  528. foreach ($models as $model) {
  529. Application_Model_YoutubeCategoriesMapper::i()->delete($model);
  530. }
  531. // cleaning up all accounts
  532. $models = Application_Model_YoutubeAccountsMapper::i()->fetchAll();
  533. foreach ($models as $model) {
  534. Application_Model_YoutubeAccountsMapper::i()->delete($model);
  535. }
  536. $mapOldNewCategoryId = array();
  537. foreach (@$items['categories'] as $modelInfo) {
  538. $model = new Application_Model_YoutubeCategory();
  539. $model->setLabel(@$modelInfo['label'])
  540. ->setThumbnail(@$modelInfo['thumbnail'] != '' ? @$modelInfo['thumbnail'] : null)
  541. ;
  542. // i don't set id, or db adapter will try to update old data that i cleaned
  543. Application_Model_YoutubeCategoriesMapper::i()->save($model);
  544. $mapOldNewCategoryId[@$modelInfo['id']] = $model->getId();
  545. }
  546. foreach (@$items['videos'] as $modelInfo) {
  547. $model = new Application_Model_YoutubeVideo();
  548. $model->setIdYoutube(@$modelInfo['idYoutube'])
  549. ->setDescription(@$modelInfo['description'])
  550. ->setIdCategory(@$mapOldNewCategoryId[$modelInfo['idCategory']])
  551. ->setLabel(@$modelInfo['label'])
  552. ->setThumbnail(@$modelInfo['thumbnail'] != '' ? @$modelInfo['thumbnail'] : null)
  553. ;
  554. // i don't set id, or db adapter will try to update old data that i cleaned
  555. Application_Model_YoutubeVideosMapper::i()->save($model);
  556. }
  557. foreach (@$items['accounts'] as $modelInfo) {
  558. $model = new Application_Model_YoutubeAccount();
  559. $model->setLabel(@$modelInfo['label'])
  560. ->setThumbnail(@$modelInfo['thumbnail'] != '' ? @$modelInfo['thumbnail'] : null)
  561. ;
  562. // i don't set id, or db adapter will try to update old data that i cleaned
  563. Application_Model_YoutubeAccountsMapper::i()->save($model);
  564. }
  565. return implode('<br/>',array(
  566. X_Env::_('p_youtube_backupper_restoredcategories'). ": " .count($items['categories']),
  567. X_Env::_('p_youtube_backupper_restoredvideos'). ": " .count($items['videos']),
  568. X_Env::_('p_youtube_backupper_restoredaccounts'). ": " .count($items['accounts'])
  569. ));
  570. }
  571. //========================
  572. // MENUS
  573. //========================
  574. protected function mainMenu(X_Page_ItemList_PItem $items) {
  575. // disabling cache plugin
  576. try {
  577. $cachePlugin = X_VlcShares_Plugins::broker()->getPlugins('cache');
  578. if ( method_exists($cachePlugin, 'setDoNotCache') ) {
  579. $cachePlugin->setDoNotCache();
  580. }
  581. } catch (Exception $e) {
  582. // cache plugin not registered, no problem
  583. }
  584. $item = new X_Page_Item_PItem('youtube-accounts', X_Env::_('p_youtube_br_mainmenu_accounts'));
  585. $item->setDescription(X_Env::_('p_youtube_br_mainmenu_accounts_desc'))
  586. ->setIcon('/images/youtube/icons/accounts.png')
  587. ->setLink(array(
  588. 'l' => X_Env::encode(self::MODE_ACCOUNTS)
  589. ), 'default', false)
  590. ->setGenerator(__CLASS__);
  591. $items->append($item);
  592. $item = new X_Page_Item_PItem('youtube-library', X_Env::_('p_youtube_br_mainmenu_library'));
  593. $item->setDescription(X_Env::_('p_youtube_br_mainmenu_library_desc'))
  594. ->setIcon('/images/youtube/icons/library.png')
  595. ->setLink(array(
  596. 'l' => X_Env::encode(self::MODE_LIBRARY)
  597. ), 'default', false)
  598. ->setGenerator(__CLASS__);
  599. $items->append($item);
  600. }
  601. protected function accountsMenu(X_Page_ItemList_PItem $items, $accountId = null) {
  602. // disabling cache plugin
  603. try {
  604. $cachePlugin = X_VlcShares_Plugins::broker()->getPlugins('cache');
  605. if ( method_exists($cachePlugin, 'setDoNotCache') ) {
  606. $cachePlugin->setDoNotCache();
  607. }
  608. } catch (Exception $e) {
  609. // cache plugin not registered, no problem
  610. }
  611. if ( $accountId != null ) {
  612. $account = new Application_Model_YoutubeAccount();
  613. Application_Model_YoutubeAccountsMapper::i()->find($accountId, $account);
  614. if ( $account->getId() != null ) {
  615. $item = new X_Page_Item_PItem('youtube-a-uploaded', X_Env::_('p_youtube_account_uploaded'));
  616. $item->setDescription(X_Env::_('p_youtube_account_uploaded_desc'))
  617. ->setIcon('/images/youtube/icons/uploaded.png')
  618. ->setCustom(__CLASS__.':location', self::A_UPLOADED.'/'.$account->getId())
  619. ->setLink(array(
  620. 'l' => X_Env::encode(self::A_UPLOADED.'/'.$account->getId())
  621. ), 'default', false)
  622. ->setGenerator(__CLASS__);
  623. $items->append($item);
  624. $item = new X_Page_Item_PItem('youtube-a-favorites', X_Env::_('p_youtube_account_favorites'));
  625. $item->setDescription(X_Env::_('p_youtube_account_favorites_desc'))
  626. ->setIcon('/images/youtube/icons/favorites.png')
  627. ->setCustom(__CLASS__.':location', self::A_FAVORITES.'/'.$account->getId())
  628. ->setLink(array(
  629. 'l' => X_Env::encode(self::A_FAVORITES.'/'.$account->getId())
  630. ), 'default', false)
  631. ->setGenerator(__CLASS__);
  632. $items->append($item);
  633. $item = new X_Page_Item_PItem('youtube-a-subscriptions', X_Env::_('p_youtube_account_subscriptions'));
  634. $item->setDescription(X_Env::_('p_youtube_account_subscriptions_desc'))
  635. ->setIcon('/images/youtube/icons/subscriptions.png')
  636. ->setCustom(__CLASS__.':location', self::A_SUBSCRIPTIONS.'/'.$account->getId())
  637. ->setLink(array(
  638. 'l' => X_Env::encode(self::A_SUBSCRIPTIONS.'/'.$account->getId())
  639. ), 'default', false)
  640. ->setGenerator(__CLASS__);
  641. $items->append($item);
  642. $item = new X_Page_Item_PItem('youtube-a-activities', X_Env::_('p_youtube_account_activities'));
  643. $item->setDescription(X_Env::_('p_youtube_account_activities_desc'))
  644. ->setIcon('/images/youtube/icons/activities.png')
  645. ->setCustom(__CLASS__.':location', self::A_ACTIVITIES.'/'.$account->getId())
  646. ->setLink(array(
  647. 'l' => X_Env::encode(self::A_ACTIVITIES.'/'.$account->getId())
  648. ), 'default', false)
  649. ->setGenerator(__CLASS__);
  650. $items->append($item);
  651. $item = new X_Page_Item_PItem('youtube-a-playlists', X_Env::_('p_youtube_account_playlists'));
  652. $item->setDescription(X_Env::_('p_youtube_account_playlists_desc'))
  653. ->setIcon('/images/youtube/icons/playlists.png')
  654. ->setCustom(__CLASS__.':location', self::A_PLAYLISTS.'/'.$account->getId())
  655. ->setLink(array(
  656. 'l' => X_Env::encode(self::A_PLAYLISTS.'/'.$account->getId())
  657. ), 'default', false)
  658. ->setGenerator(__CLASS__);
  659. $items->append($item);
  660. } else {
  661. $this->accountsMenu($items, null);
  662. }
  663. } else {
  664. $accounts = Application_Model_YoutubeAccountsMapper::i()->fetchAll();
  665. foreach ($accounts as $account) {
  666. /* @var $account Application_Model_YoutubeAccount */
  667. $item = new X_Page_Item_PItem('youtube-accounts-'.$account->getId(), $account->getLabel());
  668. $item//->setDescription(X_Env::_('p_youtube_account_friends_desc'))
  669. ->setIcon('/images/youtube/icons/account.png')
  670. ->setCustom(__CLASS__.':location', self::MODE_ACCOUNTS.'/'.$account->getId())
  671. ->setLink(array(
  672. 'l' => X_Env::encode(self::MODE_ACCOUNTS.'/'.$account->getId())
  673. ), 'default', false)
  674. ->setGenerator(__CLASS__);
  675. $items->append($item);
  676. }
  677. }
  678. }
  679. protected function uploadedMenu(X_Page_ItemList_PItem $items, $accountId, $page = 0 ) {
  680. if ( $accountId != null ) {
  681. $account = new Application_Model_YoutubeAccount();
  682. Application_Model_YoutubeAccountsMapper::i()->find($accountId, $account);
  683. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  684. $helper = $this->helpers('youtube');
  685. $feed = $helper->getVideosByUser($account->getLabel(), $page);
  686. $this->_prepareVideo($items, $feed, self::A_UPLOADED."/$accountId/$page");
  687. } else {
  688. $this->accountsMenu($items);
  689. }
  690. }
  691. protected function favoritesMenu(X_Page_ItemList_PItem $items, $accountId, $page = 0 ) {
  692. if ( $accountId != null ) {
  693. $account = new Application_Model_YoutubeAccount();
  694. Application_Model_YoutubeAccountsMapper::i()->find($accountId, $account);
  695. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  696. $helper = $this->helpers('youtube');
  697. $feed = $helper->getFavoritesByUser($account->getLabel(), $page);
  698. $this->_prepareVideo($items, $feed, self::A_FAVORITES."/$accountId/$page");
  699. if ( $feed->getNextLink() != null ) {
  700. $items->append($this->next(self::A_FAVORITES."/$accountId", $page + 1));
  701. }
  702. } else {
  703. $this->accountsMenu($items);
  704. }
  705. }
  706. protected function subscriptionsMenu(X_Page_ItemList_PItem $items, $mode = null, $page = 0 ) {
  707. // $mode has a format:
  708. // $accountId,$subscriptionname
  709. @list($accountId, $subscription) = explode(',', $mode, 2);
  710. if ( $accountId != null ) {
  711. $account = new Application_Model_YoutubeAccount();
  712. Application_Model_YoutubeAccountsMapper::i()->find($accountId, $account);
  713. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  714. $helper = $this->helpers('youtube');
  715. // i already have a subscription, so load uploaded video by subscription
  716. if ( $subscription != null ) {
  717. /* @var $feed Zend_Gdata_YouTube_VideoFeed */
  718. $feed = $helper->getVideosByUser($subscription, $page);
  719. $this->_prepareVideo($items, $feed, self::A_SUBSCRIPTIONS."/$accountId,$subscription/$page");
  720. if ( $feed->getNextLink() != null ) {
  721. $items->append($this->next(self::A_SUBSCRIPTIONS."/$accountId,$subscription", $page + 1));
  722. }
  723. } else {
  724. // i have to read all subscriptions
  725. $subscriptions = $helper->getSubscriptionsByUser($account->getLabel(), $page);
  726. foreach ($subscriptions as $sub) {
  727. /* @var $sub Zend_Gdata_YouTube_SubscriptionEntry */
  728. $un = $sub->getUsername();
  729. $item = new X_Page_Item_PItem('youtube-acc-subscriptions-'.$un, $sub->getTitle());
  730. $item->setDescription($sub->getSummary())
  731. ->setThumbnail($sub->getMediaThumbnail())
  732. ->setIcon('/images/youtube/icons/subscription.png')
  733. ->setCustom(__CLASS__.':location', self::A_SUBSCRIPTIONS."/$accountId,$un")
  734. ->setLink(array(
  735. 'l' => X_Env::encode(self::A_SUBSCRIPTIONS."/$accountId,$un")
  736. ), 'default', false)
  737. ->setGenerator(__CLASS__);
  738. $items->append($item);
  739. }
  740. if ( $subscriptions->getNextLink() != null ) {
  741. $items->append($this->next(self::A_SUBSCRIPTIONS."/$accountId", $page + 1));
  742. }
  743. }
  744. } else {
  745. $this->accountsMenu($items);
  746. }
  747. }
  748. protected function playlistsMenu(X_Page_ItemList_PItem $items, $mode = null, $page = 0 ) {
  749. // $mode has a format:
  750. // $accountId,$subscriptionname
  751. @list($accountId, $playlist) = explode(',', $mode, 2);
  752. if ( $accountId != null ) {
  753. $account = new Application_Model_YoutubeAccount();
  754. Application_Model_YoutubeAccountsMapper::i()->find($accountId, $account);
  755. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  756. $helper = $this->helpers('youtube');
  757. // i already have a subscription, so load uploaded video by subscription
  758. if ( $playlist != null ) {
  759. /* @var $feed Zend_Gdata_YouTube_VideoFeed */
  760. $feed = $helper->getVideosByPlaylist($playlist, $page);
  761. $this->_prepareVideo($items, $feed, self::A_PLAYLISTS."/$accountId,$playlist/$page");
  762. if ( $feed->getNextLink() != null ) {
  763. $items->append($this->next(self::A_PLAYLISTS."/$accountId,$playlist", $page + 1));
  764. }
  765. } else {
  766. // i have to read all subscriptions
  767. $playlists = $helper->getPlaylistsByUser($account->getLabel(), $page);
  768. foreach ($playlists as $pl) {
  769. /* @var $pl Zend_Gdata_YouTube_PlaylistListEntry */
  770. $un = $pl->getPlaylistId();
  771. $item = new X_Page_Item_PItem('youtube-acc-subscriptions-'.$pl, $pl->getTitle());
  772. $item->setDescription($pl->getDescription())
  773. ->setIcon('/images/youtube/icons/playlist.png')
  774. ->setCustom(__CLASS__.':location', self::A_PLAYLISTS."/$accountId,$un")
  775. ->setLink(array(
  776. 'l' => X_Env::encode(self::A_PLAYLISTS."/$accountId,$un")
  777. ), 'default', false)
  778. ->setGenerator(__CLASS__);
  779. $items->append($item);
  780. }
  781. if ( $playlists->getNextLink() != null ) {
  782. $items->append($this->next(self::A_PLAYLISTS."/$accountId", $page + 1));
  783. }
  784. }
  785. } else {
  786. $this->accountsMenu($items);
  787. }
  788. }
  789. protected function activitiesMenu(X_Page_ItemList_PItem $items, $accountId = null, $page = 0 ) {
  790. if ( $accountId != null ) {
  791. $account = new Application_Model_YoutubeAccount();
  792. Application_Model_YoutubeAccountsMapper::i()->find($accountId, $account);
  793. /* @var $helper X_VlcShares_Plugins_Helper_Youtube */
  794. $helper = $this->helpers('youtube');
  795. $feed = $helper->getActivitiesByUser($account->getLabel(), $page);
  796. foreach ($feed as $activity) {
  797. /* @var $activity Zend_Gdata_YouTube_ActivityEntry */
  798. $vid = $activity->getVideoId();
  799. if ( $vid == null ) continue;
  800. /* @var $video Zend_Gdata_YouTube_VideoEntry */
  801. $video = $helper->getVideo($vid);
  802. $thumb = $video->getVideoThumbnails();
  803. $thumb = $thumb[0]['url'];
  804. $item = new X_Page_Item_PItem('youtube-acc-activity-'.$vid, $activity->getTitle(). ": ".$video->getTitle());
  805. $item->setDescription($video->getVideoDescription())
  806. ->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  807. ->setThumbnail($thumb)
  808. ->setIcon('/images/youtube/icons/activity.png')
  809. ->setCustom(__CLASS__.':location', self::A_ACTIVITIES."/$accountId/0/$vid")
  810. ->setLink(array(
  811. 'action' => 'mode',
  812. 'l' => X_Env::encode(self::A_ACTIVITIES."/$accountId/0/$vid")
  813. ), 'default', false)
  814. ->setGenerator(__CLASS__);
  815. $items->append($item);
  816. }
  817. /*
  818. if ( $feed->getNextLink() != null ) {
  819. $items->append($this->next(self::A_FAVORITES."/$accountId", $page + 1));
  820. }
  821. */
  822. } else {
  823. $this->accountsMenu($items);
  824. }
  825. }
  826. protected function back($mode, $submode, $page = 0, $id = null) {
  827. $location = array($mode, $submode);
  828. if ( $page > 1 ) {
  829. $page--;
  830. $location[] = $page;
  831. if ( $id ) {
  832. $location[] = $id;
  833. }
  834. }
  835. $location = implode('/', $location);
  836. $item = new X_Page_Item_PItem('youtube-back', X_Env::_('p_youtube_backbutton'));
  837. $item->setIcon('/images/youtube/icons/back.png')
  838. ->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  839. ->setCustom(__CLASS__.':location', $location)
  840. ->setLink(array(
  841. 'l' => X_Env::encode("$location")
  842. ), 'default', false)
  843. ->setGenerator(__CLASS__);
  844. return $item;
  845. }
  846. protected function next($locationPrefix, $nextPage) {
  847. $item = new X_Page_Item_PItem('youtube-next', X_Env::_('p_youtube_nextbutton'));
  848. $item->setIcon('/images/youtube/icons/next.png')
  849. ->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  850. ->setCustom(__CLASS__.':location', "$locationPrefix/$nextPage")
  851. ->setLink(array(
  852. 'l' => X_Env::encode("$locationPrefix/$nextPage")
  853. ), 'default', false)
  854. ->setGenerator(__CLASS__);
  855. return $item;
  856. }
  857. protected function libraryMenu(X_Page_ItemList_PItem $items, $submode = false) {
  858. X_Debug::i("Submode requested: ". print_r($submode, true));
  859. // disabling cache plugin
  860. try {
  861. $cachePlugin = X_VlcShares_Plugins::broker()->getPlugins('cache');
  862. if ( method_exists($cachePlugin, 'setDoNotCache') ) {
  863. $cachePlugin->setDoNotCache();
  864. }
  865. } catch (Exception $e) {
  866. // cache plugin not registered, no problem
  867. }
  868. if ($submode === false || $submode == null ) {
  869. // load all categories in the library
  870. $categories = Application_Model_YoutubeCategoriesMapper::i()->fetchAll();
  871. foreach ( $categories as $category ) {
  872. /* @var $category Application_Model_YoutubeCategory */
  873. $item = new X_Page_Item_PItem('youtube-category-'.$category->getId(), $category->getLabel() );
  874. $item//->setDescription(X_Env::_('p_youtube_br_mainmenu_submenu_error'))
  875. ->setThumbnail($category->getThumbnail())
  876. ->setIcon('/images/youtube/icons/category.png')
  877. ->setCustom(__CLASS__.':location', self::MODE_LIBRARY."/".$category->getId())
  878. ->setLink(array(
  879. 'l' => X_Env::encode(self::MODE_LIBRARY."/".$category->getId())
  880. ), 'default', false)
  881. ->setGenerator(__CLASS__);
  882. $items->append($item);
  883. }
  884. } else {
  885. // load all video inside a category categories
  886. /* @var $category Application_Model_YoutubeCategory */
  887. $category = new Application_Model_YoutubeCategory();
  888. Application_Model_YoutubeCategoriesMapper::i()->find($submode, $category);
  889. X_Debug::i('Category found: '.print_r($category, true));
  890. if ( $category->getId() != null && $category->getId() == $submode ) {
  891. $videos = Application_Model_YoutubeVideosMapper::i()->fetchByCategory($category->getId());
  892. foreach ( $videos as $video) {
  893. /* @var $video Application_Model_YoutubeVideo */
  894. $item = new X_Page_Item_PItem('youtube-library-'.$video->getId(), $video->getLabel() );
  895. $item->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  896. ->setIcon('/images/youtube/icons/video.png')
  897. ->setDescription($video->getDescription())
  898. ->setThumbnail($video->getThumbnail())
  899. ->setCustom(__CLASS__.':location', self::MODE_LIBRARY."/".$category->getId()."/0/".$video->getId())
  900. ->setLink(array(
  901. 'action' => 'mode',
  902. 'l' => X_Env::encode(self::MODE_LIBRARY."/".$category->getId()."/0/".$video->getId())
  903. ), 'default', false)
  904. ->setGenerator(__CLASS__);
  905. $items->append($item);
  906. }
  907. }
  908. }
  909. }
  910. private function _prepareVideo(X_Page_ItemList_PItem $items, Zend_Gdata_Media_Feed $feed, $locationPrefix) {
  911. foreach ( $feed as $yvideo ) {
  912. /* @var $yvideo Zend_Gdata_YouTube_VideoEntry */
  913. if ( $yvideo->getVideoDuration() == 0 ) continue; // no duration = no video
  914. $item = new X_Page_Item_PItem('youtube-video-'.$yvideo->getVideoId(), $yvideo->getVideoTitle() . ' [' . X_Env::formatTime($yvideo->getVideoDuration()) .']' );
  915. $thumb = $yvideo->getVideoThumbnails();
  916. @$thumb = $thumb[0]['url'];
  917. $item->setDescription($yvideo->getVideoDescription())
  918. ->setType(X_Page_Item_PItem::TYPE_ELEMENT)
  919. ->setIcon('/images/youtube/icons/video.png')
  920. ->setThumbnail($thumb)
  921. ->setCustom(__CLASS__.':location', "$locationPrefix/{$yvideo->getVideoId()}")
  922. ->setLink(array(
  923. 'action' => 'mode',
  924. 'l' => X_Env::encode("$locationPrefix/{$yvideo->getVideoId()}")
  925. ), 'default', false)
  926. ->setGenerator(__CLASS__);
  927. $items->append($item);
  928. }
  929. }
  930. }