libretime/legacy/application/services/MediaService.php

164 lines
6.2 KiB
PHP
Raw Permalink Normal View History

<?php
class Application_Service_MediaService
{
2021-10-11 16:10:47 +02:00
public const PENDING_FILE_TIMEOUT_SECONDS = 3600;
/**
* @var array store an internal array of the pending files so we don't have
* to go to the database twice
*/
private static $_pendingFiles;
/** Move (or copy) a file to the stor/organize directory and send it off to the
2021-10-11 16:10:47 +02:00
* analyzer to be processed.
*
* @param mixed $fileId
* @param mixed $fileOwnerId The ID of the user that will own the file inside Airtime
* @param mixed $fileTrackTypeId
* @param string $fileOriginalFilename The original filename, if you want it to be preserved after import
* @param string $filePath Path to the local file to import to the library
* @param bool $copyFile True if you want to copy the file to the "organize" directory, false if you want to move it (default)
2021-10-11 16:10:47 +02:00
*
* @return Ambigous
2022-09-12 13:16:14 +02:00
*
* @throws Exception
*/
public static function importFileToLibrary(
$fileId,
$fileOwnerId,
$fileTrackTypeId,
$fileOriginalFilename,
$filePath,
$copyFile
) {
$importedStorageDirectory = Config::getStoragePath() . '/imported/' . $fileOwnerId;
// Copy the temporary file over to the "organize" folder so that it's off our webserver
// and accessible by libretime-analyzer which could be running on a different machine.
$newTempFilePath = Application_Model_StoredFile::moveFileToStor(
$filePath,
$fileId,
$fileOriginalFilename,
$copyFile
);
// Dispatch a message to libretime-analyzer through RabbitMQ,
// notifying it that there's a new upload to process!
2021-10-11 16:10:47 +02:00
Application_Model_RabbitMq::SendMessageToAnalyzer(
$newTempFilePath,
$importedStorageDirectory,
basename($fileOriginalFilename),
$fileId,
$fileTrackTypeId
2021-10-11 16:10:47 +02:00
);
return $newTempFilePath;
}
/**
* @param bool $inline Set the Content-Disposition header to inline to prevent a download dialog from popping up (or attachment if false)
* @param mixed $fileId
2021-10-11 16:10:47 +02:00
*
* @throws Exception
Vendorize ZF1, fix PHPUnit and configure travis This a a rather large commit due to the nature of the stuff it is touching. To get PHPUnit up and running again I had to update some deps and I did so by vendorizing them. The vendorizing of zf1 makes sense since distros are already considering to drop it from their repos. * [x] install vendorized zf1 with composer * [x] load composer autoloader before zf1 * [x] Implement headAction for all Zend_Rest_Controller based controllers * [x] switch to yml dataset to get around string only limitations of xml sets (also removed warning in readme) * [x] use year 2044 as hardcoded date for tests since it is in the future and has the same days like previously used 2016 * [x] make tests easier to run when accessing phpunit directly * [x] clean up test helper to always use airtime.conf * [x] switch test dbname to libretime_test * [x] test db username password switched to libretime/libretime * [x] install phpunit with composer in a clear version (make tests easier to reproduce on other platforms) * [x] remove local libs from airtime repo (most of airtime_mvc/library was not needed of in vendor already) * [x] configure composer autoloading and use it (also removed requires that are not needed anymore) * [x] add LibreTime prefix for FileNotFoundException (phing had a similar class and these are all pre-namespace style) * [x] add .travis.yml file * [x] make etc and logdir configurable with LIBRETIME_CONF_DIR and LIBRETIME_LOG_DIR env (so travis can change it) * [x] slight cleanup in config for travis not to fail * [x] add cloud_storage.conf for during test runs * [x] rewrite mvc testing docs and move them to docs/ folder * [x] don't use `static::class` in a class that does not have a parent class, use `__CLASS__` instead. * [x] don't use `<ClassName>::class`, since we already know what class we want `"<ClassName>"` ist just fine. * [x] fix "can't use method in write context" errors on 5.4 (also helps the optimizer) * [x] add build status badge on main README.md Fixes https://github.com/LibreTime/libretime/issues/4 The PHP parts of https://github.com/LibreTime/libretime/pull/10 get obsoleted by this change and it will need rebasing. This also contains https://github.com/LibreTime/libretime/pull/8, the late static binding compat code was broken for no reason and until CentOS drops php 5.4 there is no reason I'm aware of not to support it. I inlined #8 since the test would be failing on php 5.4 without the change. If you want to run tests you need to run `composer install` in the root directory and then `cd airtime_mvc/tests && ../../vendor/bin/phpunit`. For the tests to run the user `libretime` needs to be allowed to create the `libretime_test` database. See `docs/TESTING.md` for more info on getting set up.
2017-02-20 21:47:53 +01:00
* @throws LibreTimeFileNotFoundException
*/
2021-10-11 16:10:47 +02:00
public static function streamFileDownload($fileId, $inline = false)
{
$media = Application_Model_StoredFile::RecallById($fileId);
if ($media == null) {
Vendorize ZF1, fix PHPUnit and configure travis This a a rather large commit due to the nature of the stuff it is touching. To get PHPUnit up and running again I had to update some deps and I did so by vendorizing them. The vendorizing of zf1 makes sense since distros are already considering to drop it from their repos. * [x] install vendorized zf1 with composer * [x] load composer autoloader before zf1 * [x] Implement headAction for all Zend_Rest_Controller based controllers * [x] switch to yml dataset to get around string only limitations of xml sets (also removed warning in readme) * [x] use year 2044 as hardcoded date for tests since it is in the future and has the same days like previously used 2016 * [x] make tests easier to run when accessing phpunit directly * [x] clean up test helper to always use airtime.conf * [x] switch test dbname to libretime_test * [x] test db username password switched to libretime/libretime * [x] install phpunit with composer in a clear version (make tests easier to reproduce on other platforms) * [x] remove local libs from airtime repo (most of airtime_mvc/library was not needed of in vendor already) * [x] configure composer autoloading and use it (also removed requires that are not needed anymore) * [x] add LibreTime prefix for FileNotFoundException (phing had a similar class and these are all pre-namespace style) * [x] add .travis.yml file * [x] make etc and logdir configurable with LIBRETIME_CONF_DIR and LIBRETIME_LOG_DIR env (so travis can change it) * [x] slight cleanup in config for travis not to fail * [x] add cloud_storage.conf for during test runs * [x] rewrite mvc testing docs and move them to docs/ folder * [x] don't use `static::class` in a class that does not have a parent class, use `__CLASS__` instead. * [x] don't use `<ClassName>::class`, since we already know what class we want `"<ClassName>"` ist just fine. * [x] fix "can't use method in write context" errors on 5.4 (also helps the optimizer) * [x] add build status badge on main README.md Fixes https://github.com/LibreTime/libretime/issues/4 The PHP parts of https://github.com/LibreTime/libretime/pull/10 get obsoleted by this change and it will need rebasing. This also contains https://github.com/LibreTime/libretime/pull/8, the late static binding compat code was broken for no reason and until CentOS drops php 5.4 there is no reason I'm aware of not to support it. I inlined #8 since the test would be failing on php 5.4 without the change. If you want to run tests you need to run `composer install` in the root directory and then `cd airtime_mvc/tests && ../../vendor/bin/phpunit`. For the tests to run the user `libretime` needs to be allowed to create the `libretime_test` database. See `docs/TESTING.md` for more info on getting set up.
2017-02-20 21:47:53 +01:00
throw new LibreTimeFileNotFoundException();
}
// Make sure we don't have some wrong result because of caching
clearstatcache();
2021-10-11 16:10:47 +02:00
$filePath = '';
if ($media->getPropelOrm()->isValidPhysicalFile()) {
$filename = $media->getPropelOrm()->getFilename();
2015-07-15 19:12:56 +02:00
// Download user left clicks a track and selects Download.
if (!$inline) {
// We are using Content-Disposition to specify
// to the browser what name the file should be saved as.
header('Content-Disposition: attachment; filename="' . $filename . '"');
} else {
// user clicks play button for track and downloads it.
header('Content-Disposition: inline; filename="' . $filename . '"');
}
/*
In this block of code below, we're getting the list of download URLs for a track
and then streaming the file as the response. A file can be stored in more than one location,
with the alternate locations used as a fallback, so that's why we're looping until we
are able to actually send the file.
This mechanism is used to try fetching our file from our internal S3 caching proxy server first.
If the file isn't found there (or the cache is down), then we attempt to download the file
directly from Amazon S3. We do this to save bandwidth costs!
*/
$filePaths = $media->getFilePaths();
assert(is_array($filePaths));
do {
// Read from $filePath and stream it to the browser.
$filePath = array_shift($filePaths);
2021-10-11 16:10:47 +02:00
try {
2021-10-11 16:10:47 +02:00
$size = $media->getFileSize();
$mimeType = $media->getPropelOrm()->getDbMime();
Application_Common_FileIO::smartReadFile($filePath, $size, $mimeType);
2021-10-11 16:10:47 +02:00
break; // Break out of the loop if we successfully read the file!
Vendorize ZF1, fix PHPUnit and configure travis This a a rather large commit due to the nature of the stuff it is touching. To get PHPUnit up and running again I had to update some deps and I did so by vendorizing them. The vendorizing of zf1 makes sense since distros are already considering to drop it from their repos. * [x] install vendorized zf1 with composer * [x] load composer autoloader before zf1 * [x] Implement headAction for all Zend_Rest_Controller based controllers * [x] switch to yml dataset to get around string only limitations of xml sets (also removed warning in readme) * [x] use year 2044 as hardcoded date for tests since it is in the future and has the same days like previously used 2016 * [x] make tests easier to run when accessing phpunit directly * [x] clean up test helper to always use airtime.conf * [x] switch test dbname to libretime_test * [x] test db username password switched to libretime/libretime * [x] install phpunit with composer in a clear version (make tests easier to reproduce on other platforms) * [x] remove local libs from airtime repo (most of airtime_mvc/library was not needed of in vendor already) * [x] configure composer autoloading and use it (also removed requires that are not needed anymore) * [x] add LibreTime prefix for FileNotFoundException (phing had a similar class and these are all pre-namespace style) * [x] add .travis.yml file * [x] make etc and logdir configurable with LIBRETIME_CONF_DIR and LIBRETIME_LOG_DIR env (so travis can change it) * [x] slight cleanup in config for travis not to fail * [x] add cloud_storage.conf for during test runs * [x] rewrite mvc testing docs and move them to docs/ folder * [x] don't use `static::class` in a class that does not have a parent class, use `__CLASS__` instead. * [x] don't use `<ClassName>::class`, since we already know what class we want `"<ClassName>"` ist just fine. * [x] fix "can't use method in write context" errors on 5.4 (also helps the optimizer) * [x] add build status badge on main README.md Fixes https://github.com/LibreTime/libretime/issues/4 The PHP parts of https://github.com/LibreTime/libretime/pull/10 get obsoleted by this change and it will need rebasing. This also contains https://github.com/LibreTime/libretime/pull/8, the late static binding compat code was broken for no reason and until CentOS drops php 5.4 there is no reason I'm aware of not to support it. I inlined #8 since the test would be failing on php 5.4 without the change. If you want to run tests you need to run `composer install` in the root directory and then `cd airtime_mvc/tests && ../../vendor/bin/phpunit`. For the tests to run the user `libretime` needs to be allowed to create the `libretime_test` database. See `docs/TESTING.md` for more info on getting set up.
2017-02-20 21:47:53 +01:00
} catch (LibreTimeFileNotFoundException $e) {
// If we have no alternate filepaths left, then let the exception bubble up.
if (count($filePaths) == 0) {
throw $e;
}
}
// Retry with the next alternate filepath in the list
} while (count($filePaths) > 0);
exit;
}
2021-10-11 16:10:47 +02:00
throw new LibreTimeFileNotFoundException($filePath);
}
/**
* Check if there are any files that have been stuck
2021-10-11 16:10:47 +02:00
* in Pending status for over an hour.
*
* @return bool true if there are any files stuck pending,
* otherwise false
*/
2021-10-11 16:10:47 +02:00
public static function areFilesStuckInPending()
{
2022-07-11 17:07:30 +02:00
$oneHourAgo = gmdate(DEFAULT_TIMESTAMP_FORMAT, microtime(true) - self::PENDING_FILE_TIMEOUT_SECONDS);
self::$_pendingFiles = CcFilesQuery::create()
->filterByDbImportStatus(CcFiles::IMPORT_STATUS_PENDING)
->filterByDbUtime($oneHourAgo, Criteria::LESS_EQUAL)
->find();
$pendingEpisodes = Application_Service_PodcastEpisodeService::getStuckPendingImports();
2021-10-11 16:10:47 +02:00
return !self::$_pendingFiles->isEmpty() || !empty($pendingEpisodes);
}
/**
2021-10-11 16:10:47 +02:00
* Clean up stuck imports by changing their import status to Failed.
*/
2021-10-11 16:10:47 +02:00
public static function clearStuckPendingImports()
{
$pendingEpisodes = Application_Service_PodcastEpisodeService::getStuckPendingImports();
foreach (self::$_pendingFiles as $file) {
2021-10-11 16:10:47 +02:00
// @var $file CcFiles
$file->setDbImportStatus(CcFiles::IMPORT_STATUS_FAILED)->save();
}
foreach ($pendingEpisodes as $episode) {
2021-10-11 16:10:47 +02:00
// @var $episode PodcastEpisodes
$episode->delete();
}
}
}