PageRenderTime 74ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/package/app/app/alpha/lib/model/entry.php

https://bitbucket.org/pandaos/kaltura
PHP | 2584 lines | 1855 code | 412 blank | 317 comment | 353 complexity | ae7c4ee32669c4d8ae9f60b4d74a3fa6 MD5 | raw file
Possible License(s): AGPL-3.0, GPL-3.0, BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-3.0, JSON, MPL-2.0-no-copyleft-exception, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Subclass for representing a row from the 'entry' table.
  4. *
  5. *
  6. *
  7. * @package Core
  8. * @subpackage model
  9. */
  10. class entry extends Baseentry implements ISyncableFile, IIndexable
  11. {
  12. private $previous_status ;
  13. protected $old_categories;
  14. protected $is_categories_modified = false;
  15. const MINIMUM_ID_TO_DISPLAY = 8999;
  16. const ROOTS_FIELD_PREFIX = 'K_Pref';
  17. const ROOTS_FIELD_ENTRY_PREFIX = 'KP_Entry';
  18. const ROOTS_FIELD_BULK_UPLOAD_PREFIX = 'KP_Bulk';
  19. // NOTE - CHANGES MUST BE MADE TO LAYOUT.PHP JS PART AS WELL
  20. // different sort orders for browsing entries
  21. const ENTRY_SORT_MOST_VIEWED = 0;
  22. const ENTRY_SORT_MOST_RECENT = 1;
  23. const ENTRY_SORT_MOST_COMMENTS = 2;
  24. const ENTRY_SORT_MOST_FAVORITES = 3;
  25. const ENTRY_SORT_RANK = 4;
  26. const ENTRY_SORT_MEDIA_TYPE = 5;
  27. const ENTRY_SORT_NAME = 6;
  28. const ENTRY_SORT_KUSER_SCREEN_NAME = 7;
  29. // NOTE - CHANGES MUST BE MADE TO LAYOUT.PHP JS PART AS WELL
  30. const ENTRY_MEDIA_TYPE_AUTOMATIC = -1;
  31. const ENTRY_MEDIA_TYPE_ANY = 0;
  32. const ENTRY_MEDIA_TYPE_VIDEO = 1;
  33. const ENTRY_MEDIA_TYPE_IMAGE = 2;
  34. const ENTRY_MEDIA_TYPE_TEXT = 3;
  35. const ENTRY_MEDIA_TYPE_HTML = 4;
  36. const ENTRY_MEDIA_TYPE_AUDIO = 5;
  37. const ENTRY_MEDIA_TYPE_SHOW = 6;
  38. const ENTRY_MEDIA_TYPE_SHOW_XML = 7; // for the kplayer: the data contains the xml itself and not a url
  39. const ENTRY_MEDIA_TYPE_BUBBLES = 9;
  40. const ENTRY_MEDIA_TYPE_XML = 10;
  41. const ENTRY_MEDIA_TYPE_DOCUMENT = 11;
  42. const ENTRY_MEDIA_TYPE_SWF = 12;
  43. const ENTRY_MEDIA_TYPE_PDF = 13;
  44. const ENTRY_MEDIA_TYPE_GENERIC_1= 101; // these types can be used for derived classes - assume this is some kind of TXT file
  45. const ENTRY_MEDIA_TYPE_GENERIC_2= 102; // these types can be used for derived classes
  46. const ENTRY_MEDIA_TYPE_GENERIC_3= 103; // these types can be used for derived classes
  47. const ENTRY_MEDIA_TYPE_GENERIC_4= 104; // these types can be used for derived classes
  48. const ENTRY_MEDIA_TYPE_LIVE_STREAM_FLASH = 201;
  49. const ENTRY_MEDIA_TYPE_LIVE_STREAM_WINDOWS_MEDIA = 202;
  50. const ENTRY_MEDIA_TYPE_LIVE_STREAM_REAL_MEDIA = 203;
  51. const ENTRY_MEDIA_TYPE_LIVE_STREAM_QUICKTIME = 204;
  52. // NOTE - CHANGES MUST BE MADE TO LAYOUT.PHP JS PART AS WELL
  53. const ENTRY_MEDIA_SOURCE_FILE = 1;
  54. const ENTRY_MEDIA_SOURCE_WEBCAM = 2;
  55. const ENTRY_MEDIA_SOURCE_FLICKR = 3;
  56. const ENTRY_MEDIA_SOURCE_YOUTUBE = 4;
  57. const ENTRY_MEDIA_SOURCE_URL = 5;
  58. const ENTRY_MEDIA_SOURCE_TEXT = 6;
  59. const ENTRY_MEDIA_SOURCE_MYSPACE = 7;
  60. const ENTRY_MEDIA_SOURCE_PHOTOBUCKET = 8;
  61. const ENTRY_MEDIA_SOURCE_JAMENDO = 9;
  62. const ENTRY_MEDIA_SOURCE_CCMIXTER = 10;
  63. const ENTRY_MEDIA_SOURCE_NYPL = 11;
  64. const ENTRY_MEDIA_SOURCE_CURRENT = 12;
  65. const ENTRY_MEDIA_SOURCE_MEDIA_COMMONS = 13;
  66. const ENTRY_MEDIA_SOURCE_KALTURA = 20;
  67. const ENTRY_MEDIA_SOURCE_KALTURA_USER_CLIPS = 21;
  68. const ENTRY_MEDIA_SOURCE_ARCHIVE_ORG = 22;
  69. const ENTRY_MEDIA_SOURCE_KALTURA_PARTNER = 23;
  70. const ENTRY_MEDIA_SOURCE_METACAFE = 24;
  71. const ENTRY_MEDIA_SOURCE_KALTURA_QA = 25;
  72. const ENTRY_MEDIA_SOURCE_KALTURA_KSHOW = 26;
  73. const ENTRY_MEDIA_SOURCE_KALTURA_PARTNER_KSHOW = 27;
  74. const ENTRY_MEDIA_SOURCE_SEARCH_PROXY = 28;
  75. const ENTRY_MEDIA_SOURCE_AKAMAI_LIVE = 29;
  76. const ENTRY_MEDIA_SOURCE_PARTNER_SPECIFIC = 100;
  77. const ENTRY_MODERATION_STATUS_PENDING_MODERATION = 1;
  78. const ENTRY_MODERATION_STATUS_APPROVED = 2;
  79. const ENTRY_MODERATION_STATUS_REJECTED = 3;
  80. const ENTRY_MODERATION_STATUS_FLAGGED_FOR_REVIEW = 5;
  81. const ENTRY_MODERATION_STATUS_AUTO_APPROVED = 6;
  82. const MAX_NORMALIZED_RANK = 5;
  83. const MAX_CATEGORIES_PER_ENTRY = 32;
  84. const FILE_SYNC_ENTRY_SUB_TYPE_DATA = 1;
  85. const FILE_SYNC_ENTRY_SUB_TYPE_DATA_EDIT = 2;
  86. const FILE_SYNC_ENTRY_SUB_TYPE_THUMB = 3;
  87. const FILE_SYNC_ENTRY_SUB_TYPE_ARCHIVE = 4;
  88. const FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD = 5;
  89. const FILE_SYNC_ENTRY_SUB_TYPE_OFFLINE_THUMB = 6;
  90. const FILE_SYNC_ENTRY_SUB_TYPE_ISM = 7;
  91. const FILE_SYNC_ENTRY_SUB_TYPE_ISMC = 8;
  92. const FILE_SYNC_ENTRY_SUB_TYPE_CONVERSION_LOG = 9;
  93. const MIX_EDITOR_TYPE_SIMPLE = 1;
  94. const MIX_EDITOR_TYPE_ADVANCED = 2;
  95. const ENTRY_DURATION_TYPE_NOTAVAILABLE = "notavailable";
  96. const ENTRY_DURATION_TYPE_SHORT = "short";
  97. const ENTRY_DURATION_TYPE_MEDIUM = "medium";
  98. const ENTRY_DURATION_TYPE_LONG = "long";
  99. const ENTRY_CATEGORY_ESCAPE = "_";
  100. const ENTRY_CATEGORY_SEPARATOR = ",";
  101. private $appears_in = null;
  102. private $m_added_moderation = false;
  103. private $should_call_set_data_content = false;
  104. private $data_content = null;
  105. private $desired_version = null;
  106. private $archive_extension = null;
  107. private static $mediaTypeNames = array(
  108. self::ENTRY_MEDIA_TYPE_AUTOMATIC => 'AUTOMATIC',
  109. self::ENTRY_MEDIA_TYPE_ANY => 'ANY',
  110. self::ENTRY_MEDIA_TYPE_VIDEO => 'VIDEO',
  111. self::ENTRY_MEDIA_TYPE_IMAGE => 'IMAGE',
  112. self::ENTRY_MEDIA_TYPE_TEXT => 'TEXT',
  113. self::ENTRY_MEDIA_TYPE_HTML => 'HTML',
  114. self::ENTRY_MEDIA_TYPE_AUDIO => 'AUDIO',
  115. self::ENTRY_MEDIA_TYPE_SHOW => 'SHOW',
  116. self::ENTRY_MEDIA_TYPE_SHOW_XML => 'SHOW_XML',
  117. self::ENTRY_MEDIA_TYPE_BUBBLES => 'BUBBLES',
  118. self::ENTRY_MEDIA_TYPE_XML => 'XML',
  119. self::ENTRY_MEDIA_TYPE_DOCUMENT => 'DOCUMENT',
  120. self::ENTRY_MEDIA_TYPE_SWF => 'SWF',
  121. self::ENTRY_MEDIA_TYPE_PDF => 'PDF',
  122. self::ENTRY_MEDIA_TYPE_GENERIC_1 => 'GENERIC_1',
  123. self::ENTRY_MEDIA_TYPE_GENERIC_2 => 'GENERIC_2',
  124. self::ENTRY_MEDIA_TYPE_GENERIC_3 => 'GENERIC_3',
  125. self::ENTRY_MEDIA_TYPE_GENERIC_4 => 'GENERIC_4',
  126. self::ENTRY_MEDIA_TYPE_LIVE_STREAM_FLASH => 'LIVE_STREAM_FLASH',
  127. self::ENTRY_MEDIA_TYPE_LIVE_STREAM_WINDOWS_MEDIA => 'LIVE_STREAM_WINDOWS_MEDIA',
  128. self::ENTRY_MEDIA_TYPE_LIVE_STREAM_REAL_MEDIA => 'LIVE_STREAM_REAL_MEDIA',
  129. self::ENTRY_MEDIA_TYPE_LIVE_STREAM_QUICKTIME => 'LIVE_STREAM_QUICKTIME',
  130. );
  131. /**
  132. * Applies default values to this object.
  133. * This method should be called from the object's constructor (or
  134. * equivalent initialization method).
  135. * @see __construct()
  136. */
  137. public function applyDefaultValues()
  138. {
  139. parent::applyDefaultValues();
  140. $this->setStatus(entryStatus::PENDING);
  141. $this->setModerationStatus(self::ENTRY_MODERATION_STATUS_AUTO_APPROVED);
  142. }
  143. // the columns names is a list of all fields that will participate in the search_text
  144. // TODO - add the admin_tags to the column names
  145. public static function getColumnNames() { return array ( "name" , "tags" ,"description" , "admin_tags" ); }
  146. public static function getSearchableColumnName () { return "search_text" ; }
  147. // don't stop until a unique hash is created for this object
  148. private static function calculateId ( )
  149. {
  150. $dc = kDataCenterMgr::getCurrentDc();
  151. for ( $i = 0 ; $i < 10 ; ++$i)
  152. {
  153. $id = $dc["id"].'_'.kString::generateStringId();
  154. $existing_object = entryPeer::retrieveByPk( $id );
  155. if ( ! $existing_object ) return $id;
  156. }
  157. die();
  158. }
  159. public function justSave($con = null)
  160. {
  161. return parent::save( $con );
  162. }
  163. public function save(PropelPDO $con = null)
  164. {
  165. $is_new = false;
  166. if ( $this->isNew() )
  167. {
  168. $this->setId(self::calculateId());
  169. // start by setting the modified_at to the current time
  170. $this->setModifiedAt( time() ) ;
  171. $this->setModerationCount(0);
  172. if (is_null($this->getAccessControlId()))
  173. {
  174. $partner = $this->getPartner();
  175. if($partner)
  176. $this->setAccessControlId($partner->getDefaultAccessControlId());
  177. }
  178. // only media clips should increments - not roughcuts or backgrounds
  179. if ( $this->type == entryType::MEDIA_CLIP )
  180. myStatisticsMgr::addEntry( $this );
  181. $is_new = true;
  182. }
  183. if ( $this->isColumnModified ( entryPeer::STATUS ) && ( $this->previous_status != $this->getStatus() ) )
  184. {
  185. // add a track for when the status changed
  186. $track_entry = new TrackEntry();
  187. $track_entry->setEntryId( $this->getId() );
  188. $track_entry->setTrackEventTypeId( TrackEntry::TRACK_ENTRY_EVENT_TYPE_UPDATE_ENTRY );
  189. $track_entry->setChangedProperties( "status [{$this->previous_status}]->[{$this->getStatus()}]" );
  190. if ( $this->previous_status != entryStatus::DELETED &&
  191. $this->getStatus() == entryStatus::DELETED )
  192. {
  193. myStatisticsMgr::deleteEntry( $this );
  194. $track_entry->setTrackEventTypeId( TrackEntry::TRACK_ENTRY_EVENT_TYPE_DELETED_ENTRY );
  195. }
  196. TrackEntry::addTrackEntry( $track_entry );
  197. }
  198. if ( $this->type == entryType::MIX )
  199. {
  200. // some of the properties should be copied to the kshow
  201. $kshow = $this->getkshow();
  202. if ( $kshow )
  203. {
  204. $modified = false;
  205. if ( $kshow->getRank() != $this->getRank() )
  206. {
  207. $kshow->setRank( $this->getRank() );
  208. $modified = true;
  209. }
  210. if ( $kshow->getLengthInMsecs() != $this->getLengthInMsecs() )
  211. {
  212. $kshow->setLengthInMsecs ( $this->getLengthInMsecs() );
  213. $modified = true;
  214. }
  215. if ( $modified ) $kshow->save();
  216. }
  217. else
  218. {
  219. $this->log( "entry [" . $this->getId() . "] does not have a real kshow with id [" . $this->getKshowId() . "]", Propel::LOG_WARNING );
  220. }
  221. }
  222. myPartnerUtils::setPartnerIdForObj( $this );
  223. if ( $this->getType() != entryType::PLAYLIST )
  224. mySearchUtils::setDisplayInSearch( $this );
  225. mySearchUtils::setSearchTextDiscreteForEntry($this);
  226. // update the admin_tags per partner
  227. ktagword::updateAdminTags( $this );
  228. // same for puserId ...
  229. $this->getPuserId( true );
  230. // make sure this entry is saved before calling updateAllMetadataVersionsRelevantForEntry, since fixMetadata retrieves the entry from the DB
  231. // and checks its data path which was modified above.
  232. $res = parent::save( $con );
  233. if ($is_new)
  234. {
  235. // when retrieving the entry - ignore thr filter - when in partner has moderate_content =1 - the entry will have status=3 and will fail the retrieveByPk
  236. entryPeer::setUseCriteriaFilter(false);
  237. $obj = entryPeer::retrieveByPk($this->getId());
  238. $this->setIntId($obj->getIntId());
  239. entryPeer::setUseCriteriaFilter(true);
  240. }
  241. if ( $this->should_call_set_data_content )
  242. {
  243. // calling the funciton with null will cause it to use the $this->data_content
  244. $this->setDataContent( null );
  245. $res = parent::save( $con );
  246. }
  247. // the fix should be done whether the status is READY or ERROR_CONVERTING
  248. if ( $this->getStatus() == entryStatus::READY || $this->getStatus() == entryStatus::ERROR_CONVERTING )
  249. {
  250. // fire some stuff due to the new status
  251. $version_to_update = $this->getUpdateWhenReady();
  252. if ( $version_to_update )
  253. {
  254. try{
  255. myMetadataUtils::updateAllMetadataVersionsRelevantForEntry ( $this);
  256. $this->resetUpdateWhenReady();
  257. $res = parent::save( $con );
  258. }
  259. catch(Exception $e)
  260. {
  261. KalturaLog::err($e->getMessage());
  262. }
  263. }
  264. }
  265. $this->syncCategories();
  266. return $res;
  267. }
  268. // TODO - PERFORMANCE DB - move to use cache !!
  269. // will increment the views by 1
  270. public function incViews ( $should_save = true )
  271. {
  272. myStatisticsMgr::incEntryViews( $this );
  273. }
  274. private function statusChangedTo ( $new_status )
  275. {
  276. return ( $this->previous_status != $new_status &&
  277. $this->getStatus() == $new_status );
  278. }
  279. public function setStatus ( $v)
  280. {
  281. // if we haven't yet set the previous status - remember it now
  282. if ( is_null ( $this->previous_status ) )
  283. $this->previous_status = $this->getStatus();
  284. parent::setStatus( $v );
  285. }
  286. /**
  287. * will handle the flow in case of need to moderate.
  288. */
  289. public function setStatusReady ( $force = false )
  290. {
  291. $this->setStatus( entryStatus::READY );
  292. $this->setDefaultModerationStatus();
  293. return $this->getStatus();
  294. }
  295. public function setDefaultModerationStatus()
  296. {
  297. $should_moderate = false;
  298. // in this case no configuration really matters
  299. if ( $this->getModerate() )
  300. {
  301. $should_moderate = true;
  302. }
  303. else
  304. {
  305. $should_moderate = myPartnerUtils::shouldModerate( $this->getPartnerId(), $this);
  306. }
  307. if( $should_moderate )
  308. {
  309. if ( ! $this->getId() )
  310. $this->save(); // save to DB so we'll have the id for the moderation list
  311. $this->setModerationStatus( self::ENTRY_MODERATION_STATUS_PENDING_MODERATION );
  312. if ( !$this->m_added_moderation )
  313. {
  314. myModerationMgr::addToModerationList( $this );
  315. $this->m_added_moderation = true;
  316. }
  317. }
  318. else
  319. {
  320. $this->setModerationStatus( self::ENTRY_MODERATION_STATUS_AUTO_APPROVED );
  321. }
  322. }
  323. public function isReady()
  324. {
  325. return ( $this->getStatus() == entryStatus::READY ) ;
  326. }
  327. public function getNormalizedRank ()
  328. {
  329. $res = round($this->rank / 1000);
  330. if ( $res > self::MAX_NORMALIZED_RANK ) return self::MAX_NORMALIZED_RANK;
  331. return $res;
  332. }
  333. /*
  334. * return an array of tuples of the file's version: [name, size, time, version]
  335. */
  336. public function getAllVersions ()
  337. {
  338. $current_version = $this->getData();
  339. $c = strstr($current_version, '^') ? '^' : '&';
  340. $parts = explode($c, $current_version);
  341. if (count($parts) == 2 && strlen($parts[1]))
  342. {
  343. return null;
  344. }
  345. // create an array to hold versions list
  346. $results = array();
  347. for ($version = 100000; $version <= $current_version; $version++ )
  348. {
  349. $version_sync_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $version);
  350. $local_file_sync = kFileSyncUtils::getLocalFileSyncForKey($version_sync_key, false);
  351. if ($local_file_sync)
  352. {
  353. $result = array();
  354. // first - file name (with the full path)
  355. $result[] = $local_file_sync->getFilePath();
  356. // second - size
  357. $result[] = $local_file_sync->getFileSize();
  358. // third - time
  359. $result[] = filemtime ( $local_file_sync->getFullPath());
  360. // forth - version
  361. $result[] = substr( kFile::getFileNameNoExtension ( $local_file_sync->getFilePath() ) , strlen ($this->getId().'_') );
  362. $results[] = $result;
  363. }
  364. }
  365. return $results;
  366. }
  367. public function getAllVersionsFormatted()
  368. {
  369. $res = $this->getAllVersions();
  370. $formatted = array ();
  371. if ( ! is_array ( $res ) ) return null;
  372. foreach ( $res as $version_info )
  373. {
  374. $formatted []= array (
  375. "version" => $version_info[3] ,
  376. "rawData" => $version_info[2] ,
  377. "date" => strftime( "%d/%m/%y %H:%M:%S" , $version_info[2] ) );
  378. }
  379. return $formatted;
  380. }
  381. public function getLastVersion()
  382. {
  383. $version = kFile::getFileNameNoExtension ( $this->getData() );
  384. return $version;
  385. }
  386. public function getFormattedLengthInMsecs ()
  387. {
  388. return dateUtils::formatDuration ( $this->getLengthInMsecs() );
  389. }
  390. /**
  391. * (non-PHPdoc)
  392. * @see lib/model/ISyncableFile#getSyncKey()
  393. */
  394. public function getSyncKey ( $sub_type , $version = null )
  395. {
  396. self::validateFileSyncSubType ( $sub_type );
  397. $key = new FileSyncKey();
  398. $key->object_type = FileSyncObjectType::ENTRY;
  399. // // remarked by Tan-Tan 13/01/2010
  400. // if($sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_THUMB && $this->getMediaType() == self::ENTRY_MEDIA_TYPE_IMAGE)
  401. // {
  402. // $key->object_sub_type = self::FILE_SYNC_ENTRY_SUB_TYPE_DATA;
  403. // }
  404. // else
  405. // {
  406. $key->object_sub_type = $sub_type;
  407. // }
  408. $key->object_id = $this->getId();
  409. $key->version = $this->getVersionForSubType ( $sub_type, $version );
  410. $key->partner_id = $this->getPartnerId();
  411. return $key;
  412. }
  413. /**
  414. * @return string
  415. */
  416. public function generateBaseFileName( $sub_type, $version = null)
  417. {
  418. if(is_null($version))
  419. $version = $this->getVersion();
  420. // TODO - remove after Akamai bug fixed and create the file names with sub type
  421. if($sub_type == entry::FILE_SYNC_ENTRY_SUB_TYPE_ISM)
  422. return "_{$version}";
  423. if($sub_type == entry::FILE_SYNC_ENTRY_SUB_TYPE_ISMC)
  424. return "_{$version}";
  425. // remove till here
  426. return "{$sub_type}_{$version}";
  427. }
  428. /* (non-PHPdoc)
  429. * @see lib/model/ISyncableFile#generateFileName()
  430. */
  431. public function generateFileName( $sub_type, $version = null)
  432. {
  433. if($sub_type == entry::FILE_SYNC_ENTRY_SUB_TYPE_ISM)
  434. return $this->getId() . '_' . $this->generateBaseFileName(0, $version) . '.ism';
  435. if($sub_type == entry::FILE_SYNC_ENTRY_SUB_TYPE_ISMC)
  436. return $this->getId() . '_' . $this->generateBaseFileName(0, $version) . '.ismc';
  437. return $this->getId() . '_' . $this->generateBaseFileName($sub_type, $version);
  438. }
  439. /**
  440. * (non-PHPdoc)
  441. * @see lib/model/ISyncableFile#generateFilePathArr()
  442. */
  443. public function generateFilePathArr( $sub_type, $version = null)
  444. {
  445. self::validateFileSyncSubType ( $sub_type );
  446. if ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_DATA )
  447. {
  448. $data = $this->getData();
  449. if($this->getType() == entryType::MIX && (!$this->getData() || !strpos($this->getData(), 'xml')))
  450. {
  451. $data .= ".xml";
  452. }
  453. $res = myContentStorage::getGeneralEntityPath("entry/data", $this->getIntId(), $this->getId(), $data, $version);
  454. // $res = myContentStorage::getGeneralEntityPath("entry/data", $this->getIntId(), $this->getId(), $this->getData(), $version);
  455. }
  456. elseif ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_DATA_EDIT )
  457. {
  458. $res = myContentStorage::getFileNameEdit( myContentStorage::getGeneralEntityPath("entry/data", $this->getIntId(), $this->getId(), $this->getData(), $version) );
  459. }
  460. elseif ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_THUMB )
  461. {
  462. $res = myContentStorage::getGeneralEntityPath("entry/bigthumbnail", $this->getIntId(), $this->getId(), $this->getThumbnail() , $version);
  463. }
  464. elseif ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_ARCHIVE )
  465. {
  466. $res = null;
  467. $data_path = myContentStorage::getGeneralEntityPath("entry/data", $this->getIntId(), $this->getId(), $this->getData(), $version);
  468. // assume the suffix is not the same as the one on the data
  469. $archive_path = dirname ( str_replace ( "content/entry/" , "archive/" , $data_path ) ) . "/" . $this->getId();
  470. if ($this->getArchiveExtension())
  471. {
  472. $res = $archive_path . "." . $this->getArchiveExtension();
  473. }
  474. else
  475. {
  476. $archive_pattern = $archive_path . ".*" ;
  477. $arc_files = glob ( myContentStorage::getFSContentRootPath( ) . $archive_pattern );
  478. foreach ( $arc_files as $full_path_name )
  479. {
  480. // return the first file found
  481. $res = $full_path_name;
  482. break;
  483. }
  484. if ( ! $res )
  485. $res = $archive_pattern;
  486. }
  487. }
  488. elseif ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD )
  489. {
  490. // in this case the $version is used as the format
  491. $basename = kFile::getFileNameNoExtension ( $this->getData() );
  492. $path = myContentStorage::getGeneralEntityPath("entry/download", $this->getIntId(), $this->getId(), $basename);
  493. $download_path = $path.".$version";
  494. $res = $download_path;
  495. }
  496. else
  497. {
  498. $path = "entry/data";
  499. switch($sub_type)
  500. {
  501. case self::FILE_SYNC_ENTRY_SUB_TYPE_ISM:
  502. $basename = $this->generateBaseFileName(0, $this->getIsmVersion());
  503. $basename .= '.ism';
  504. break;
  505. case self::FILE_SYNC_ENTRY_SUB_TYPE_ISMC:
  506. $basename = $this->generateBaseFileName(0, $this->getIsmVersion());
  507. $basename .= '.ismc';
  508. break;
  509. case self::FILE_SYNC_ENTRY_SUB_TYPE_CONVERSION_LOG:
  510. $basename = $this->generateBaseFileName(0, $this->getIsmVersion());
  511. $basename .= '.log';
  512. break;
  513. }
  514. $res = myContentStorage::getGeneralEntityPath($path, $this->getIntId(), $this->getId(), $basename);
  515. }
  516. return array ( myContentStorage::getFSContentRootPath( ) , $res );
  517. }
  518. private function getVersionForSubType ( $sub_type, $version = null )
  519. {
  520. if (
  521. $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_ISM
  522. ||
  523. $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_ISMC
  524. ||
  525. $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_CONVERSION_LOG
  526. )
  527. {
  528. if(!is_null($version))
  529. return $version;
  530. return $this->getIsmVersion();
  531. }
  532. $new_version = "";
  533. if ( $version )
  534. {
  535. if ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD )
  536. {
  537. // MUST have A VERSION !
  538. $new_version = $this->getVersion() . "." . $version;
  539. }
  540. else
  541. {
  542. $new_version = $version;
  543. }
  544. }
  545. else
  546. {
  547. if ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_DATA || $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_DATA_EDIT )
  548. $new_version = $this->getVersion();
  549. elseif ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_THUMB )
  550. $new_version = $this->getThumbnailVersion();
  551. elseif ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_ARCHIVE )
  552. $new_version = "";
  553. elseif ( $sub_type == self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD )
  554. {
  555. // MUST have A VERSION !
  556. $new_version = $this->getVersion();
  557. }
  558. }
  559. return $new_version;
  560. }
  561. /**
  562. * Enter description here...
  563. *
  564. * @var FileSync
  565. */
  566. private $m_file_sync;
  567. /**
  568. * @return FileSync
  569. */
  570. public function getFileSync ( )
  571. {
  572. return $this->m_file_sync;
  573. }
  574. public function setFileSync ( FileSync $file_sync )
  575. {
  576. $this->m_file_sync = $file_sync;
  577. }
  578. private static function validateFileSyncSubType ( $sub_type )
  579. {
  580. if ( $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_DATA &&
  581. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_DATA_EDIT &&
  582. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_THUMB &&
  583. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_ARCHIVE &&
  584. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD &&
  585. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_ISM &&
  586. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_ISMC &&
  587. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_CONVERSION_LOG &&
  588. $sub_type != self::FILE_SYNC_ENTRY_SUB_TYPE_OFFLINE_THUMB
  589. )
  590. throw new FileSyncException ( FileSyncObjectType::ENTRY ,
  591. $sub_type , array (
  592. self::FILE_SYNC_ENTRY_SUB_TYPE_DATA ,
  593. self::FILE_SYNC_ENTRY_SUB_TYPE_DATA_EDIT,
  594. self::FILE_SYNC_ENTRY_SUB_TYPE_THUMB ,
  595. self::FILE_SYNC_ENTRY_SUB_TYPE_ARCHIVE ,
  596. self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD ,
  597. self::FILE_SYNC_ENTRY_SUB_TYPE_ISM ,
  598. self::FILE_SYNC_ENTRY_SUB_TYPE_ISMC ,
  599. self::FILE_SYNC_ENTRY_SUB_TYPE_CONVERSION_LOG ,
  600. self::FILE_SYNC_ENTRY_SUB_TYPE_OFFLINE_THUMB ,
  601. ) );
  602. }
  603. // return the full path on the disk
  604. public function getFullDataPath( $version = NULL )
  605. {
  606. $path = myContentStorage::getFSContentRootPath() . $this->getDataPath();
  607. if ( file_exists( $path )) return $path;
  608. return $path;
  609. }
  610. /**
  611. * This function returns the file system path for a requested content entity.
  612. * @return string the content path
  613. */
  614. public function getDataPath( $version = NULL )
  615. {
  616. if ( $version == NULL || $version == -1 )
  617. {
  618. return myContentStorage::getGeneralEntityPath("entry/data", $this->getIntId(), $this->getId(), $this->getData());
  619. }
  620. else
  621. {
  622. $ext = pathinfo ($this->getData(), PATHINFO_EXTENSION);
  623. $file_version = myContentStorage::getGeneralEntityPath("entry/data", $this->getIntId(), $this->getId(), $version);
  624. return $file_version . "." . $ext;
  625. }
  626. }
  627. public function getDataUrl( $version = NULL )
  628. {
  629. if( $this->getType() == entryType::PLAYLIST )
  630. {
  631. return myPlaylistUtils::getExecutionUrl( $this );
  632. }
  633. //$path = $this->getThumbnailPath ( $version );
  634. $path = myPartnerUtils::getUrlForPartner( $this->getPartnerId() , $this->getSubpId() ) . "/flvclipper/entry_id/" . $this->getId() ;
  635. $current_version = $this->getVersion();
  636. if ( $version )
  637. $path .= "/version/$version";
  638. else
  639. $path .= "/version/$current_version";
  640. $url = myPartnerUtils::getCdnHost($this->getPartnerId()) . $path ;
  641. return $url;
  642. }
  643. /**
  644. * This function sets and returns a new path for a requested content entity.
  645. * @param string $filename = the original fileName from which the extension is cut.
  646. * @return string the content file name
  647. */
  648. public function setData($filename , $force = false )
  649. {
  650. if ( $force )
  651. $data = $filename;
  652. else
  653. $data = myContentStorage::generateRandomFileName($filename, $this->getData());
  654. Baseentry::setData( $data );
  655. return $this->getData();
  656. }
  657. /**
  658. *
  659. * @param $version
  660. * @param $format
  661. * @return FileSync
  662. */
  663. public function getDownloadFileSyncAndLocal ( $version = NULL , $format = null , $sub_type = null )
  664. {
  665. $sync_key = null;
  666. if ( $this->getType() == entryType::MEDIA_CLIP)
  667. {
  668. if ( $this->getMediaType() == self::ENTRY_MEDIA_TYPE_VIDEO || $this->getMediaType() == self::ENTRY_MEDIA_TYPE_AUDIO)
  669. {
  670. $flavor_assets = assetPeer::retrieveBestPlayByEntryId($this->getId()); // uset the format as the extension
  671. if($flavor_assets)
  672. $sync_key = $flavor_assets->getSyncKey(flavorAsset::FILE_SYNC_FLAVOR_ASSET_SUB_TYPE_ASSET);
  673. }
  674. elseif ( $this->getMediaType() == self::ENTRY_MEDIA_TYPE_IMAGE )
  675. {
  676. $sync_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $version );
  677. }
  678. }
  679. elseif ( $this->getType() == entryType::MIX )
  680. {
  681. // if roughcut - the version should be used
  682. $sync_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD , $version );
  683. }
  684. else
  685. {
  686. // if not roughcut - the format should be used
  687. $sync_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD , $format );
  688. }
  689. if(!$sync_key)
  690. return null;
  691. return kFileSyncUtils::getReadyFileSyncForKey ( $sync_key , true , false );
  692. }
  693. // return the file
  694. public function getDownloadPath( $version = NULL , $format = null , $sub_type = null )
  695. {
  696. // fetch the path (from remote if no local)
  697. list ( $file_sync , $local ) = $this->getDownloadFileSyncAndLocal( $version , $format , $sub_type );
  698. if ( ! $file_sync )
  699. return null;
  700. return $file_sync->getFullPath();
  701. }
  702. public function getDownloadSize( $version = NULL )
  703. {
  704. // fetch the path (from remote if no local)
  705. list ( $file_sync , $local ) = $this->getDownloadFileSyncAndLocal( $version , null );
  706. if ( ! $file_sync )
  707. return 0;
  708. return $file_sync->getFileSize();
  709. }
  710. public function getDownloadUrl( $version = NULL )
  711. {
  712. // always return the URL for the download - there is enough logic there to fix problems return the correct version/flavor
  713. return myPartnerUtils::getCdnHost($this->getPartnerId()). myPartnerUtils::getUrlForPartner( $this->getPartnerId() , $this->getSubpId() ) . "/raw/entry_id/" . $this->getId() . "/version/" . $this->getVersion();
  714. }
  715. public function getDownloadPathForFormat ( $version = NULL , $format )
  716. {
  717. // used by ppt-convert flow (downloadPath in addDownload response)
  718. // and perhaps by other clients as name
  719. $download_path = $this->getDownloadPath( $version , $format , self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD );
  720. if($download_path)
  721. return $download_path;
  722. // if did not return anything, probably due to missing fileSync
  723. // missing fileSync - if conversion was not done yet
  724. $key = $this->getSyncKey(self::FILE_SYNC_ENTRY_SUB_TYPE_DOWNLOAD, $format);
  725. return kFileSyncUtils::getLocalFilePathForKey($key);
  726. }
  727. /*
  728. * deprecated - was called from myBatchDownloadVideoServer which is no longer used
  729. // given the path of the converted file (not an FLV file) - create its URL
  730. public function getConvertedDownoadUrl ( $file_real_path )
  731. {
  732. $path = str_replace ( myContentStorage::getFSContentRootPath() , "" , $file_real_path );
  733. $path = str_replace ( "\\" , "" , $path );
  734. return myPartnerUtils::getCdnHost($this->getPartnerId()). myPartnerUtils::getUrlForPartner( $this->getPartnerId() , $this->getSubpId() ) . $path;
  735. }
  736. */
  737. public function setDesiredVersion ( $v )
  738. {
  739. $this->desired_version = $v;
  740. }
  741. public function getDesiredVersion ( )
  742. {
  743. return $this->desired_version ;
  744. }
  745. public function setArchiveExtension($v)
  746. {
  747. $this->archive_extension = $v;
  748. }
  749. public function getArchiveExtension()
  750. {
  751. return $this->archive_extension;
  752. }
  753. // will work only for types that the data can be served as an a response to the service
  754. public function getDataContent ( $from_cache = false )
  755. {
  756. if ( $this->getType() == entryType::MIX ||
  757. $this->getType() == entryType::DATA ||
  758. $this->getType() == entryType::PLAYLIST ||
  759. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_XML ||
  760. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_TEXT ||
  761. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_GENERIC_1 )
  762. {
  763. if ( $from_cache ) return $this->data_content;
  764. $content_path = myContentStorage::getFSContentRootPath();
  765. $version = $this->desired_version;
  766. if ( ! $version || $version == -1 ) $version = null;
  767. $sync_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $version );
  768. $content = kFileSyncUtils::file_get_contents( $sync_key , true , false ); // don't be strict when fetching this content
  769. if ( $content )
  770. {
  771. // patch for fixing old AE roughcuts without cross="0"
  772. if ($this->getType() == entryType::MIX)
  773. {
  774. $data2 = str_replace('<EndTransition type', '<EndTransition cross="0" type', $content);
  775. return $data2;
  776. }
  777. return $content;
  778. }
  779. }
  780. return null;
  781. }
  782. // will work only for types that the data can be served as an a response to the service
  783. public function setDataContent ( $v , $increment_version = true , $allow_type_roughcut = false )
  784. {
  785. // if ( $v === null ) return ;
  786. // DON'T do this for ENTRY_TYPE_SHOW unless $allow_type_roughcut is true
  787. // - the metadata is handling is complex and is done in other places in the code
  788. if ( ($allow_type_roughcut && $this->getType() == entryType::MIX) ||
  789. $this->getType() == entryType::DATA ||
  790. $this->getType() == entryType::PLAYLIST ||
  791. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_XML ||
  792. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_SHOW ||
  793. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_TEXT ||
  794. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_GENERIC_1 )
  795. {
  796. if ( $this->getId() == null )
  797. {
  798. // come back when there is an ID
  799. $this->data_content = $v;
  800. $this->should_call_set_data_content = true;
  801. return ;
  802. }
  803. // if increment_version is false - don't be strict
  804. $strict = false;
  805. if ( ! $increment_version || $v == $this->data_content )
  806. {
  807. // attempting to update the same value
  808. $strict = false ;
  809. }
  810. if ( $v == null ) $v = $this->data_content;
  811. else $this->data_content = $v; // store it so it can be used with getDataContent(true) is called
  812. if ( $v !== null )
  813. {
  814. // increment the version
  815. if ( $increment_version ) $this->setData ( parent::getData() . $this->getFileSuffix() ) ;
  816. $this->should_call_set_data_content = false;
  817. $this->save();
  818. $sync_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA );
  819. kFileSyncUtils::file_put_contents( $sync_key , $v , $strict );
  820. }
  821. }
  822. }
  823. // return the default file suffix according to the entry type
  824. private function getFileSuffix ( )
  825. {
  826. if ( $this->getType() == entryType::MIX ||
  827. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_SHOW ||
  828. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_XML )
  829. {
  830. return ".xml";
  831. }
  832. elseif ( $this->getMediaType() == self::ENTRY_MEDIA_TYPE_TEXT ||
  833. $this->getMediaType() == self::ENTRY_MEDIA_TYPE_GENERIC_1 )
  834. {
  835. return ".txt";
  836. }
  837. return "";
  838. }
  839. public function getThumbnail()
  840. {
  841. $thumbnail = parent::getThumbnail();
  842. if (!$thumbnail && $this->getMediaType() == entry::ENTRY_MEDIA_TYPE_AUDIO)
  843. $thumbnail = "&audio_thumb.jpg";
  844. return $thumbnail;
  845. }
  846. /**
  847. * This function returns the file system path for a requested content entity.
  848. * @return string the content path
  849. */
  850. public function getThumbnailPath( $version = NULL )
  851. {
  852. return myContentStorage::getGeneralEntityPath("entry/thumbnail", $this->getIntId(), $this->getId(), $this->getThumbnail() , $version );
  853. }
  854. public function getThumbnailUrl( $version = NULL )
  855. {
  856. if(PermissionPeer::isValidForPartner(PermissionName::FEATURE_DISABLE_KMC_DRILL_DOWN_THUMB_RESIZE, $this->getPartnerId()))
  857. {
  858. $subType = entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA;
  859. if($this->getType() == entryType::MEDIA_CLIP && $this->getMediaType() != entry::ENTRY_MEDIA_TYPE_IMAGE)
  860. $subType = entry::FILE_SYNC_ENTRY_SUB_TYPE_THUMB;
  861. $syncKey = $this->getSyncKey($subType);
  862. $fileSync = null;
  863. $serveRemote = false;
  864. $partner = PartnerPeer::retrieveByPK($this->getPartnerId());
  865. switch($partner->getStorageServePriority())
  866. {
  867. case StorageProfile::STORAGE_SERVE_PRIORITY_EXTERNAL_ONLY:
  868. $serveRemote = true;
  869. $fileSync = kFileSyncUtils::getReadyExternalFileSyncForKey($syncKey);
  870. if(!$fileSync)
  871. return null;
  872. break;
  873. case StorageProfile::STORAGE_SERVE_PRIORITY_EXTERNAL_FIRST:
  874. $fileSync = kFileSyncUtils::getReadyExternalFileSyncForKey($syncKey);
  875. if($fileSync)
  876. $serveRemote = true;
  877. break;
  878. case StorageProfile::STORAGE_SERVE_PRIORITY_KALTURA_FIRST:
  879. $fileSync = kFileSyncUtils::getReadyInternalFileSyncForKey($syncKey);
  880. if($fileSync)
  881. break;
  882. $fileSync = kFileSyncUtils::getReadyExternalFileSyncForKey($syncKey);
  883. if(!$fileSync)
  884. return null;
  885. $serveRemote = true;
  886. break;
  887. case StorageProfile::STORAGE_SERVE_PRIORITY_KALTURA_ONLY:
  888. $fileSync = kFileSyncUtils::getReadyInternalFileSyncForKey($syncKey);
  889. if(!$fileSync)
  890. return null;
  891. break;
  892. }
  893. if($serveRemote && $fileSync)
  894. return $fileSync->getExternalUrl();
  895. }
  896. //$path = $this->getThumbnailPath ( $version );
  897. $path = myPartnerUtils::getUrlForPartner( $this->getPartnerId() , $this->getSubpId() ) . "/thumbnail/entry_id/" . $this->getId() ;
  898. $current_version = $this->getThumbnailVersion();
  899. if ( $version )
  900. $path .= "/version/$version";
  901. else
  902. $path .= "/version/$current_version";
  903. $url = myPartnerUtils::getCdnHost($this->getPartnerId()) . $path ;
  904. return $url;
  905. }
  906. public function getBigThumbnailPath($revertToSmall = false , $version = NULL )
  907. {
  908. if ( $this->getMediaType() == self::ENTRY_MEDIA_TYPE_IMAGE )
  909. {
  910. // we dont need to make a copy for the big thumbnail - we can use the image itself
  911. return $this->getDataPath();
  912. }
  913. $path = myContentStorage::getGeneralEntityPath("entry/bigthumbnail", $this->getIntId(), $this->getId(), $this->getThumbnail() , $version );
  914. if ($revertToSmall && !file_exists(myContentStorage::getFSContentRootPath().$path))
  915. $path = $this->getThumbnailPath();
  916. return $path;
  917. }
  918. public function getBigThumbnailUrl( $version = NULL )
  919. {
  920. $path = $this->getBigThumbnailPath ( $version );
  921. $url = requestUtils::getRequestHost() . $path ;
  922. return $url;
  923. }
  924. /**
  925. * This function sets and returns a new path for a requested content entity.
  926. * @param string $filename = the original fileName from which the extension is cut.
  927. * @return string the content file name
  928. */
  929. public function setThumbnail($filename , $force = false )
  930. {
  931. if ( $force )
  932. $data = $filename;
  933. else
  934. $data = myContentStorage::generateRandomFileName($filename, $this->getThumbnail());
  935. parent::setThumbnail($data);
  936. return $this->getThumbnail();
  937. }
  938. public function setTags($tags , $update_db = true )
  939. {
  940. if ($this->tags !== $tags) {
  941. $tags = ktagword::updateTags($this->tags, $tags , $update_db );
  942. parent::setTags( trim($tags));
  943. }
  944. }
  945. public function setAdminTags($tags)
  946. {
  947. if ( $tags === null ) return ;
  948. if ( $tags == "" || $this->getAdminTags() !== $tags ) {
  949. parent::setAdminTags(trim(ktagword::fixAdminTags( $tags)));
  950. }
  951. }
  952. /**
  953. * Set the categories (use only the most child categories)
  954. *
  955. * @param string $categories
  956. */
  957. public function setCategories($newCats)
  958. {
  959. $newCats = explode(self::ENTRY_CATEGORY_SEPARATOR, $newCats);
  960. $this->trimCategories($newCats);
  961. if (count($newCats) > self::MAX_CATEGORIES_PER_ENTRY)
  962. throw new kCoreException("Max number of allowed entries per category was reached", kCoreException::MAX_CATEGORIES_PER_ENTRY);
  963. // remove duplicates
  964. $newCats = array_unique($newCats);
  965. // leave only the most child categories
  966. $mostChildCats = array();
  967. foreach($newCats as $currentCat)
  968. {
  969. $unsetI = false;
  970. $add = true;
  971. foreach($mostChildCats as $i => $mostChild)
  972. {
  973. if (strpos($currentCat, $mostChild.categoryPeer::CATEGORY_SEPARATOR) === 0)
  974. {
  975. $unsetI = $i;
  976. break;
  977. }
  978. if (strpos($mostChild, $currentCat.categoryPeer::CATEGORY_SEPARATOR) === 0)
  979. {
  980. $add = false;
  981. }
  982. }
  983. if ($unsetI !== false)
  984. unset($mostChildCats[$unsetI]);
  985. if ($add)
  986. $mostChildCats[] = $currentCat;
  987. }
  988. $this->old_categories = $this->categories;
  989. parent::setCategories(implode(",", $mostChildCats));
  990. $this->is_categories_modified = true;
  991. }
  992. public function renameCategory($oldFullName, $newFullName)
  993. {
  994. $categories = explode(self::ENTRY_CATEGORY_SEPARATOR, $this->categories);
  995. foreach($categories as &$category)
  996. {
  997. $category = preg_replace("/^".$oldFullName."/", $newFullName, $category);
  998. }
  999. $this->categories = implode(self::ENTRY_CATEGORY_SEPARATOR, $categories);
  1000. $this->old_categories = $this->categories; // so the sync won't increment the count on categories
  1001. $this->modifiedColumns[] = entryPeer::CATEGORIES;
  1002. $this->is_categories_modified = true;
  1003. }
  1004. public function removeCategory($fullName)
  1005. {
  1006. $this->old_categories = $this->categories;
  1007. $categories = explode(self::ENTRY_CATEGORY_SEPARATOR, $this->categories);
  1008. $newCategories = array();
  1009. foreach($categories as $category)
  1010. {
  1011. if (!preg_match("/^".$fullName."/", $category))
  1012. $newCategories[] = $category;
  1013. }
  1014. $this->categories = implode(self::ENTRY_CATEGORY_SEPARATOR, $newCategories);
  1015. $this->modifiedColumns[] = entryPeer::CATEGORIES;
  1016. $this->is_categories_modified = true;
  1017. }
  1018. private function trimCategories(&$categories)
  1019. {
  1020. $trimedCategories = array();
  1021. foreach($categories as &$cat)
  1022. {
  1023. $cat = trim($cat);
  1024. $catExploded = explode(categoryPeer::CATEGORY_SEPARATOR, $cat);
  1025. $fixedCat = array();
  1026. foreach($catExploded as $subCat)
  1027. {
  1028. if (strlen($subCat) > 0)
  1029. {
  1030. $fixedCat[] = $subCat;
  1031. }
  1032. }
  1033. $cat = implode($fixedCat, categoryPeer::CATEGORY_SEPARATOR);
  1034. if (strlen($cat) > 0)
  1035. $trimedCategories[] = $cat;
  1036. }
  1037. $categories = $trimedCategories;
  1038. }
  1039. public function getCreatedAtAsInt ()
  1040. {
  1041. return $this->getCreatedAt( null );
  1042. }
  1043. public function getUpdateAtAsInt ()
  1044. {
  1045. return $this->getUpdatedAt( null );
  1046. }
  1047. public function getFormattedCreatedAt( $format = dateUtils::KALTURA_FORMAT )
  1048. {
  1049. return dateUtils::formatKalturaDate( $this , 'getCreatedAt' , $format );
  1050. }
  1051. public function getFormattedUpdatedAt( $format = dateUtils::KALTURA_FORMAT )
  1052. {
  1053. return dateUtils::formatKalturaDate( $this , 'getUpdatedAt' , $format );
  1054. }
  1055. public function getAppearsIn ( )
  1056. {
  1057. if ( $this->appears_in == NULL )
  1058. {
  1059. if ( $this->getkshow() )
  1060. {
  1061. $this->setAppearsIn ( $this->getkshow()->getName() );
  1062. }
  1063. else
  1064. {
  1065. return ""; // strange - no kshow ! must be a dangling entry
  1066. }
  1067. }
  1068. return $this->appears_in;
  1069. }
  1070. public function setAppearsIn ( $name )
  1071. {
  1072. $this->appears_in = $name;
  1073. }
  1074. public function getWidgetImagePath()
  1075. {
  1076. return myContentStorage::getGeneralEntityPath("entry/widget", $this->getIntId(), $this->getId(), ".gif" );
  1077. }
  1078. // when calling duration - use seconds rather than msecs
  1079. public function getDuration ()
  1080. {
  1081. $t = $this->getLengthInMsecs();
  1082. if ( $t == null ) return 0;
  1083. return ( $t / 1000 );
  1084. }
  1085. /**
  1086. * returns the duration as int
  1087. * @return int
  1088. */
  1089. public function getDurationInt()
  1090. {
  1091. return (int)round($this->getDuration());
  1092. }
  1093. /**
  1094. * @return string
  1095. */
  1096. public function getDurationType()
  1097. {
  1098. return entryPeer::getDurationType($this->getDurationInt());
  1099. }
  1100. public function getMetadata( $version = null)
  1101. {
  1102. if ( $this->getMediaType() != entry::ENTRY_MEDIA_TYPE_SHOW )
  1103. {
  1104. return null;
  1105. }
  1106. if ( $version <= 0 ) $version=null;
  1107. $sync_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $version );
  1108. $content = kFileSyncUtils::file_get_contents( $sync_key , true , false ); // don't be strict when fetching metadata
  1109. if ( $content )
  1110. return $content;
  1111. else
  1112. return "<xml></xml>";
  1113. }
  1114. // will place the metadata in the entry (as long as it's of type show)
  1115. // TODO - maybe change this because entries can change their types - intro of type video can become a show !!
  1116. // by default will override the existing file - this will be starnge because there is not supposed to be a file with that name yet -
  1117. // all the indexes up to this point where smaller then this futurae one.
  1118. /**
  1119. Writes the content of the metadata to a new file.
  1120. Returns the number of bytes written to disk
  1121. */
  1122. // TODO - is this really what should be returned ??
  1123. public function setMetadata ( $kshow , $content , $override_existing=true , $total_duration = null , $specific_version = null )
  1124. {
  1125. if ( $this->getMediaType() != entry::ENTRY_MEDIA_TYPE_SHOW )
  1126. {
  1127. return null;
  1128. }
  1129. // TODO - better to call this with slight modifications
  1130. //myMetadataUtils::setMetadata ($content, $kshow, $this , $override_existing );
  1131. if ( $specific_version == null )
  1132. {
  1133. // increment the counter of the file
  1134. $this->setData ( parent::getData() );
  1135. }
  1136. // check that the file of the desired version really exists
  1137. // $content_dir = myContentStorage::getFSContentRootPath();
  1138. // $file_name = $content_dir . $this->getDataPath( $specific_version ); // replaced__getDataPath
  1139. $sync_key = $this->getSyncKey ( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $specific_version );
  1140. if ( $override_existing || ! kFileSyncUtils::file_exists( $sync_key ,false ) )
  1141. {
  1142. $duration = $total_duration ? $total_duration : myMetadataUtils::getDuration ( $content );
  1143. $this->setLengthInMsecs ( $duration * 1000 );
  1144. $total_duration = null;
  1145. $editor_type = null;
  1146. $version = myContentStorage::getVersion( kFileSyncUtils::getReadyLocalFilePathForKey ( $sync_key ) );
  1147. $fixed_content = myFlvStreamer::fixMetadata( $content , $version, $total_duration , $editor_type);
  1148. $this->setModifiedAt(time()); // update the modified_at date
  1149. $this->save();
  1150. $sync_key = $this->getSyncKey ( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $version );
  1151. // TODO: here we assume we are UPDATING an exising version of the file - make sure all the following functions are tolerant.
  1152. kFileSyncUtils::file_put_contents( $sync_key , $fixed_content , false ); // replaced__setFileContent
  1153. // update the roughcut_entry table
  1154. if ( $kshow != null ) $kshow_id = $kshow->getId();
  1155. else $kshow_id = $this->getKshowId();
  1156. $all_entries_for_roughcut = myMetadataUtils::getAllEntries ( $fixed_content );
  1157. roughcutEntry::updateRoughcut( $this->getId() , $version , $kshow_id , $all_entries_for_roughcut );
  1158. return ;
  1159. }
  1160. else
  1161. {
  1162. // no need to save changes - why increment the count if failed ??
  1163. return -1;
  1164. }
  1165. }
  1166. public function fixMetadata ( $increment_version = true , $content = null , $total_duration = null , $specific_version = null )
  1167. {
  1168. // check that the file of the desired version really exists
  1169. $content_dir = myContentStorage::getFSContentRootPath();
  1170. if ( !$content ) $content = $this->getMetadata( $specific_version );
  1171. if ( $increment_version )
  1172. {
  1173. // increment the counter of the file
  1174. $this->setData ( parent::getData() );
  1175. }
  1176. $file_name = kFileSyncUtils::getLocalFilePathForKey($this->getSyncKey(entry::FILE_SYNC_ENTRY_SUB_TYPE_DATA, $specific_version)); // replaced__getDataPath
  1177. $duration = $total_duration ? $total_duration : myMetadataUtils::getDuration ( $content );
  1178. $this->setLengthInMsecs ( $duration * 1000 );
  1179. $total_duration = null;
  1180. $editor_type = null;
  1181. $version = myContentStorage::getVersion($file_name);
  1182. $fixed_content = myFlvStreamer::fixMetadata( $content , $version, $total_duration , $editor_type);
  1183. $this->save();
  1184. $sync_key = $this->getSyncKey ( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $version );
  1185. kFileSyncUtils::file_put_contents( $sync_key , $fixed_content , false ); // replaced__setFileContent
  1186. return $fixed_content;
  1187. }
  1188. public function getVersion()
  1189. {
  1190. $version = parent::getData();
  1191. if ($version)
  1192. {
  1193. $c = strstr($version, '^') ? '^' : '&';
  1194. $parts = explode( $c, $version);
  1195. }
  1196. else
  1197. $parts = array('');
  1198. if (strlen($parts[0]))
  1199. $current_version = pathinfo($parts[0], PATHINFO_FILENAME) ;
  1200. else
  1201. $current_version = 0;
  1202. return $current_version;
  1203. }
  1204. public function getThumbnailVersion()
  1205. {
  1206. // For image entry, the data file sync sub type is used as thumbnail
  1207. if($this->getType() == entryType::MEDIA_CLIP && $this->getMediaType() == self::ENTRY_MEDIA_TYPE_IMAGE)
  1208. return $this->getVersion();
  1209. $version = parent::getThumbnail();
  1210. if ($version)
  1211. {
  1212. $c = strstr($version, '^') ? '^' : '&';
  1213. $parts = explode( $c, $version);
  1214. }
  1215. else
  1216. $parts = array('');
  1217. if (strlen($parts[0]))
  1218. $current_version = pathinfo($parts[0], PATHINFO_FILENAME) ;
  1219. else
  1220. $current_version = 0;
  1221. return $current_version;
  1222. }
  1223. // makes a copy of the desired version from the past as the next coming version of the entry
  1224. // $desired_version = 100003, current_version = 100006 -> will conpy the content of <id>_100003.xxx -> <id>_1000007.xxx and will increment the version
  1225. // so current_version = 100007.xxx now
  1226. public function rollbackVersion( $desired_version )
  1227. {
  1228. // don't duplicate if staying in hte same version
  1229. $current_version = $this->getVersion();
  1230. if ( $desired_version == $current_version)
  1231. return $current_version;
  1232. $source_syc_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA , $desired_version );
  1233. /*
  1234. // check that the file of the desired version really exists
  1235. $content = myContentStorage::getFSContentRootPath();
  1236. $path = $content . $this->getDataPath( $desired_version ); // replaced__getDataPath
  1237. if ( ! file_exists( $path ))
  1238. {
  1239. return null;
  1240. }
  1241. */
  1242. // increment the counter of the file
  1243. $this->setData ( parent::getData() );
  1244. $target_syc_key = $this->getSyncKey( self::FILE_SYNC_ENTRY_SUB_TYPE_DATA );
  1245. /*
  1246. $new_path = $content . $this->getDataPath( ); //replaced__getDataPath
  1247. // make a copy
  1248. kFile::moveFile( $path , $new_path , true , true );
  1249. */
  1250. kFileSyncUtils::copy( $source_syc_key , $target_syc_key );
  1251. $this->save();
  1252. // return the new version
  1253. return $this->getVersion();
  1254. }
  1255. // if has status self::ENTRY_S
  1256. public function getImportInfo ()
  1257. {
  1258. if ( $this->getStatus() == entryStatus::IMPORT )
  1259. {
  1260. $c = new Criteria();
  1261. $c->add ( BatchJobPeer::ENTRY_ID , $this->getId() );
  1262. $c->addDescendingOrderByColumn( BatchJobPeer::ID );
  1263. $import = BatchJobPeer::doSelectOne ( $c );
  1264. return $import;
  1265. }
  1266. return null;
  1267. }
  1268. public function getDisplayCredit ( )
  1269. {
  1270. if ($this->getCredit())
  1271. return $this->getCredit();
  1272. else if ( $this->getScreenName() )
  1273. {
  1274. return $this->getScreenName();
  1275. }
  1276. else
  1277. {
  1278. $kuser = $this->getkuser();
  1279. return ( $kuser ? $kuser->getScreenName() : "" );
  1280. }
  1281. }
  1282. public function moderate ($new_moderation_status , $fix_moderation_objects = false )
  1283. {
  1284. $error_msg = "Moderation status [$new_moderation_status] not supported by entry";
  1285. switch($new_moderation_status)
  1286. {
  1287. case moderation::MODERATION_STATUS_APPROVED:
  1288. // a new notification that is sent when an entry was founc to be ok after moderation
  1289. myNotificationMgr::createNotification(kNotificationJobData::NOTIFICATION_TYPE_ENTRY_UPDATE , $this );
  1290. break;
  1291. case moderation::MODERATION_STATUS_BLOCK:
  1292. myNotificationMgr::createNotification(kNotificationJobData::NOTIFICATION_TYPE_ENTRY_BLOCK , $this->getid());
  1293. break;
  1294. case moderation::MODERATION_STATUS_DELETE:
  1295. // physical disk deletion
  1296. myEntryUtils::deleteEntry($this);
  1297. myNotificationMgr::createNotification(kNotificationJobData::NOTIFICATION_TYPE_ENTRY_BLOCK , $this->getid());
  1298. break;
  1299. case moderation::MODERATION_STATUS_PENDING:
  1300. // $this->setStatus(entryStatus::MODERATE);
  1301. // throw new Exception($error_msg);
  1302. break;
  1303. case moderation::MODERATION_STATUS_REVIEW:
  1304. // in this case the status of the entry should not change
  1305. // throw new Exception($error_msg);
  1306. break;
  1307. default:
  1308. throw new Exception($error_msg);
  1309. break;
  1310. }
  1311. $this->setModerationStatus( $new_moderation_status );
  1312. // TODO - fix loop of updating from entry ot moderation back to entry ...
  1313. if ( $fix_moderation_objects )
  1314. {
  1315. myModerationMgr::updateModerationsForObject ( $this , $new_moderation_status );
  1316. }
  1317. $this->save();
  1318. }
  1319. public function setEditorType ( $editor_type ) { $this->putInCustomData ( "editor_type" , $editor_type ); }
  1320. public function getEditorType ( )
  1321. {
  1322. if ( $this->getType() != entryType::MIX ) return null;
  1323. $res = $this->getFromCustomData( "editor_type" );
  1324. if ( $res == null ) return "Keditor"; // no value means Keditor == advanced
  1325. return $res;
  1326. }
  1327. public function setConversionProfileId($conversion_quality)
  1328. {
  1329. $this->setConversionQuality($conversion_quality);
  1330. }
  1331. public function setConversionQuality($conversion_quality)
  1332. {
  1333. parent::setConversionProfileId($conversion

Large files files are truncated, but you can click here to view the full file