2010-12-07 20:19:27 +01:00
< ? php
/**
2021-10-11 16:10:47 +02:00
* Application_Model_StoredFile class .
2010-12-07 20:19:27 +01:00
*
* @ copyright 2010 Sourcefabric O . P . S .
2022-08-25 16:25:54 +02:00
* @ license https :// www . gnu . org / licenses / gpl . txt
2021-10-11 16:10:47 +02:00
*
2010-12-07 20:19:27 +01:00
* @ see MetaData
*/
2012-07-16 03:17:13 +02:00
class Application_Model_StoredFile
{
2010-12-07 20:19:27 +01:00
/**
2011-06-08 10:15:35 +02:00
* @ holds propel database object
2021-10-11 16:10:47 +02:00
*
2015-07-07 19:54:19 +02:00
* @ var CcFiles
2011-06-08 10:15:35 +02:00
*/
private $_file ;
2010-12-07 20:19:27 +01:00
2013-04-20 02:10:51 +02:00
/**
* @ holds PDO object reference
*/
private $_con ;
2010-12-07 20:19:27 +01:00
/**
2021-10-11 16:10:47 +02:00
* array of db metadata -> propel .
2010-12-07 20:19:27 +01:00
*/
2021-10-11 16:10:47 +02:00
private $_dbMD = [
'track_title' => 'DbTrackTitle' ,
'artist_name' => 'DbArtistName' ,
'album_title' => 'DbAlbumTitle' ,
'genre' => 'DbGenre' ,
'mood' => 'DbMood' ,
'track_number' => 'DbTrackNumber' ,
'bpm' => 'DbBpm' ,
'label' => 'DbLabel' ,
'composer' => 'DbComposer' ,
'encoded_by' => 'DbEncodedBy' ,
'conductor' => 'DbConductor' ,
'year' => 'DbYear' ,
'info_url' => 'DbInfoUrl' ,
'isrc_number' => 'DbIsrcNumber' ,
'copyright' => 'DbCopyright' ,
'length' => 'DbLength' ,
'bit_rate' => 'DbBitRate' ,
'sample_rate' => 'DbSampleRate' ,
'mime' => 'DbMime' ,
2022-03-14 11:15:04 +01:00
// "md5" => "DbMd5",
2021-10-11 16:10:47 +02:00
'ftype' => 'DbFtype' ,
'language' => 'DbLanguage' ,
'replay_gain' => 'DbReplayGain' ,
'owner_id' => 'DbOwnerId' ,
'cuein' => 'DbCueIn' ,
'cueout' => 'DbCueOut' ,
'description' => 'DbDescription' ,
'artwork' => 'DbArtwork' ,
2022-06-08 16:31:01 +02:00
'track_type_id' => 'DbTrackTypeId' ,
2021-10-11 16:10:47 +02:00
];
public function __construct ( $file , $con )
{
2013-04-20 02:10:51 +02:00
$this -> _file = $file ;
$this -> _con = $con ;
}
2011-06-08 11:59:48 +02:00
public function getId ()
{
2011-06-08 10:15:35 +02:00
return $this -> _file -> getDbId ();
}
2010-12-07 20:19:27 +01:00
2011-06-08 11:59:48 +02:00
public function getFormat ()
{
return $this -> _file -> getDbFtype ();
}
2015-06-24 21:46:53 +02:00
/**
* @ return CcFiles
*/
2012-07-16 03:17:13 +02:00
public function getPropelOrm ()
{
2011-06-20 20:10:33 +02:00
return $this -> _file ;
}
2011-06-08 11:59:48 +02:00
public function setFormat ( $p_format )
{
$this -> _file -> setDbFtype ( $p_format );
}
2012-08-29 16:58:03 +02:00
2012-07-20 00:07:39 +02:00
/* This function is only called after liquidsoap
* has notified that a track has started playing .
*/
public function setLastPlayedTime ( $p_now )
{
$this -> _file -> setDbLPtime ( $p_now );
/* Normally we would only call save after all columns have been set
2012-08-29 16:58:03 +02:00
* like in setDbColMetadata () . But since we are only setting one
2012-07-20 00:07:39 +02:00
* column in this case it is OK .
*/
$this -> _file -> save ();
}
2011-06-08 11:59:48 +02:00
2021-10-11 16:10:47 +02:00
public static function createWithFile ( $f , $con )
{
return new Application_Model_StoredFile ( $f , $con );
2012-09-12 00:22:46 +02:00
}
2010-12-07 20:19:27 +01:00
/**
2011-06-08 10:15:35 +02:00
* Set multiple metadata values using defined metadata constants .
2010-12-07 20:19:27 +01:00
*
2011-06-08 10:15:35 +02:00
* @ param array $p_md
2022-09-21 00:44:42 +02:00
* example : $p_md [ 'MDATA_KEY_URL' ] = 'https://example.org'
2010-12-07 20:19:27 +01:00
*/
2021-10-11 16:10:47 +02:00
public function setMetadata ( $p_md = null )
2010-12-07 20:19:27 +01:00
{
2011-06-08 10:15:35 +02:00
if ( is_null ( $p_md )) {
$this -> setDbColMetadata ();
2012-07-16 03:17:13 +02:00
} else {
2021-10-11 16:10:47 +02:00
$dbMd = [];
2012-07-11 00:51:32 +02:00
2021-10-11 16:10:47 +02:00
if ( isset ( $p_md [ 'MDATA_KEY_YEAR' ])) {
2012-09-19 23:39:30 +02:00
// We need to make sure to clean this value before
// inserting into database. If value is outside of range
// [-2^31, 2^31-1] then postgresl will throw error when
// trying to retrieve this value. We could make sure
// number is within these bounds, but simplest is to do
// substring to 4 digits (both values are garbage, but
// at least our new garbage value won't cause errors).
// If the value is 2012-01-01, then substring to first 4
// digits is an OK result. CC-3771
2012-07-11 00:51:32 +02:00
2021-10-11 16:10:47 +02:00
$year = $p_md [ 'MDATA_KEY_YEAR' ];
2012-07-11 00:51:32 +02:00
2012-07-16 03:17:13 +02:00
if ( strlen ( $year ) > 4 ) {
2012-06-04 17:43:41 +02:00
$year = substr ( $year , 0 , 4 );
}
2012-07-16 03:17:13 +02:00
if ( ! is_numeric ( $year )) {
2012-06-04 17:43:41 +02:00
$year = 0 ;
}
2021-10-11 16:10:47 +02:00
$p_md [ 'MDATA_KEY_YEAR' ] = $year ;
2012-06-04 17:43:41 +02:00
}
2012-07-11 00:51:32 +02:00
2021-10-11 16:10:47 +02:00
// Translate metadata attributes from media monitor (MDATA_KEY_*)
// to their counterparts in constants.php (usually the column names)
2013-01-10 17:49:02 +01:00
$track_length = $p_md [ 'MDATA_KEY_DURATION' ];
$track_length_in_sec = Application_Common_DateHelper :: calculateLengthInSeconds ( $track_length );
2011-06-08 10:15:35 +02:00
foreach ( $p_md as $mdConst => $mdValue ) {
2012-07-16 03:17:13 +02:00
if ( defined ( $mdConst )) {
2021-10-11 16:10:47 +02:00
if ( $mdConst == 'MDATA_KEY_CUE_OUT' ) {
2013-01-15 17:16:50 +01:00
if ( $mdValue == '0.0' ) {
$mdValue = $track_length_in_sec ;
} else {
$this -> _file -> setDbSilanCheck ( true ) -> save ();
}
2013-01-10 17:49:02 +01:00
}
2012-05-15 21:17:19 +02:00
$dbMd [ constant ( $mdConst )] = $mdValue ;
}
2011-06-08 10:15:35 +02:00
}
$this -> setDbColMetadata ( $dbMd );
2010-12-07 20:19:27 +01:00
}
}
2011-06-08 10:15:35 +02:00
/**
* Set multiple metadata values using database columns as indexes .
*
* @ param array $p_md
2022-09-21 00:44:42 +02:00
* example : $p_md [ 'url' ] = 'https://www.example.com'
2011-06-08 10:15:35 +02:00
*/
2021-10-11 16:10:47 +02:00
public function setDbColMetadata ( $p_md = null )
2010-12-07 20:19:27 +01:00
{
2011-06-08 10:15:35 +02:00
if ( is_null ( $p_md )) {
foreach ( $this -> _dbMD as $dbColumn => $propelColumn ) {
2021-10-11 16:10:47 +02:00
$method = " set { $propelColumn } " ;
$this -> _file -> { $method }( null );
2011-06-08 10:15:35 +02:00
}
2012-07-16 03:17:13 +02:00
} else {
2019-03-05 16:00:54 +01:00
// in order to edit the owner of a file we see if owner_id exists in the track form metadata otherwise
// we determine it via the algorithm below
if ( ! array_key_exists ( 'owner_id' , $p_md )) {
$owner = $this -> _file -> getFkOwner ();
// if owner_id is already set we don't want to set it again.
if ( ! $owner ) { // no owner detected, we try to assign one.
// if MDATA_OWNER_ID is not set then we default to the
// first admin user we find
if ( ! array_key_exists ( 'owner_id' , $p_md )) {
2022-03-14 11:15:04 +01:00
// $admins = Application_Model_User::getUsers(array('A'));
2021-10-11 16:10:47 +02:00
$admins = array_merge (
Application_Model_User :: getUsersOfType ( 'A' ) -> getData (),
Application_Model_User :: getUsersOfType ( 'S' ) -> getData ()
);
2019-03-05 16:00:54 +01:00
if ( count ( $admins ) > 0 ) { // found admin => pick first one
$owner = $admins [ 0 ];
}
} // get the user by id and set it like that
else {
$user = CcSubjsQuery :: create ()
2022-01-23 19:15:55 +01:00
-> findPk ( $p_md [ 'owner_id' ]);
2019-03-05 16:00:54 +01:00
if ( $user ) {
$owner = $user ;
}
2012-08-23 22:46:35 +02:00
}
2019-03-05 16:00:54 +01:00
if ( $owner ) {
$this -> _file -> setDbOwnerId ( $owner -> getDbId ());
} else {
Logging :: info ( " Could not find suitable owner for file
'" . $p_md[' filepath '] . "' " );
2012-08-23 22:46:35 +02:00
}
}
2012-08-27 21:09:55 +02:00
}
2011-06-08 10:15:35 +02:00
foreach ( $p_md as $dbColumn => $mdValue ) {
2012-08-24 18:38:33 +02:00
// don't blank out name, defaults to original filename on first
// insertion to database.
2021-10-11 16:10:47 +02:00
if ( $dbColumn == 'track_title' && ( is_null ( $mdValue ) || $mdValue == '' )) {
2011-06-15 09:19:41 +02:00
continue ;
}
2019-09-20 02:07:50 +02:00
2014-11-18 16:32:03 +01:00
// Bpm gets POSTed as a string type. With Propel 1.6 this value
// was casted to an integer type before saving it to the db. But
// Propel 1.7 does not do this
2021-10-11 16:10:47 +02:00
if ( $dbColumn == 'bpm' ) {
2014-11-18 16:32:03 +01:00
$mdValue = ( int ) $mdValue ;
}
2021-10-11 16:10:47 +02:00
// TODO : refactor string evals
2011-06-21 10:24:02 +02:00
if ( isset ( $this -> _dbMD [ $dbColumn ])) {
$propelColumn = $this -> _dbMD [ $dbColumn ];
2021-10-11 16:10:47 +02:00
$method = " set { $propelColumn } " ;
2013-05-28 20:27:59 +02:00
2012-10-16 21:56:03 +02:00
/* We need to set track_number to null if it is an empty string
* because propel defaults empty strings to zeros */
2021-10-11 16:10:47 +02:00
if ( $dbColumn == 'track_number' && empty ( $mdValue )) {
$mdValue = null ;
}
2022-07-27 09:52:09 +02:00
// We need to set track_type_id to null if it is an empty string or 0
if ( $dbColumn == 'track_type_id' && ( $mdValue == 0 || empty ( $mdValue ))) {
$mdValue = null ;
}
2021-10-11 16:10:47 +02:00
$this -> _file -> { $method }( $mdValue );
2011-06-21 10:24:02 +02:00
}
2011-06-08 10:15:35 +02:00
}
2010-12-07 20:19:27 +01:00
}
2012-07-20 00:11:31 +02:00
2021-10-11 16:10:47 +02:00
$this -> _file -> setDbMtime ( new DateTime ( 'now' , new DateTimeZone ( 'UTC' )));
2013-04-20 02:10:51 +02:00
$this -> _file -> save ( $this -> _con );
2010-12-07 20:19:27 +01:00
}
/**
2021-10-11 16:10:47 +02:00
* Set metadata element value .
2010-12-07 20:19:27 +01:00
*
2023-05-25 15:06:18 +02:00
* @ param mixed $p_category
* @ param mixed $p_value
2010-12-07 20:19:27 +01:00
*/
public function setMetadataValue ( $p_category , $p_value )
{
2011-07-15 23:35:16 +02:00
// constant() was used because it gets quoted constant name value from
// api_client.py. This is the wrapper funtion
2011-06-08 10:15:35 +02:00
$this -> setDbColMetadataValue ( constant ( $p_category ), $p_value );
2010-12-07 20:19:27 +01:00
}
/**
2021-10-11 16:10:47 +02:00
* Set metadata element value .
2010-12-07 20:19:27 +01:00
*
2023-05-25 15:06:18 +02:00
* @ param mixed $p_category
* @ param mixed $p_value
2010-12-07 20:19:27 +01:00
*/
2011-06-08 10:15:35 +02:00
public function setDbColMetadataValue ( $p_category , $p_value )
2010-12-07 20:19:27 +01:00
{
2022-03-14 11:15:04 +01:00
// don't blank out name, defaults to original filename on first insertion to database.
2021-10-11 16:10:47 +02:00
if ( $p_category == 'track_title' && ( is_null ( $p_value ) || $p_value == '' )) {
2011-06-15 09:19:41 +02:00
return ;
}
2011-07-15 23:35:16 +02:00
if ( isset ( $this -> _dbMD [ $p_category ])) {
2012-09-11 22:25:45 +02:00
// TODO : fix this crust -- RG
2011-06-21 10:24:02 +02:00
$propelColumn = $this -> _dbMD [ $p_category ];
2021-10-11 16:10:47 +02:00
$method = " set { $propelColumn } " ;
$this -> _file -> { $method }( $p_value );
2011-06-21 10:24:02 +02:00
$this -> _file -> save ();
}
2010-12-07 20:19:27 +01:00
}
2011-06-08 10:15:35 +02:00
/**
* Get metadata as array , indexed by the column names in the database .
*
* @ return array
*/
public function getDbColMetadata ()
2010-12-07 20:19:27 +01:00
{
2021-10-11 16:10:47 +02:00
$md = [];
2011-06-08 10:15:35 +02:00
foreach ( $this -> _dbMD as $dbColumn => $propelColumn ) {
2021-10-11 16:10:47 +02:00
$method = " get { $propelColumn } " ;
$md [ $dbColumn ] = $this -> _file -> { $method }();
2010-12-07 23:29:28 +01:00
}
2011-06-08 10:15:35 +02:00
return $md ;
2010-12-07 20:19:27 +01:00
}
2011-06-15 14:20:14 +02:00
/**
* Get metadata as array , indexed by the constant names .
*
* @ return array
*/
public function getMetadata ()
{
$c = get_defined_constants ( true );
2021-10-11 16:10:47 +02:00
$md = [];
2012-07-11 00:51:32 +02:00
/* Create a copy of dbMD here and create a " filepath " key inside of
2012-05-04 18:02:42 +02:00
* it . The reason we do this here , instead of creating this key inside
2012-07-11 00:51:32 +02:00
* dbMD is because " filepath " isn 't really metadata, and we don' t want
2012-05-04 18:02:42 +02:00
* filepath updated everytime the metadata changes . Also it needs extra
2012-07-11 00:51:32 +02:00
* processing before we can write it to the database ( needs to be split
2012-05-04 18:02:42 +02:00
* into base and relative path )
* */
$dbmd_copy = $this -> _dbMD ;
2021-10-11 16:10:47 +02:00
$dbmd_copy [ 'filepath' ] = 'DbFilepath' ;
2011-06-15 14:20:14 +02:00
foreach ( $c [ 'user' ] as $constant => $value ) {
if ( preg_match ( '/^MDATA_KEY/' , $constant )) {
2012-05-04 18:02:42 +02:00
if ( isset ( $dbmd_copy [ $value ])) {
2021-10-11 16:10:47 +02:00
$propelColumn = $dbmd_copy [ $value ];
$method = " get { $propelColumn } " ;
$md [ $constant ] = $this -> _file -> { $method }();
2011-06-15 14:20:14 +02:00
}
}
}
return $md ;
}
2010-12-07 20:19:27 +01:00
/**
* Returns an array of playlist objects that this file is a part of .
2021-10-11 16:10:47 +02:00
*
2010-12-07 20:19:27 +01:00
* @ return array
*/
2012-07-16 03:17:13 +02:00
public function getPlaylists ()
{
2012-04-01 21:51:03 +02:00
$con = Propel :: getConnection ();
2012-09-04 23:21:59 +02:00
2021-10-11 16:10:47 +02:00
$sql = <<< 'SQL'
2012-09-11 22:20:59 +02:00
SELECT playlist_id
FROM cc_playlist
WHERE file_id = : file_id
SQL ;
2012-09-04 23:21:59 +02:00
$stmt = $con -> prepare ( $sql );
$stmt -> bindParam ( ':file_id' , $this -> id , PDO :: PARAM_INT );
2013-05-28 20:27:59 +02:00
2012-09-04 23:21:59 +02:00
if ( $stmt -> execute ()) {
$ids = $stmt -> fetchAll ();
} else {
$msg = implode ( ',' , $stmt -> errorInfo ());
2021-10-11 16:10:47 +02:00
throw new Exception ( " Error: { $msg } " );
2012-09-04 23:21:59 +02:00
}
2010-12-07 20:19:27 +01:00
if ( is_array ( $ids ) && count ( $ids ) > 0 ) {
2021-10-11 16:10:47 +02:00
return array_map ( function ( $id ) {
2013-04-20 02:24:05 +02:00
return Application_Model_Playlist :: RecallById ( $id );
2012-09-11 22:20:59 +02:00
}, $ids );
} else {
2021-10-11 16:10:47 +02:00
return [];
2010-12-07 20:19:27 +01:00
}
}
2019-09-20 02:07:50 +02:00
/**
2014-03-24 22:14:04 +01:00
* Check if the file ( on disk ) corresponding to this class exists or not .
2021-10-11 16:10:47 +02:00
*
* @ return bool true if the file exists , false otherwise
2014-03-24 22:14:04 +01:00
*/
public function existsOnDisk ()
{
$exists = false ;
2021-10-11 16:10:47 +02:00
2014-03-24 22:14:04 +01:00
try {
2015-03-30 17:31:07 +02:00
$filePaths = $this -> getFilePaths ();
$filePath = $filePaths [ 0 ];
$exists = ( file_exists ( $filePath ) && ! is_dir ( $filePath ));
2014-03-24 22:14:04 +01:00
} catch ( Exception $e ) {
return false ;
}
2021-10-11 16:10:47 +02:00
2014-03-24 22:14:04 +01:00
return $exists ;
}
2010-12-07 20:19:27 +01:00
/**
2022-07-04 22:09:14 +02:00
* Deletes the physical file from the local file system .
2011-06-08 11:59:48 +02:00
*
2021-10-11 16:10:47 +02:00
* @ param mixed $quiet
2010-12-07 20:19:27 +01:00
*/
2021-10-11 16:10:47 +02:00
public function delete ( $quiet = false )
2010-12-07 20:19:27 +01:00
{
2011-06-08 11:59:48 +02:00
// Check if the file is scheduled to be played in the future
2015-01-13 21:49:57 +01:00
if ( Application_Model_Schedule :: IsFileScheduledInTheFuture ( $this -> _file -> getCcFileId ())) {
2012-02-05 18:19:22 +01:00
throw new DeleteScheduledFileException ();
2011-06-08 11:59:48 +02:00
}
2015-01-12 22:26:27 +01:00
2024-05-05 22:26:27 +02:00
// if we get here from the REST API, there's no valid user. APIKEY is validated already.
if ( $userInfo = Zend_Auth :: getInstance () -> getStorage () -> read ()) {
// This call will throw "Trying to get property 'id' of non-object"
$user = new Application_Model_User ( $userInfo -> id );
$isAdminOrPM = $user -> isUserType ([ UTYPE_SUPERADMIN , UTYPE_ADMIN , UTYPE_PROGRAM_MANAGER ]);
if ( ! $isAdminOrPM && $this -> getFileOwnerId () != $user -> getId ()) {
throw new FileNoPermissionException ();
}
$file_id = $this -> _file -> getDbId ();
Logging :: info ( $file_id );
Logging :: info ( 'User ' . $user -> getLogin () . ' is deleting file: ' . $this -> _file -> getDbTrackTitle () . ' - file id: ' . $file_id );
} else {
Logging :: info ( 'API Auth is deleting file: ' . $this -> _file -> getDbTrackTitle () . ' - file id: ' . $this -> _file -> getDbId ());
2012-10-31 21:51:29 +01:00
}
2014-10-21 22:05:50 +02:00
$filesize = $this -> _file -> getFileSize ();
2015-02-25 21:09:02 +01:00
if ( $filesize < 0 ) {
2021-10-11 16:10:47 +02:00
throw new Exception ( 'Cannot delete file with filesize ' . $filesize );
2014-10-27 17:39:02 +01:00
}
2014-10-21 22:05:50 +02:00
2022-03-14 11:15:04 +01:00
// Delete the physical file from either the local stor directory
2015-03-03 19:44:42 +01:00
if ( $this -> _file -> getDbImportStatus () == CcFiles :: IMPORT_STATUS_SUCCESS ) {
2015-04-01 22:16:46 +02:00
try {
$this -> _file -> deletePhysicalFile ();
2021-10-11 16:10:47 +02:00
} catch ( Exception $e ) {
2015-05-13 23:58:11 +02:00
if ( $quiet ) {
Logging :: info ( $e );
} else {
2022-03-14 11:15:04 +01:00
// Just log the exception and continue.
2015-05-13 23:58:11 +02:00
Logging :: error ( $e );
}
2015-04-01 22:16:46 +02:00
}
2015-03-03 19:44:42 +01:00
}
2014-10-21 22:05:50 +02:00
2022-03-14 11:15:04 +01:00
// Update the user's disk usage
2014-10-21 22:05:50 +02:00
Application_Model_Preference :: updateDiskUsage ( - 1 * $filesize );
2019-09-20 02:07:50 +02:00
2022-03-14 11:15:04 +01:00
// Explicitly update any playlist's and block's length that contain
// the file getting deleted
2014-10-21 22:05:50 +02:00
self :: updateBlockAndPlaylistLength ( $this -> _file -> getDbId ());
2019-09-20 02:07:50 +02:00
2022-07-04 22:09:14 +02:00
// delete the file record from cc_files
2014-10-21 22:05:50 +02:00
$this -> _file -> delete ();
2014-07-15 23:20:04 +02:00
}
2014-07-15 13:26:39 +02:00
2014-07-15 23:20:04 +02:00
/*
* This function is meant to be called when a file is getting
* deleted from the library . It re - calculates the length of
2019-09-20 02:07:50 +02:00
* all blocks and playlists that contained the deleted file .
2014-07-15 23:20:04 +02:00
*/
2014-07-24 22:56:15 +02:00
private static function updateBlockAndPlaylistLength ( $fileId )
2014-07-15 23:20:04 +02:00
{
$plRows = CcPlaylistcontentsQuery :: create () -> filterByDbFileId ( $fileId ) -> find ();
2012-11-06 16:58:25 +01:00
foreach ( $plRows as $row ) {
$pl = CcPlaylistQuery :: create () -> filterByDbId ( $row -> getDbPlaylistId ( $fileId )) -> findOne ();
$pl -> setDbLength ( $pl -> computeDbLength ( Propel :: getConnection ( CcPlaylistPeer :: DATABASE_NAME )));
$pl -> save ();
}
2013-05-28 20:27:59 +02:00
2012-11-06 16:58:25 +01:00
$blRows = CcBlockcontentsQuery :: create () -> filterByDbFileId ( $fileId ) -> find ();
foreach ( $blRows as $row ) {
$bl = CcBlockQuery :: create () -> filterByDbId ( $row -> getDbBlockId ()) -> findOne ();
$bl -> setDbLength ( $bl -> computeDbLength ( Propel :: getConnection ( CcBlockPeer :: DATABASE_NAME )));
$bl -> save ();
}
2012-04-12 22:17:19 +02:00
}
2012-07-11 00:51:32 +02:00
2012-04-12 22:17:19 +02:00
/**
* This function is for when media monitor detects deletion of file
2021-10-11 16:10:47 +02:00
* and trying to update airtime side .
2012-04-12 22:17:19 +02:00
*
2021-10-11 16:10:47 +02:00
* @ param mixed $deleteFromPlaylist
2012-04-12 22:17:19 +02:00
*/
2021-10-11 16:10:47 +02:00
public function deleteByMediaMonitor ( $deleteFromPlaylist = false )
2012-04-12 22:17:19 +02:00
{
2012-07-16 03:17:13 +02:00
if ( $deleteFromPlaylist ) {
2012-04-12 22:17:19 +02:00
Application_Model_Playlist :: DeleteFileFromAllPlaylists ( $this -> getId ());
}
2012-08-27 22:49:45 +02:00
// set file_exists flag to false
2012-02-05 18:19:22 +01:00
$this -> _file -> setDbFileExists ( false );
$this -> _file -> save ();
2010-12-07 20:19:27 +01:00
}
/**
2021-10-11 16:10:47 +02:00
* Get the absolute filepath .
2010-12-07 20:19:27 +01:00
*
2015-03-30 17:31:07 +02:00
* @ return array of strings
2010-12-07 20:19:27 +01:00
*/
2015-03-30 17:31:07 +02:00
public function getFilePaths ()
2012-01-17 11:18:17 +01:00
{
2014-03-24 22:14:04 +01:00
assert ( $this -> _file );
2019-09-20 02:07:50 +02:00
2015-03-30 17:31:07 +02:00
return $this -> _file -> getURLsForTrackPreviewOrDownload ();
2011-06-21 10:24:02 +02:00
}
2012-07-11 00:51:32 +02:00
2011-06-21 10:24:02 +02:00
/**
2021-10-11 16:10:47 +02:00
* Set real filename of raw media data .
*
* @ param mixed $p_filepath
2011-06-21 10:24:02 +02:00
*
* @ return string
*/
public function setFilePath ( $p_filepath )
{
2022-04-18 20:34:38 +02:00
$path_info = Application_Common_Storage :: splitFilePath ( $p_filepath );
2012-01-17 11:18:17 +01:00
2011-06-21 10:24:02 +02:00
if ( is_null ( $path_info )) {
return - 1 ;
}
$this -> _file -> setDbFilepath ( $path_info [ 1 ]);
2013-04-20 02:10:51 +02:00
$this -> _file -> save ( $this -> _con );
2010-12-07 20:19:27 +01:00
}
/**
2021-10-11 16:10:47 +02:00
* Get the URL to access this file .
2010-12-07 20:19:27 +01:00
*/
public function getFileUrl ()
2011-09-22 21:31:21 +02:00
{
2022-08-09 20:24:09 +02:00
return $this -> getRelativeFileUrl ( Config :: getPublicUrl ());
2011-06-09 11:50:03 +02:00
}
2011-06-22 22:50:58 +02:00
/**
* Sometimes we want a relative URL and not a full URL . See bug
2022-08-25 16:25:54 +02:00
* https :// dev . sourcefabric . org / browse / CC - 2403.
2021-10-11 16:10:47 +02:00
*
* @ param mixed $baseUrl
2011-06-22 22:50:58 +02:00
*/
2011-06-24 22:04:57 +02:00
public function getRelativeFileUrl ( $baseUrl )
2011-06-22 22:50:58 +02:00
{
2021-10-11 16:10:47 +02:00
return $baseUrl . 'api/get-media/file/' . $this -> getId ();
2011-06-22 22:50:58 +02:00
}
2019-09-20 02:07:50 +02:00
2014-07-10 23:56:41 +02:00
public function getResourceId ()
{
2014-07-29 21:07:51 +02:00
return $this -> _file -> getResourceId ();
2014-07-10 23:56:41 +02:00
}
2011-06-22 22:50:58 +02:00
2014-07-10 23:56:41 +02:00
public function getFileSize ()
{
2014-07-29 21:07:51 +02:00
$filesize = $this -> _file -> getFileSize ();
2015-02-24 17:00:41 +01:00
// It's OK for the file size to be zero. Pypo will make a request to Airtime and update
// the file size and md5 hash if they are not set.
if ( $filesize < 0 ) {
2021-10-11 16:10:47 +02:00
throw new Exception ( 'Could not determine filesize for file id: ' . $this -> _file -> getDbId () . '. Filesize: ' . $filesize );
2014-07-29 21:07:51 +02:00
}
2021-10-11 16:10:47 +02:00
2014-07-29 21:07:51 +02:00
return $filesize ;
2014-07-10 23:56:41 +02:00
}
2019-09-20 02:07:50 +02:00
2013-04-20 02:10:51 +02:00
public static function Insert ( $md , $con )
2011-06-09 11:50:03 +02:00
{
2012-08-08 21:55:58 +02:00
// save some work by checking if filepath is given right away
2021-10-11 16:10:47 +02:00
if ( ! isset ( $md [ 'MDATA_KEY_FILEPATH' ])) {
2012-08-29 16:58:03 +02:00
return null ;
}
2012-08-08 21:55:58 +02:00
2011-06-09 11:50:03 +02:00
$file = new CcFiles ();
2021-10-11 16:10:47 +02:00
$now = new DateTime ( 'now' , new DateTimeZone ( 'UTC' ));
2012-08-24 17:09:38 +02:00
$file -> setDbUtime ( $now );
$file -> setDbMtime ( $now );
2011-06-09 11:50:03 +02:00
2013-04-20 02:10:51 +02:00
$storedFile = new Application_Model_StoredFile ( $file , $con );
2011-06-09 12:57:30 +02:00
2012-08-08 21:55:58 +02:00
// removed "//" in the path. Always use '/' for path separator
2012-08-23 19:49:49 +02:00
// TODO : it might be better to just call OsPath::normpath on the file
// path. Also note that mediamonitor normalizes the paths anyway
// before passing them to php so it's not necessary to do this at all
2012-08-24 17:09:38 +02:00
2021-10-11 16:10:47 +02:00
$filepath = str_replace ( '//' , '/' , $md [ 'MDATA_KEY_FILEPATH' ]);
2012-08-08 21:55:58 +02:00
$res = $storedFile -> setFilePath ( $filepath );
if ( $res === - 1 ) {
2011-06-21 10:24:02 +02:00
return null ;
}
2012-08-08 21:55:58 +02:00
$storedFile -> setMetadata ( $md );
2012-08-29 16:58:03 +02:00
2012-08-08 21:55:58 +02:00
return $storedFile ;
2010-12-07 20:19:27 +01:00
}
2013-04-20 02:40:31 +02:00
/* TODO : Callers of this function should use a Propel transaction . Start
* by creating $con outside the function with beingTransaction () */
2015-06-03 22:57:17 +02:00
/**
* @ param int $p_id
2017-03-10 18:37:11 +01:00
* @ param Propel Connection
2021-10-11 16:10:47 +02:00
* @ param null | mixed $con
2015-06-03 22:57:17 +02:00
*
2021-10-11 16:10:47 +02:00
* @ return Application_Model_StoredFile
2022-09-12 13:16:14 +02:00
*
* @ throws Exception
2015-06-03 22:57:17 +02:00
*/
2021-10-11 16:10:47 +02:00
public static function RecallById ( $p_id = null , $con = null )
{
2022-03-14 11:15:04 +01:00
// TODO
2013-04-20 02:10:51 +02:00
if ( is_null ( $con )) {
$con = Propel :: getConnection ( CcFilesPeer :: DATABASE_NAME );
}
if ( isset ( $p_id )) {
2014-08-12 17:39:29 +02:00
$p_id = intval ( $p_id );
2019-09-20 02:07:50 +02:00
2021-10-11 16:10:47 +02:00
$storedFile = CcFilesQuery :: create () -> findPK ( $p_id , $con );
2014-07-24 22:56:15 +02:00
if ( is_null ( $storedFile )) {
2021-10-11 16:10:47 +02:00
throw new Exception ( 'Could not recall file with id: ' . $p_id );
2014-07-24 22:56:15 +02:00
}
2019-09-20 02:07:50 +02:00
2022-07-04 22:09:14 +02:00
return self :: createWithFile ( $storedFile , $con );
2011-06-09 12:57:30 +02:00
}
2021-10-11 16:10:47 +02:00
throw new Exception ( 'No arguments passed to RecallById' );
2011-06-08 10:15:35 +02:00
}
2011-06-28 15:04:03 +02:00
2012-07-16 03:17:13 +02:00
public function getName ()
{
2014-07-24 22:56:15 +02:00
return $this -> _file -> getFilename ();
2011-06-27 17:23:48 +02:00
}
2011-06-08 10:15:35 +02:00
/**
2011-09-22 18:24:17 +02:00
* Fetch the Application_Model_StoredFile by looking up its filepath .
2011-06-08 10:15:35 +02:00
*
2021-10-11 16:10:47 +02:00
* @ param string $p_filepath path of file stored in Airtime
* @ param mixed $con
*
* @ return null | Application_Model_StoredFile
2011-06-08 10:15:35 +02:00
*/
2013-04-20 02:10:51 +02:00
public static function RecallByFilepath ( $p_filepath , $con )
2011-06-08 10:15:35 +02:00
{
2022-04-18 20:34:38 +02:00
$path_info = Application_Common_Storage :: splitFilePath ( $p_filepath );
2012-09-12 00:22:46 +02:00
if ( is_null ( $path_info )) {
return null ;
}
$file = CcFilesQuery :: create ()
2021-10-11 16:10:47 +02:00
-> filterByDbFilepath ( $path_info [ 1 ])
2022-01-23 19:15:55 +01:00
-> findOne ( $con );
2021-10-11 16:10:47 +02:00
2013-04-20 02:10:51 +02:00
return is_null ( $file ) ? null : self :: createWithFile ( $file , $con );
2011-06-08 10:15:35 +02:00
}
2011-12-01 11:16:29 +01:00
2013-04-20 02:10:51 +02:00
public static function RecallByPartialFilepath ( $partial_path , $con )
2012-07-16 03:17:13 +02:00
{
2022-04-18 20:34:38 +02:00
$path_info = Application_Common_Storage :: splitFilePath ( $partial_path );
2011-09-27 20:49:03 +02:00
if ( is_null ( $path_info )) {
return null ;
}
$files = CcFilesQuery :: create ()
2021-10-11 16:10:47 +02:00
-> filterByDbFilepath ( " { $path_info [ 1 ] } % " )
2022-01-23 19:15:55 +01:00
-> find ( $con );
2021-10-11 16:10:47 +02:00
$res = [];
2012-07-16 03:17:13 +02:00
foreach ( $files as $file ) {
2021-10-11 16:10:47 +02:00
$storedFile = new Application_Model_StoredFile ( $file , $con );
$res [] = $storedFile ;
2011-09-27 20:49:03 +02:00
}
2012-07-16 03:17:13 +02:00
2011-09-27 20:49:03 +02:00
return $res ;
}
2011-12-01 11:16:29 +01:00
2012-09-14 18:09:40 +02:00
public static function getLibraryColumns ()
{
2022-07-04 22:09:14 +02:00
return [
'id' , 'track_title' , 'artist_name' , 'album_title' ,
2021-10-11 16:10:47 +02:00
'genre' , 'length' , 'year' , 'utime' , 'mtime' , 'ftype' ,
'track_number' , 'mood' , 'bpm' , 'composer' , 'info_url' ,
'bit_rate' , 'sample_rate' , 'isrc_number' , 'encoded_by' , 'label' ,
'copyright' , 'mime' , 'language' , 'filepath' , 'owner_id' ,
'conductor' , 'replay_gain' , 'lptime' , 'is_playlist' , 'is_scheduled' ,
2022-06-08 16:31:01 +02:00
'cuein' , 'cueout' , 'description' , 'artwork' , 'track_type_id' ,
2022-07-04 22:09:14 +02:00
];
2012-09-14 18:09:40 +02:00
}
2012-07-16 03:17:13 +02:00
public static function searchLibraryFiles ( $datatables )
{
2012-07-11 00:51:32 +02:00
$con = Propel :: getConnection ( CcFilesPeer :: DATABASE_NAME );
2010-12-07 23:29:28 +01:00
2012-09-14 18:09:40 +02:00
$displayColumns = self :: getLibraryColumns ();
2012-08-31 19:34:21 +02:00
2021-10-11 16:10:47 +02:00
$plSelect = [];
$blSelect = [];
$fileSelect = [];
$streamSelect = [];
2012-02-22 18:38:33 +01:00
foreach ( $displayColumns as $key ) {
2021-10-11 16:10:47 +02:00
if ( $key === 'id' ) {
$plSelect [] = 'PL.id AS ' . $key ;
$blSelect [] = 'BL.id AS ' . $key ;
$fileSelect [] = " FILES.id AS { $key } " ;
$streamSelect [] = 'ws.id AS ' . $key ;
} elseif ( $key === 'track_title' ) {
$plSelect [] = 'name AS ' . $key ;
$blSelect [] = 'name AS ' . $key ;
$fileSelect [] = $key ;
$streamSelect [] = 'name AS ' . $key ;
} elseif ( $key === 'ftype' ) {
$plSelect [] = " 'playlist'::varchar AS " . $key ;
$blSelect [] = " 'block'::varchar AS " . $key ;
$fileSelect [] = $key ;
$streamSelect [] = " 'stream'::varchar AS " . $key ;
} elseif ( $key === 'artist_name' ) {
$plSelect [] = 'login AS ' . $key ;
$blSelect [] = 'login AS ' . $key ;
$fileSelect [] = $key ;
$streamSelect [] = 'login AS ' . $key ;
} elseif ( $key === 'owner_id' ) {
$plSelect [] = 'login AS ' . $key ;
$blSelect [] = 'login AS ' . $key ;
$fileSelect [] = " sub.login AS { $key } " ;
$streamSelect [] = 'login AS ' . $key ;
} elseif ( $key === 'replay_gain' ) {
$plSelect [] = 'NULL::NUMERIC AS ' . $key ;
$blSelect [] = 'NULL::NUMERIC AS ' . $key ;
$fileSelect [] = $key ;
$streamSelect [] = 'NULL::NUMERIC AS ' . $key ;
} elseif ( $key === 'lptime' ) {
$plSelect [] = 'NULL::TIMESTAMP AS ' . $key ;
$blSelect [] = 'NULL::TIMESTAMP AS ' . $key ;
$fileSelect [] = $key ;
2012-09-11 00:01:36 +02:00
$streamSelect [] = $key ;
2021-10-11 16:10:47 +02:00
} elseif ( $key === 'is_scheduled' || $key === 'is_playlist' ) {
$plSelect [] = 'NULL::boolean AS ' . $key ;
$blSelect [] = 'NULL::boolean AS ' . $key ;
$fileSelect [] = $key ;
$streamSelect [] = 'NULL::boolean AS ' . $key ;
} elseif ( $key === 'cuein' || $key === 'cueout' ) {
$plSelect [] = 'NULL::INTERVAL AS ' . $key ;
$blSelect [] = 'NULL::INTERVAL AS ' . $key ;
$fileSelect [] = $key ;
$streamSelect [] = 'NULL::INTERVAL AS ' . $key ;
2012-02-24 00:55:20 +01:00
}
2022-03-14 11:15:04 +01:00
// file length is displayed based on cueout - cuein.
2021-10-11 16:10:47 +02:00
elseif ( $key === 'length' ) {
$plSelect [] = $key ;
$blSelect [] = $key ;
$fileSelect [] = '(cueout - cuein)::INTERVAL AS length' ;
$streamSelect [] = $key ;
2013-10-16 21:56:32 +02:00
}
2022-03-14 11:15:04 +01:00
// same columns in each table.
2021-10-11 16:10:47 +02:00
elseif ( in_array ( $key , [ 'utime' , 'mtime' ])) {
$plSelect [] = $key ;
$blSelect [] = $key ;
$fileSelect [] = $key ;
2012-07-19 00:27:39 +02:00
$streamSelect [] = $key ;
2021-10-11 16:10:47 +02:00
} elseif ( $key === 'year' ) {
$plSelect [] = 'EXTRACT(YEAR FROM utime)::varchar AS ' . $key ;
$blSelect [] = 'EXTRACT(YEAR FROM utime)::varchar AS ' . $key ;
$fileSelect [] = 'year AS ' . $key ;
$streamSelect [] = 'EXTRACT(YEAR FROM utime)::varchar AS ' . $key ;
2012-02-24 00:55:20 +01:00
}
2022-03-14 11:15:04 +01:00
// need to cast certain data as ints for the union to search on.
2022-09-08 22:55:41 +02:00
elseif ( in_array ( $key , [ 'track_number' , 'bit_rate' , 'sample_rate' , 'bpm' , 'track_type_id' ])) {
2021-10-11 16:10:47 +02:00
$plSelect [] = 'NULL::int AS ' . $key ;
$blSelect [] = 'NULL::int AS ' . $key ;
$fileSelect [] = $key ;
$streamSelect [] = 'NULL::int AS ' . $key ;
} elseif ( $key === 'filepath' ) {
$plSelect [] = 'NULL::VARCHAR AS ' . $key ;
$blSelect [] = 'NULL::VARCHAR AS ' . $key ;
2024-10-20 00:20:30 +02:00
$fileSelect [] = " reverse(split_part(reverse( { $key } ), '/', 1)) as { $key } " ;
2021-10-11 16:10:47 +02:00
$streamSelect [] = 'url AS ' . $key ;
} elseif ( $key == 'mime' ) {
$plSelect [] = 'NULL::VARCHAR AS ' . $key ;
$blSelect [] = 'NULL::VARCHAR AS ' . $key ;
$fileSelect [] = $key ;
2013-01-02 22:09:32 +01:00
$streamSelect [] = $key ;
2021-10-11 16:10:47 +02:00
} else {
$plSelect [] = 'NULL::text AS ' . $key ;
$blSelect [] = 'NULL::text AS ' . $key ;
$fileSelect [] = $key ;
$streamSelect [] = 'NULL::text AS ' . $key ;
2010-12-30 00:43:17 +01:00
}
}
Feature: Support php7.4 (#1354)
* Run CI tests against php 7.4
* Sort composer dependencies
* Remove unused Aws S3 php library
* Pin simplepie dependency to ^1.5
* Pin getid3 dependency to ^1.9
* Pin composer semver to ^3.2
* Pin php-amqplib to ^2.12
* Drop sentry logging support
* Update composer dependencies
* Move propel regenerate to Makefile
* Regenerate propel files with v1.7.0
* Pin propel orm to ^1.7
* Regenerate propel files with v1.7.2
* fix: generator_version in airtime-conf-production.php
* Replace propel/propel1 with jooola/propel1
* Regenerate propel files with v1.7.3-dev
* Fix php7.4 compatibility
Using php-cs-fixer:
'@PhpCsFixer' => true,
'concat_space' => ['spacing' => 'one'],
'ordered_class_elements' => false,
'yoda_style' => false,
'@PHP74Migration' => true,
'assign_null_coalescing_to_coalesce_equal' => false,
'ternary_to_null_coalescing' => false,
'heredoc_indentation' => false,
'@PHP74Migration:risky' => true,
'declare_strict_types' => false,
'void_return' => false,
'use_arrow_functions' => false,
* Fix pre-commit
2021-10-17 17:19:53 +02:00
$plSelect = 'SELECT ' . implode ( ',' , $plSelect );
$blSelect = 'SELECT ' . implode ( ',' , $blSelect );
$fileSelect = 'SELECT ' . implode ( ',' , $fileSelect );
$streamSelect = 'SELECT ' . implode ( ',' , $streamSelect );
2012-02-22 18:38:33 +01:00
2021-10-11 16:10:47 +02:00
$type = intval ( $datatables [ 'type' ]);
2012-02-24 00:55:20 +01:00
$plTable = " ( { $plSelect } FROM cc_playlist AS PL LEFT JOIN cc_subjs AS sub ON (sub.id = PL.creator_id)) " ;
2012-07-25 23:08:22 +02:00
$blTable = " ( { $blSelect } FROM cc_block AS BL LEFT JOIN cc_subjs AS sub ON (sub.id = BL.creator_id)) " ;
2012-11-20 21:18:18 +01:00
$fileTable = " ( { $fileSelect } FROM cc_files AS FILES LEFT JOIN cc_subjs AS sub ON (sub.id = FILES.owner_id) WHERE file_exists = 'TRUE' AND hidden='FALSE') " ;
2022-03-14 11:15:04 +01:00
// $fileTable = "({$fileSelect} FROM cc_files AS FILES WHERE file_exists = 'TRUE')";
2012-08-04 00:06:47 +02:00
$streamTable = " ( { $streamSelect } FROM cc_webstream AS ws LEFT JOIN cc_subjs AS sub ON (sub.id = ws.creator_id)) " ;
2012-07-19 00:27:39 +02:00
$unionTable = " ( { $plTable } UNION { $blTable } UNION { $fileTable } UNION { $streamTable } ) AS RESULTS " ;
2012-01-17 11:18:17 +01:00
2022-03-14 11:15:04 +01:00
// choose which table we need to select data from.
2012-02-24 00:55:20 +01:00
switch ( $type ) {
2015-09-15 00:26:28 +02:00
case MediaType :: FILE :
2022-03-14 11:15:04 +01:00
$fromTable = $fileTable . ' AS File' ; // need an alias for the table if it's standalone.
2021-10-11 16:10:47 +02:00
2012-02-24 00:55:20 +01:00
break ;
2021-10-11 16:10:47 +02:00
2015-09-15 00:26:28 +02:00
case MediaType :: PLAYLIST :
2022-03-14 11:15:04 +01:00
$fromTable = $plTable . ' AS Playlist' ; // need an alias for the table if it's standalone.
2021-10-11 16:10:47 +02:00
2012-02-24 00:55:20 +01:00
break ;
2021-10-11 16:10:47 +02:00
2015-09-15 00:26:28 +02:00
case MediaType :: BLOCK :
2022-03-14 11:15:04 +01:00
$fromTable = $blTable . ' AS Block' ; // need an alias for the table if it's standalone.
2021-10-11 16:10:47 +02:00
2012-07-25 23:08:22 +02:00
break ;
2021-10-11 16:10:47 +02:00
2015-09-15 00:26:28 +02:00
case MediaType :: WEBSTREAM :
2022-03-14 11:15:04 +01:00
$fromTable = $streamTable . ' AS StreamTable' ; // need an alias for the table if it's standalone.
2021-10-11 16:10:47 +02:00
2012-08-03 22:33:58 +02:00
break ;
2021-10-11 16:10:47 +02:00
2012-02-24 00:55:20 +01:00
default :
$fromTable = $unionTable ;
}
2012-04-01 21:51:03 +02:00
2013-02-05 22:52:25 +01:00
// update is_scheduled to false for tracks that
// have already played out
self :: updatePastFilesIsScheduled ();
2012-03-12 15:32:24 +01:00
$results = Application_Model_Datatables :: findEntries ( $con , $displayColumns , $fromTable , $datatables );
2013-01-30 22:53:59 +01:00
2013-12-04 21:16:07 +01:00
$displayTimezone = new DateTimeZone ( Application_Model_Preference :: GetUserTimezone ());
2021-10-11 16:10:47 +02:00
$utcTimezone = new DateTimeZone ( 'UTC' );
2019-09-20 02:07:50 +02:00
2022-04-18 20:34:38 +02:00
$fp = Config :: getStoragePath ();
2019-09-20 02:07:50 +02:00
2012-02-20 11:41:44 +01:00
foreach ( $results [ 'aaData' ] as & $row ) {
2012-02-01 18:47:08 +01:00
$row [ 'id' ] = intval ( $row [ 'id' ]);
2022-03-14 11:15:04 +01:00
// taken from Datatables.php, needs to be cleaned up there.
2013-07-18 07:37:39 +02:00
if ( isset ( $r [ 'ftype' ])) {
if ( $r [ 'ftype' ] == 'playlist' ) {
$pl = new Application_Model_Playlist ( $r [ 'id' ]);
$r [ 'length' ] = $pl -> getLength ();
2021-10-11 16:10:47 +02:00
} elseif ( $r [ 'ftype' ] == 'block' ) {
2013-07-18 07:37:39 +02:00
$bl = new Application_Model_Block ( $r [ 'id' ]);
$r [ 'bl_type' ] = $bl -> isStatic () ? 'static' : 'dynamic' ;
2021-10-11 16:10:47 +02:00
$r [ 'length' ] = $bl -> getLength ();
2013-07-18 07:37:39 +02:00
}
2013-07-18 07:31:20 +02:00
}
2021-10-11 16:10:47 +02:00
if ( $row [ 'ftype' ] === 'audioclip' ) {
$cuein_formatter = new LengthFormatter ( $row [ 'cuein' ]);
$row [ 'cuein' ] = $cuein_formatter -> format ();
2013-02-19 19:38:35 +01:00
2021-10-11 16:10:47 +02:00
$cueout_formatter = new LengthFormatter ( $row [ 'cueout' ]);
$row [ 'cueout' ] = $cueout_formatter -> format ();
2013-06-24 17:15:09 +02:00
2021-10-11 16:10:47 +02:00
$cuein = Application_Common_DateHelper :: playlistTimeToSeconds ( $row [ 'cuein' ]);
$cueout = Application_Common_DateHelper :: playlistTimeToSeconds ( $row [ 'cueout' ]);
2013-06-24 17:09:03 +02:00
$row_length = Application_Common_DateHelper :: secondsToPlaylistTime ( $cueout - $cuein );
2012-02-01 23:33:20 +01:00
2012-02-24 18:22:07 +01:00
$formatter = new SamplerateFormatter ( $row [ 'sample_rate' ]);
$row [ 'sample_rate' ] = $formatter -> format ();
$formatter = new BitrateFormatter ( $row [ 'bit_rate' ]);
$row [ 'bit_rate' ] = $formatter -> format ();
2013-01-30 21:38:25 +01:00
2019-09-20 02:07:50 +02:00
$get_artwork = FileDataHelper :: getArtworkData ( $row [ 'artwork' ], 32 , $fp );
$row [ 'artwork_data' ] = $get_artwork ;
2013-01-30 21:38:25 +01:00
// for audio preview
2021-10-11 16:10:47 +02:00
$row [ 'audioFile' ] = $row [ 'id' ] . '.' . pathinfo ( $row [ 'filepath' ], PATHINFO_EXTENSION );
} else {
2013-01-30 21:38:25 +01:00
$row [ 'audioFile' ] = $row [ 'id' ];
2013-06-24 17:09:03 +02:00
$row_length = $row [ 'length' ];
2012-02-24 18:22:07 +01:00
}
2012-08-29 16:58:03 +02:00
2013-06-24 17:15:09 +02:00
$len_formatter = new LengthFormatter ( $row_length );
2013-06-24 17:09:03 +02:00
$row [ 'length' ] = $len_formatter -> format ();
2019-09-20 02:07:50 +02:00
2022-03-14 11:15:04 +01:00
// convert mtime and utime to localtime
2013-12-04 21:16:07 +01:00
$row [ 'mtime' ] = new DateTime ( $row [ 'mtime' ], $utcTimezone );
$row [ 'mtime' ] -> setTimeZone ( $displayTimezone );
2015-06-26 20:42:52 +02:00
$row [ 'mtime' ] = $row [ 'mtime' ] -> format ( DEFAULT_TIMESTAMP_FORMAT );
2013-12-04 21:16:07 +01:00
$row [ 'utime' ] = new DateTime ( $row [ 'utime' ], $utcTimezone );
$row [ 'utime' ] -> setTimeZone ( $displayTimezone );
2015-06-26 20:42:52 +02:00
$row [ 'utime' ] = $row [ 'utime' ] -> format ( DEFAULT_TIMESTAMP_FORMAT );
2019-09-20 02:07:50 +02:00
2022-03-14 11:15:04 +01:00
// need to convert last played to localtime if it exists.
2013-12-04 21:24:27 +01:00
if ( isset ( $row [ 'lptime' ])) {
2021-10-11 16:10:47 +02:00
$row [ 'lptime' ] = new DateTime ( $row [ 'lptime' ], $utcTimezone );
$row [ 'lptime' ] -> setTimeZone ( $displayTimezone );
$row [ 'lptime' ] = $row [ 'lptime' ] -> format ( DEFAULT_TIMESTAMP_FORMAT );
2015-07-16 00:53:19 +02:00
}
// we need to initalize the checkbox and image row because we do not retrieve
// any data from the db for these and datatables will complain
2021-10-11 16:10:47 +02:00
$row [ 'checkbox' ] = '' ;
$row [ 'image' ] = '' ;
$row [ 'options' ] = '' ;
2015-07-16 00:53:19 +02:00
$type = substr ( $row [ 'ftype' ], 0 , 2 );
$row [ 'tr_id' ] = " { $type } _ { $row [ 'id' ] } " ;
}
return $results ;
}
2015-07-27 21:37:55 +02:00
/**
2019-09-20 02:07:50 +02:00
* Copy a newly uploaded audio file from its temporary upload directory
* on the local disk ( like / tmp ) over to Airtime ' s " stor " directory ,
2014-03-17 15:19:39 +01:00
* which is where all ingested music / media live .
2019-09-20 02:07:50 +02:00
*
2020-12-30 14:17:50 +01:00
* This is done in PHP here on the web server rather than in libretime - analyzer because
* the libretime - analyzer might be running on a different physical computer than the web server ,
2014-03-17 15:19:39 +01:00
* and it probably won 't have access to the web server' s / tmp folder . The stor / organize directory
2020-12-30 14:17:50 +01:00
* is , however , both accessible to the machines running libretime - analyzer and the web server
2014-03-17 15:19:39 +01:00
* on Airtime Pro .
2019-09-20 02:07:50 +02:00
*
2014-03-17 15:19:39 +01:00
* The file is actually copied to " stor/organize " , which is a staging directory where files go
2020-12-30 14:17:50 +01:00
* before they ' re processed by libretime - analyzer , which then moves them to " stor/imported " in the final
2014-03-17 15:19:39 +01:00
* step .
*
* @ param string $tempFilePath
* @ param string $originalFilename
2021-10-11 16:10:47 +02:00
* @ param bool $copyFile copy the file instead of moving it
2022-09-21 14:04:11 +02:00
* @ param mixed $fileId
2021-10-11 16:10:47 +02:00
*
2014-03-17 15:19:39 +01:00
* @ return Ambigous < unknown , string >
2022-09-12 13:16:14 +02:00
*
* @ throws Exception
2014-03-17 15:19:39 +01:00
*/
2022-09-21 14:04:11 +02:00
public static function moveFileToStor ( $tempFilePath , $fileId , $originalFilename , $copyFile = false )
2012-07-16 03:17:13 +02:00
{
2014-03-17 15:19:39 +01:00
$audio_file = $tempFilePath ;
2015-02-20 22:36:36 +01:00
2022-04-18 20:34:38 +02:00
$stor = Config :: getStoragePath ();
2012-08-22 22:08:46 +02:00
// check if "organize" dir exists and if not create one
2021-10-11 16:10:47 +02:00
if ( ! file_exists ( $stor . '/organize' )) {
if ( ! mkdir ( $stor . '/organize' , 0777 )) {
throw new Exception ( 'Failed to create organize directory.' );
2012-07-06 04:37:40 +02:00
}
2012-08-22 22:08:46 +02:00
}
2019-09-20 02:07:50 +02:00
2012-08-22 22:08:46 +02:00
if ( chmod ( $audio_file , 0644 ) === false ) {
2021-10-11 16:10:47 +02:00
Logging :: info ( " Warning: couldn't change permissions of { $audio_file } to 0644 " );
2012-08-22 22:08:46 +02:00
}
2019-09-20 02:07:50 +02:00
2012-09-19 23:45:03 +02:00
// Did all the checks for real, now trying to copy
2021-10-11 16:10:47 +02:00
$audio_stor = Application_Common_OsPath :: join (
$stor ,
'organize' ,
2022-09-21 14:04:11 +02:00
$fileId . '-' . $originalFilename
2021-10-11 16:10:47 +02:00
);
2022-03-14 11:15:04 +01:00
// if the uploaded file is not UTF-8 encoded, let's encode it. Assuming source
// encoding is ISO-8859-1
2021-10-11 16:10:47 +02:00
$audio_stor = mb_detect_encoding ( $audio_stor , 'UTF-8' ) == 'UTF-8' ? $audio_stor : utf8_encode ( $audio_stor );
2015-02-20 22:36:36 +01:00
if ( $copyFile ) {
2021-10-11 16:10:47 +02:00
Logging :: info ( " Copying file { $audio_file } to { $audio_stor } " );
2015-02-20 22:36:36 +01:00
if ( @ copy ( $audio_file , $audio_stor ) === false ) {
2021-10-11 16:10:47 +02:00
throw new Exception ( " Failed to copy { $audio_file } to { $audio_stor } " );
2015-02-20 22:36:36 +01:00
}
} else {
2021-10-11 16:10:47 +02:00
Logging :: info ( " Moving file { $audio_file } to { $audio_stor } " );
2015-02-20 22:36:36 +01:00
2022-03-14 11:15:04 +01:00
// Ensure we have permissions to overwrite the file in stor, in case it already exists.
2015-03-25 22:34:38 +01:00
if ( file_exists ( $audio_stor )) {
chmod ( $audio_stor , 0644 );
}
2015-02-20 22:36:36 +01:00
// Martin K.: changed to rename: Much less load + quicker since this is
// an atomic operation
2015-03-24 19:56:03 +01:00
if ( rename ( $audio_file , $audio_stor ) === false ) {
2022-03-14 11:15:04 +01:00
// something went wrong likely there wasn't enough space in .
// the audio_stor to move the file too warn the user that .
// the file wasn't uploaded and they should check if there .
// is enough disk space .
unlink ( $audio_file ); // remove the file after failed rename
2015-02-20 22:36:36 +01:00
2021-10-11 16:10:47 +02:00
throw new Exception ( 'The file was not uploaded, this error can occur if the computer '
. 'hard drive does not have enough disk space or the stor '
. 'directory does not have correct write permissions.' );
2015-02-20 22:36:36 +01:00
}
2012-08-22 22:08:46 +02:00
}
2021-10-11 16:10:47 +02:00
2014-03-17 15:19:39 +01:00
return $audio_stor ;
2011-03-25 04:07:13 +01:00
}
2019-09-20 02:07:50 +02:00
2021-10-11 16:10:47 +02:00
// Pass the file through Liquidsoap and test if it is readable. Return True if readable, and False otherwise.
2012-07-16 03:17:13 +02:00
public static function liquidsoapFilePlayabilityTest ( $audio_file )
{
2021-10-11 16:10:47 +02:00
$LIQUIDSOAP_ERRORS = [ 'TagLib: MPEG::Properties::read() -- Could not find a valid last MPEG frame in the stream.' ];
2012-07-11 00:51:32 +02:00
2012-07-06 04:37:40 +02:00
// Ask Liquidsoap if file is playable
2021-10-11 16:10:47 +02:00
// CC-5990/5991 - Changed to point directly to liquidsoap, removed PATH export
$command = sprintf (
'liquidsoap -v -c "output.dummy(audio_to_stereo(single(%s)))" 2>&1' ,
escapeshellarg ( $audio_file )
);
2012-07-11 00:51:32 +02:00
2012-07-06 04:37:40 +02:00
exec ( $command , $output , $rv );
2012-07-11 00:51:32 +02:00
2012-07-06 04:37:40 +02:00
$isError = count ( $output ) > 0 && in_array ( $output [ 0 ], $LIQUIDSOAP_ERRORS );
2012-07-16 03:17:13 +02:00
2021-10-11 16:10:47 +02:00
Logging :: info ( 'Is error?! : ' . $isError );
Logging :: info ( 'ls playability response: ' . $rv );
return $rv == 0 && ! $isError ;
2012-07-06 04:37:40 +02:00
}
2012-07-11 00:51:32 +02:00
2011-07-22 12:54:42 +02:00
public static function getFileCount ()
{
2021-10-11 16:10:47 +02:00
$sql = 'SELECT count(*) as cnt FROM cc_files WHERE file_exists' ;
return Application_Common_Database :: prepareAndExecute (
$sql ,
[],
Application_Common_Database :: COLUMN
);
2011-07-22 12:54:42 +02:00
}
2012-01-13 20:17:39 +01:00
/**
* Enter description here ...
2021-10-11 16:10:47 +02:00
*
2023-05-25 15:06:18 +02:00
* @ param $dir_id - if this is not provided , it returns all files with full
2023-12-29 15:28:57 +01:00
* path constructed
2021-10-11 16:10:47 +02:00
* @ param mixed $all
2012-01-13 20:17:39 +01:00
*/
2021-10-11 16:10:47 +02:00
public static function listAllFiles ( $dir_id = null , $all = true )
2012-04-01 21:51:03 +02:00
{
2012-07-16 03:17:13 +02:00
$con = Propel :: getConnection ();
2012-01-17 11:18:17 +01:00
2021-10-11 16:10:47 +02:00
$sql = <<< 'SQL'
2012-09-19 17:17:32 +02:00
SELECT filepath AS fp
FROM CC_FILES AS f
2013-01-03 20:02:06 +01:00
WHERE f . directory = : dir_id
2012-09-19 17:17:32 +02:00
SQL ;
2012-11-05 17:11:05 +01:00
2012-09-04 23:21:59 +02:00
if ( ! $all ) {
$sql .= " AND f.file_exists = 'TRUE' " ;
}
2012-08-28 18:35:19 +02:00
2012-09-04 23:21:59 +02:00
$stmt = $con -> prepare ( $sql );
$stmt -> bindParam ( ':dir_id' , $dir_id );
2013-05-28 20:27:59 +02:00
2012-09-04 23:21:59 +02:00
if ( $stmt -> execute ()) {
$rows = $stmt -> fetchAll ();
2012-04-01 21:51:03 +02:00
} else {
2012-09-04 23:21:59 +02:00
$msg = implode ( ',' , $stmt -> errorInfo ());
2021-10-11 16:10:47 +02:00
throw new Exception ( " Error: { $msg } " );
2012-01-13 20:17:39 +01:00
}
2013-05-28 20:27:59 +02:00
2021-10-11 16:10:47 +02:00
$results = [];
2012-04-01 21:51:03 +02:00
foreach ( $rows as $row ) {
2021-10-11 16:10:47 +02:00
$results [] = $row [ 'fp' ];
2011-07-04 20:29:09 +02:00
}
return $results ;
}
2012-07-16 03:17:13 +02:00
2022-03-14 11:15:04 +01:00
// TODO: MERGE THIS FUNCTION AND "listAllFiles" -MK
2021-10-11 16:10:47 +02:00
public static function listAllFiles2 ( $dir_id = null , $limit = 'ALL' )
2012-07-12 23:58:29 +02:00
{
$con = Propel :: getConnection ();
2021-10-11 16:10:47 +02:00
$sql = <<< 'SQL'
2012-09-18 21:04:22 +02:00
SELECT id ,
filepath AS fp
FROM cc_files
WHERE directory = : dir_id
AND file_exists = 'TRUE'
AND replay_gain IS NULL LIMIT : lim
SQL ;
2012-08-29 16:58:03 +02:00
2012-09-04 23:21:59 +02:00
$stmt = $con -> prepare ( $sql );
$stmt -> bindParam ( ':dir_id' , $dir_id );
$stmt -> bindParam ( ':lim' , $limit );
if ( $stmt -> execute ()) {
$rows = $stmt -> fetchAll ( PDO :: FETCH_ASSOC );
} else {
$msg = implode ( ',' , $stmt -> errorInfo ());
2021-10-11 16:10:47 +02:00
throw new Exception ( " Error: { $msg } " );
2012-09-04 23:21:59 +02:00
}
2012-08-29 16:58:03 +02:00
2012-07-12 23:58:29 +02:00
return $rows ;
}
2013-05-28 20:27:59 +02:00
2021-10-11 16:10:47 +02:00
public static function getAllFilesWithoutSilan ()
{
2013-01-18 17:53:26 +01:00
$con = Propel :: getConnection ();
2013-05-28 20:27:59 +02:00
2021-10-11 16:10:47 +02:00
$sql = <<< 'SQL'
2013-01-18 17:53:26 +01:00
SELECT f . id ,
m . directory || f . filepath AS fp
FROM cc_files as f
JOIN cc_music_dirs as m ON f . directory = m . id
WHERE file_exists = 'TRUE'
AND silan_check IS FALSE Limit 100
SQL ;
$stmt = $con -> prepare ( $sql );
2013-05-28 20:27:59 +02:00
2013-01-18 17:53:26 +01:00
if ( $stmt -> execute ()) {
$rows = $stmt -> fetchAll ( PDO :: FETCH_ASSOC );
} else {
$msg = implode ( ',' , $stmt -> errorInfo ());
2021-10-11 16:10:47 +02:00
throw new Exception ( " Error: { $msg } " );
2013-01-18 17:53:26 +01:00
}
2013-05-28 20:27:59 +02:00
2013-01-18 17:53:26 +01:00
return $rows ;
}
2012-07-11 00:51:32 +02:00
2012-07-16 03:17:13 +02:00
public function setFileExistsFlag ( $flag )
{
2012-01-13 20:17:39 +01:00
$this -> _file -> setDbFileExists ( $flag )
2022-01-23 19:15:55 +01:00
-> save ();
2012-01-13 20:17:39 +01:00
}
2021-10-11 16:10:47 +02:00
2013-01-08 21:42:35 +01:00
public function setFileHiddenFlag ( $flag )
{
$this -> _file -> setDbHidden ( $flag )
2022-01-23 19:15:55 +01:00
-> save ();
2013-01-08 21:42:35 +01:00
}
2013-05-28 20:27:59 +02:00
2012-11-05 15:49:49 +01:00
// This method seems to be unsued everywhere so I've commented it out
2013-01-03 20:02:06 +01:00
// If it's absence does not have any effect then it will be completely
2012-11-05 15:49:49 +01:00
// removed soon
2022-03-14 11:15:04 +01:00
// public function getFileExistsFlag()
// {
// return $this->_file->getDbFileExists();
// }
2011-09-22 21:31:21 +02:00
2012-10-31 21:01:17 +01:00
public function getFileOwnerId ()
{
return $this -> _file -> getDbOwnerId ();
}
2012-09-18 21:04:22 +02:00
2021-10-11 16:10:47 +02:00
public static function setIsPlaylist ( $p_playlistItems , $p_type , $p_status )
{
2013-02-01 23:47:07 +01:00
foreach ( $p_playlistItems as $item ) {
2013-04-20 02:24:05 +02:00
$file = self :: RecallById ( $item -> getDbFileId ());
2013-02-01 23:47:07 +01:00
$fileId = $file -> _file -> getDbId ();
if ( $p_type == 'playlist' ) {
// we have to check if the file is in another playlist before
// we can update
if ( ! is_null ( $fileId ) && ! in_array ( $fileId , Application_Model_Playlist :: getAllPlaylistFiles ())) {
$file -> _file -> setDbIsPlaylist ( $p_status ) -> save ();
}
} elseif ( $p_type == 'block' ) {
if ( ! is_null ( $fileId ) && ! in_array ( $fileId , Application_Model_Block :: getAllBlockFiles ())) {
$file -> _file -> setDbIsPlaylist ( $p_status ) -> save ();
}
}
}
}
2013-05-28 20:27:59 +02:00
2021-10-11 16:10:47 +02:00
public static function setIsScheduled ( $fileId , $status )
{
2013-04-20 02:24:05 +02:00
$file = self :: RecallById ( $fileId );
2013-02-01 23:47:07 +01:00
$updateIsScheduled = false ;
2021-10-11 16:10:47 +02:00
if ( ! is_null ( $fileId ) && ! in_array (
$fileId ,
Application_Model_Schedule :: getAllFutureScheduledFiles ()
)) {
2013-10-02 17:24:48 +02:00
$file -> _file -> setDbIsScheduled ( $status ) -> save ();
2013-02-01 23:47:07 +01:00
$updateIsScheduled = true ;
}
return $updateIsScheduled ;
}
2013-02-03 03:07:34 +01:00
2014-10-28 15:25:40 +01:00
/**
* Updates the is_scheduled flag to false for tracks that are no longer
* scheduled in the future . We do this by checking the difference between
* all files scheduled in the future and all files with is_scheduled = true .
* The difference of the two result sets is what we need to update .
*/
2013-02-05 22:52:25 +01:00
public static function updatePastFilesIsScheduled ()
{
2014-10-28 15:25:40 +01:00
$futureScheduledFilesSelectCriteria = new Criteria ();
$futureScheduledFilesSelectCriteria -> addSelectColumn ( CcSchedulePeer :: FILE_ID );
$futureScheduledFilesSelectCriteria -> setDistinct ();
2015-06-26 20:42:52 +02:00
$futureScheduledFilesSelectCriteria -> add ( CcSchedulePeer :: ENDS , gmdate ( DEFAULT_TIMESTAMP_FORMAT ), Criteria :: GREATER_THAN );
2014-10-28 15:25:40 +01:00
$stmt = CcSchedulePeer :: doSelectStmt ( $futureScheduledFilesSelectCriteria );
$filesScheduledInFuture = $stmt -> fetchAll ( PDO :: FETCH_COLUMN , 0 );
2019-09-20 02:07:50 +02:00
2014-10-28 15:25:40 +01:00
$filesCurrentlySetWithIsScheduledSelectCriteria = new Criteria ();
$filesCurrentlySetWithIsScheduledSelectCriteria -> addSelectColumn ( CcFilesPeer :: ID );
$filesCurrentlySetWithIsScheduledSelectCriteria -> add ( CcFilesPeer :: IS_SCHEDULED , true );
$stmt = CcFilesPeer :: doSelectStmt ( $filesCurrentlySetWithIsScheduledSelectCriteria );
$filesCurrentlySetWithIsScheduled = $stmt -> fetchAll ( PDO :: FETCH_COLUMN , 0 );
2019-09-20 02:07:50 +02:00
2014-10-28 15:25:40 +01:00
$diff = array_diff ( $filesCurrentlySetWithIsScheduled , $filesScheduledInFuture );
2019-09-20 02:07:50 +02:00
2014-10-28 15:25:40 +01:00
$con = Propel :: getConnection ( CcFilesPeer :: DATABASE_NAME );
$selectCriteria = new Criteria ();
$selectCriteria -> add ( CcFilesPeer :: ID , $diff , Criteria :: IN );
$updateCriteria = new Criteria ();
$updateCriteria -> add ( CcFilesPeer :: IS_SCHEDULED , false );
BasePeer :: doUpdate ( $selectCriteria , $updateCriteria , $con );
2013-02-05 22:52:25 +01:00
}
2010-12-07 23:29:28 +01:00
}
2011-02-22 18:22:31 +01:00
2023-09-08 15:45:24 +02:00
class DeleteScheduledFileException extends Exception {}
class FileDoesNotExistException extends Exception {}
class FileNoPermissionException extends Exception {}