123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- <?php
- class NestedDirectoryException extends Exception { }
- class Application_Model_MusicDir
- {
- /**
- * @holds propel database object
- */
- private $_dir;
- public function __construct($dir)
- {
- $this->_dir = $dir;
- }
- public function getId()
- {
- return $this->_dir->getId();
- }
- public function getType()
- {
- return $this->_dir->getType();
- }
- public function setType($type)
- {
- $this->_dir->setType($type);
- }
- public function getDirectory()
- {
- return $this->_dir->getDirectory();
- }
- public function setDirectory($dir)
- {
- $this->_dir->setDirectory($dir);
- $this->_dir->save();
- }
- public function setExistsFlag($flag)
- {
- $this->_dir->setExists($flag);
- $this->_dir->save();
- }
- public function setWatchedFlag($flag)
- {
- $this->_dir->setWatched($flag);
- $this->_dir->save();
- }
- public function getWatchedFlag()
- {
- return $this->_dir->getWatched();
- }
- public function getExistsFlag()
- {
- return $this->_dir->getExists();
- }
- /**
- * There are 2 cases where this function can be called.
- * 1. When watched dir was removed
- * 2. When some dir was watched, but it was unmounted
- *
- * In case of 1, $userAddedWatchedDir should be true
- * In case of 2, $userAddedWatchedDir should be false
- *
- * When $userAddedWatchedDir is true, it will set "Watched" flag to false
- * otherwise, it will set "Exists" flag to true
- */
- public function remove($userAddedWatchedDir=true)
- {
- $music_dir_id = $this->getId();
- $sql = <<<SQL
- SELECT DISTINCT s.instance_id
- FROM cc_music_dirs AS md
- LEFT JOIN cc_files AS f ON f.directory = md.id
- RIGHT JOIN cc_schedule AS s ON s.file_id = f.id
- WHERE md.id = :musicDirId;
- SQL;
- $show_instances = Application_Common_Database::prepareAndExecute($sql,
- array( ':musicDirId' => $music_dir_id ), 'all' );
- // get all the files on this dir
- $sql = <<<SQL
- UPDATE cc_files
- SET file_exists = 'f'
- WHERE id IN
- (SELECT f.id
- FROM cc_music_dirs AS md
- LEFT JOIN cc_files AS f ON f.directory = md.id
- WHERE md.id = :musicDirId);
- SQL;
- $affected = Application_Common_Database::prepareAndExecute($sql,
- array( ':musicDirId' => $music_dir_id ), 'all');
- // set RemovedFlag to true
- if ($userAddedWatchedDir) {
- self::setWatchedFlag(false);
- } else {
- self::setExistsFlag(false);
- }
- //$res = $this->_dir->delete();
- foreach ($show_instances as $show_instance_row) {
- $temp_show = new Application_Model_ShowInstance($show_instance_row["instance_id"]);
- $temp_show->updateScheduledTime();
- }
- Application_Model_RabbitMq::PushSchedule();
- }
- /**
- * Checks if p_dir1 is the ancestor of p_dir2. Returns
- * true if it is the ancestor, false otherwise. Note that
- * /home/user is considered the ancestor of /home/user
- *
- * @param string $p_dir1
- * The potential ancestor directory.
- * @param string $p_dir2
- * The potential descendent directory.
- * @return boolean
- * Returns true if it is the ancestor, false otherwise.
- */
- private static function isAncestorDir($p_dir1, $p_dir2)
- {
- if (strlen($p_dir1) > strlen($p_dir2)) {
- return false;
- }
- return substr($p_dir2, 0, strlen($p_dir1)) == $p_dir1;
- }
- /**
- * Checks whether the path provided is a valid path. A valid path
- * is defined as not being nested within an existing watched directory,
- * or vice-versa. Throws a NestedDirectoryException if invalid.
- *
- * @param string $p_path
- * The path we want to validate
- * @return void
- */
- public static function isPathValid($p_path)
- {
- $dirs = self::getWatchedDirs();
- $dirs[] = self::getStorDir();
- foreach ($dirs as $dirObj) {
- $dir = $dirObj->getDirectory();
- $diff = strlen($dir) - strlen($p_path);
- if ($diff == 0) {
- if ($dir == $p_path) {
- throw new NestedDirectoryException(sprintf(_("%s is already watched."), $p_path));
- }
- } elseif ($diff > 0) {
- if (self::isAncestorDir($p_path, $dir)) {
- throw new NestedDirectoryException(sprintf(_("%s contains nested watched directory: %s"), $p_path, $dir));
- }
- } else { /* diff < 0*/
- if (self::isAncestorDir($dir, $p_path)) {
- throw new NestedDirectoryException(sprintf(_("%s is nested within existing watched directory: %s"), $p_path, $dir));
- }
- }
- }
- }
- /** There are 2 cases where this function can be called.
- * 1. When watched dir was added
- * 2. When some dir was watched, but it was unmounted somehow, but gets mounted again
- *
- * In case of 1, $userAddedWatchedDir should be true
- * In case of 2, $userAddedWatchedDir should be false
- *
- * When $userAddedWatchedDir is true, it will set "Removed" flag to false
- * otherwise, it will set "Exists" flag to true
- *
- * @param $nestedWatch - if true, bypass path check, and Watched to false
- **/
- public static function addDir($p_path, $p_type, $userAddedWatchedDir=true, $nestedWatch=false)
- {
- if (!is_dir($p_path)) {
- return array("code"=>2, "error"=>sprintf(_("%s is not a valid directory."), $p_path));
- }
- $real_path = Application_Common_OsPath::normpath($p_path)."/";
- if ($real_path != "/") {
- $p_path = $real_path;
- }
- $exist_dir = self::getDirByPath($p_path);
- if (is_null($exist_dir)) {
- $temp_dir = new CcMusicDirs();
- $dir = new Application_Model_MusicDir($temp_dir);
- } else {
- $dir = $exist_dir;
- }
- $dir->setType($p_type);
- $p_path = Application_Common_OsPath::normpath($p_path)."/";
- try {
- /* isPathValid() checks if path is a substring or a superstring of an
- * existing dir and if not, throws NestedDirectoryException */
- if (!$nestedWatch) {
- self::isPathValid($p_path);
- }
- if ($userAddedWatchedDir) {
- $dir->setWatchedFlag(true);
- } else {
- if ($nestedWatch) {
- $dir->setWatchedFlag(false);
- }
- $dir->setExistsFlag(true);
- }
- $dir->setDirectory($p_path);
- return array("code"=>0);
- } catch (NestedDirectoryException $nde) {
- $msg = $nde->getMessage();
- return array("code"=>1, "error"=>"$msg");
- } catch (Exception $e) {
- return array("code"=>1,
- "error" => sprintf(
- _("%s is already set as the current storage dir or in the".
- " watched folders list"),
- $p_path
- )
- );
- }
- }
- /** There are 2 cases where this function can be called.
- * 1. When watched dir was added
- * 2. When some dir was watched, but it was unmounted somehow, but gets mounted again
- *
- * In case of 1, $userAddedWatchedDir should be true
- * In case of 2, $userAddedWatchedDir should be false
- *
- * When $userAddedWatchedDir is true, it will set "Watched" flag to true
- * otherwise, it will set "Exists" flag to true
- **/
- public static function addWatchedDir($p_path, $userAddedWatchedDir=true, $nestedWatch=false)
- {
- $res = self::addDir($p_path, "watched", $userAddedWatchedDir, $nestedWatch);
- if ($res['code'] != 0) { return $res; }
- //convert "linked" files (Airtime <= 1.8.2) to watched files.
- $propel_link_dir = CcMusicDirsQuery::create()
- ->filterByType('link')
- ->findOne();
- //see if any linked files exist.
- if (isset($propel_link_dir)) {
- //newly added watched directory object
- $propel_new_watch = CcMusicDirsQuery::create()
- ->filterByDirectory(Application_Common_OsPath::normpath($p_path)."/")
- ->findOne();
- //any files of the deprecated "link" type.
- $link_files = CcFilesQuery::create()
- ->setFormatter(ModelCriteria::FORMAT_ON_DEMAND)
- ->filterByDbDirectory($propel_link_dir->getId())
- ->find();
- $newly_watched_dir = $propel_new_watch->getDirectory();
- foreach ($link_files as $link_file) {
- $link_filepath = $link_file->getDbFilepath();
- //convert "link" file into a watched file.
- if ((strlen($newly_watched_dir) < strlen($link_filepath)) && (substr($link_filepath, 0, strlen($newly_watched_dir)) === $newly_watched_dir)) {
- //get the filepath path not including the watched directory.
- $sub_link_filepath = substr($link_filepath, strlen($newly_watched_dir));
- $link_file->setDbDirectory($propel_new_watch->getId());
- $link_file->setDbFilepath($sub_link_filepath);
- $link_file->save();
- }
- }
- }
- $data = array();
- $data["directory"] = $p_path;
- Application_Model_RabbitMq::SendMessageToMediaMonitor("new_watch", $data);
- return $res;
- }
- public static function getDirByPK($pk)
- {
- $dir = CcMusicDirsQuery::create()->findPK($pk);
- $mus_dir = new Application_Model_MusicDir($dir);
- return $mus_dir;
- }
- public static function getDirByPath($p_path)
- {
- $dir = CcMusicDirsQuery::create()
- ->filterByDirectory($p_path)
- ->findOne();
- if ($dir == NULL) {
- return null;
- } else {
- $mus_dir = new Application_Model_MusicDir($dir);
- return $mus_dir;
- }
- }
- /**
- * Search and returns watched dirs
- *
- * @param $exists search condition with exists flag
- * @param $watched search condition with watched flag
- */
- public static function getWatchedDirs($exists=true, $watched=true)
- {
- $result = array();
- $dirs = CcMusicDirsQuery::create()
- ->filterByType("watched");
- if ($exists !== null) {
- $dirs = $dirs->filterByExists($exists);
- }
- if ($watched !== null) {
- $dirs = $dirs->filterByWatched($watched);
- }
- $dirs = $dirs->find();
- foreach ($dirs as $dir) {
- $result[] = new Application_Model_MusicDir($dir);
- }
- return $result;
- }
- public static function getStorDir()
- {
- $dir = CcMusicDirsQuery::create()
- ->filterByType("stor")
- ->findOne();
- $mus_dir = new Application_Model_MusicDir($dir);
- return $mus_dir;
- }
- public static function setStorDir($p_dir)
- {
- // we want to be consistent when storing dir path.
- // path should always ends with trailing '/'
- $p_dir = Application_Common_OsPath::normpath($p_dir)."/";
- if (!is_dir($p_dir)) {
- return array("code"=>2, "error"=>sprintf(_("%s is not a valid directory."), $p_dir));
- } elseif (Application_Model_Preference::GetImportTimestamp()+10 > time()) {
- return array("code"=>3, "error"=>"Airtime is currently importing files. Please wait until this is complete before changing the storage directory.");
- }
- $dir = self::getStorDir();
- // if $p_dir doesn't exist in DB
- $exist = $dir->getDirByPath($p_dir);
- if ($exist == NULL) {
- $dir->setDirectory($p_dir);
- $dirId = $dir->getId();
- $data = array();
- $data["directory"] = $p_dir;
- $data["dir_id"] = $dirId;
- Application_Model_RabbitMq::SendMessageToMediaMonitor("change_stor", $data);
- return array("code"=>0);
- } else {
- return array("code"=>1,
- "error"=>sprintf(_("%s is already set as the current storage dir or in the watched folders list."), $p_dir));
- }
- }
- public static function getWatchedDirFromFilepath($p_filepath)
- {
- $dirs = CcMusicDirsQuery::create()
- ->filterByType(array("watched", "stor"))
- ->filterByExists(true)
- ->filterByWatched(true)
- ->find();
- foreach ($dirs as $dir) {
- $directory = $dir->getDirectory();
- if (substr($p_filepath, 0, strlen($directory)) === $directory) {
- $mus_dir = new Application_Model_MusicDir($dir);
- return $mus_dir;
- }
- }
- return null;
- }
- /** There are 2 cases where this function can be called.
- * 1. When watched dir was removed
- * 2. When some dir was watched, but it was unmounted
- *
- * In case of 1, $userAddedWatchedDir should be true
- * In case of 2, $userAddedWatchedDir should be false
- *
- * When $userAddedWatchedDir is true, it will set "Watched" flag to false
- * otherwise, it will set "Exists" flag to true
- **/
- public static function removeWatchedDir($p_dir, $userAddedWatchedDir=true)
- {
- //make sure that $p_dir has a trailing "/"
- $real_path = Application_Common_OsPath::normpath($p_dir)."/";
- if ($real_path != "/") {
- $p_dir = $real_path;
- }
- $dir = Application_Model_MusicDir::getDirByPath($p_dir);
- if (is_null($dir)) {
- return array("code"=>1, "error"=>sprintf(_("%s doesn't exist in the watched list."), $p_dir));
- } else {
- $dir->remove($userAddedWatchedDir);
- $data = array();
- $data["directory"] = $p_dir;
- Application_Model_RabbitMq::SendMessageToMediaMonitor("remove_watch", $data);
- return array("code"=>0);
- }
- }
- public static function splitFilePath($p_filepath)
- {
- $mus_dir = self::getWatchedDirFromFilepath($p_filepath);
- if (is_null($mus_dir)) {
- return null;
- }
- $length_dir = strlen($mus_dir->getDirectory());
- $fp = substr($p_filepath, $length_dir);
- return array($mus_dir->getDirectory(), trim($fp));
- }
- public function unhideFiles()
- {
- $files = $this->_dir->getCcFiless();
- $hid = 0;
- foreach ($files as $file) {
- $hid++;
- $file->setDbHidden(false);
- $file->save();
- }
- Logging::info("unhide '$hid' files");
- }
- }
|