/**
  * Main logic function.
  * Sync between the list of physical files and drop folder file object for the given drop folder ($folder).
  * Add new files, update sizes and status and delete physical files when required.
  * @param KalturaDropFolder $folder
  */
 private function watchFolder(KalturaDropFolder $folder)
 {
     KalturaLog::debug('Watching folder [' . $folder->id . ']');
     // if remote folder -> login to server and set fileTransferManager
     try {
         $this->fileTransferMgr = DropFolderBatchUtils::getFileTransferManager($folder);
     } catch (Exception $e) {
         $this->unimpersonate();
         KalturaLog::err('Cannot initialize file transfer manager for folder [' . $folder->id . '] - ' . $e->getMessage());
         return;
         // skipping to next folder
     }
     // get list of DropFolderFile objects from the current $folder
     $dropFolderFiles = null;
     $deletedDropFolderFiles = null;
     try {
         $dropFolderFiles = $this->getDropFolderFileObjects($folder->id);
     } catch (Exception $e) {
         $this->unimpersonate();
         KalturaLog::err('Cannot get drop folder file list from the server for drop folder id [' . $folder->id . '] - ' . $e->getMessage());
         return;
         // skipping to next folder
     }
     // get a list of physical files from the folder's path
     $physicalFiles = null;
     try {
         $physicalFiles = $this->getPhysicalFileList($folder);
     } catch (Exception $e) {
         $this->unimpersonate();
         $physicalFiles = null;
     }
     if (!$physicalFiles) {
         KalturaLog::err('Cannot get physical file list for drop folder id [' . $folder->id . '] with path [' . $folder->path . ']');
         return;
         // skipping to next folder
     }
     // with local drop folder, file may have been moved (hence deleted) immidiately upon ingestion
     $autoDeleteOriginalFile = $folder->fileDeletePolicy == KalturaDropFolderFileDeletePolicy::AUTO_DELETE && $folder->autoFileDeleteDays == 0;
     $dropFolderFileMapByName = array();
     foreach ($dropFolderFiles as $dropFolderFile) {
         if ($dropFolderFile->status !== KalturaDropFolderFileStatus::PURGED) {
             if (!in_array($dropFolderFile->fileName, $physicalFiles)) {
                 if ($autoDeleteOriginalFile) {
                     $this->setFileAsPurged($dropFolderFile);
                 } else {
                     if (!in_array($dropFolderFile->status, self::$dropFolderFileErrorStatuses)) {
                         $this->errorWithFile($dropFolderFile, KalturaDropFolderFileErrorCode::ERROR_READING_FILE, 'Cannot find file with name [' . $dropFolderFile->fileName . ']');
                     }
                 }
                 continue;
             }
             $dropFolderFileMapByName[$dropFolderFile->fileName] = $dropFolderFile;
         }
     }
     // get defined file name patterns
     $ignorePatterns = $folder->ignoreFileNamePatterns;
     $ignorePatterns = array_map('trim', explode(',', $ignorePatterns));
     // sync between physical file list and drop folder file objects
     foreach ($physicalFiles as $physicalFileName) {
         try {
             if (empty($physicalFileName) || $physicalFileName === '.' || $physicalFileName === '..') {
                 continue;
             }
             KalturaLog::debug("Watch file [{$physicalFileName}]");
             $shouldIgnore = false;
             foreach ($ignorePatterns as $ignorePattern) {
                 if (!is_null($ignorePattern) && $ignorePattern != '') {
                     if (fnmatch($ignorePattern, $physicalFileName)) {
                         $shouldIgnore = true;
                         KalturaLog::err("Ignoring file [{$physicalFileName}] matching ignore pattern [{$ignorePattern}]");
                         break;
                     }
                 }
             }
             if ($shouldIgnore) {
                 continue;
             }
             // translate file name to path+name on the shared location
             $fullPath = $folder->path . '/' . $physicalFileName;
             // skip non-accessible files
             if (!$fullPath || !$this->fileTransferMgr->fileExists($fullPath)) {
                 KalturaLog::err("Cannot access physical file in path [{$fullPath}]");
                 continue;
             }
             // skip directories
             /*
             if (is_dir($fullPath)) {
             	KalturaLog::log("Path [$fullPath] is a directory - skipped");
             	continue;
             }
             */
             // check if file is already in the list of drop folder files
             if (!array_key_exists($physicalFileName, $dropFolderFileMapByName)) {
                 // new physical file found in folder - add new drop folder file object with status UPLOADING
                 $this->addNewDropFolderFile($folder->id, $physicalFileName, $fullPath);
             } else {
                 $currentDropFolderFile = $dropFolderFileMapByName[$physicalFileName];
                 try {
                     $lastModificationTime = $this->getModificationTime($fullPath);
                 } catch (Exception $e) {
                     $this->unimpersonate();
                     KalturaLog::err('Cannot get modification time for file in path [' . $fullPath . '] - ' . $e->getMessage());
                     continue;
                     // skipping to next file
                 }
                 $knownLastModificationTime = $currentDropFolderFile->lastModificationTime;
                 if ($knownLastModificationTime && $lastModificationTime > $knownLastModificationTime && $currentDropFolderFile->status != KalturaDropFolderFileStatus::UPLOADING) {
                     // file has been replaced by a new file with the same name
                     $this->setFileAsPurged($currentDropFolderFile);
                     $this->addNewDropFolderFile($folder->id, $physicalFileName, $fullPath, $lastModificationTime);
                     continue;
                     // continue to next file
                 }
                 // update existing drop folder file object according to current physical file
                 if ($currentDropFolderFile->status == KalturaDropFolderFileStatus::UPLOADING) {
                     $this->updateDropFolderFile($folder, $currentDropFolderFile, $fullPath, $lastModificationTime);
                 } else {
                     if ($currentDropFolderFile->status == KalturaDropFolderFileStatus::HANDLED) {
                         $this->purgeHandledFileIfNeeded($folder, $currentDropFolderFile, $fullPath);
                     } else {
                         if ($currentDropFolderFile->status == KalturaDropFolderFileStatus::DELETED) {
                             // purge file marked as deleted
                             $this->purgeFile($dropFolderFileMapByName[$physicalFileName], $fullPath);
                             continue;
                         }
                     }
                 }
             }
         } catch (Exception $e) {
             $this->unimpersonate();
             KalturaLog::err("Error handling drop folder file [{$physicalFileName}] " . $e->getMessage());
         }
     }
 }
 public function handle()
 {
     $this->tempDirectory = sys_get_temp_dir();
     if (!is_dir($this->tempDirectory)) {
         KalturaLog::err('Missing temporary directory');
         return false;
     }
     // check prerequisites
     $checkConfig = $this->checkConfig();
     if (!$checkConfig) {
         KalturaLog::err('Missing required configurations');
         return false;
     }
     $this->fileTransferMgr = DropFolderBatchUtils::getFileTransferManager($this->dropFolder);
     if (!$this->fileTransferMgr) {
         $this->dropFolderFile->status = KalturaDropFolderFileStatus::ERROR_HANDLING;
         $this->dropFolderFile->errorCode = KalturaDropFolderFileErrorCode::INTERNAL_ERROR;
         $this->dropFolderFile->errorDescription = 'Internal server error - cannot initiate file transfer manager';
         KalturaLog::err($this->dropFolderFile->errorDescription);
         $this->updateDropFolderFile();
         return false;
     }
     $xmlPath = $this->getLocalXmlFilePath();
     if (!$xmlPath) {
         $this->dropFolderFile->status = KalturaDropFolderFileStatus::ERROR_HANDLING;
         $this->dropFolderFile->errorCode = KalturaDropFolderFileErrorCode::ERROR_READING_FILE;
         $this->dropFolderFile->errorDescription = 'Cannot read file at path [' . $this->dropFolder->path . '/' . $this->dropFolderFile->fileName . ']';
         KalturaLog::err($this->dropFolderFile->errorDescription);
         $this->updateDropFolderFile();
         return false;
     }
     $xmlDoc = new KDOMDocument();
     $xmlDoc->load($xmlPath);
     if (!$xmlDoc) {
         $this->dropFolderFile->status = KalturaDropFolderFileStatus::ERROR_HANDLING;
         $this->dropFolderFile->errorCode = KalturaDropFolderFileErrorCode::ERROR_READING_FILE;
         $this->dropFolderFile->errorDescription = "Cannot parse XML file at [{$xmlPath}]";
         KalturaLog::err($this->dropFolderFile->errorDescription);
         $this->updateDropFolderFile();
         return false;
     }
     $localResources = $xmlDoc->getElementsByTagName(self::DROP_FOLDER_RESOURCE_NODE_NAME);
     if (!$localResources) {
         $this->dropFolderFile->status = KalturaDropFolderFileStatus::ERROR_HANDLING;
         $this->dropFolderFile->errorCode = KalturaDropFolderFileErrorCode::ERROR_READING_FILE;
         $this->dropFolderFile->errorDescription = "Cannot parse XML file at [{$xmlPath}]";
         KalturaLog::err($this->dropFolderFile->errorDescription);
         $this->updateDropFolderFile();
         return false;
     }
     $replaceResources = array();
     $localResourcesLength = $localResources->length;
     foreach ($localResources as $local) {
         // already have drop folder file id
         if (!is_null($this->getDropFolderFileId($local))) {
             continue;
         }
         // replacement/modification of $local must not happen inside this foreach loop
         $dropFolderFileId = $this->checkFileExists($local);
         if (is_null($dropFolderFileId)) {
             KalturaLog::debug('Some required files do not exist in the drop folder - changing status to WAITING');
             $this->dropFolderFile->status = KalturaDropFolderFileStatus::WAITING;
             KalturaLog::debug('Changing status to WAITING');
             $this->updateDropFolderFile();
             return false;
         }
         $localVerified = $this->verifyLocalResource($local);
         if (!$localVerified) {
             $this->dropFolderFile->status = KalturaDropFolderFileStatus::ERROR_HANDLING;
             // error code and description already set
             KalturaLog::err($this->dropFolderFile->errorDescription);
             $this->updateDropFolderFile();
             return false;
         }
         $replaceResources[] = array($local, $dropFolderFileId);
     }
     foreach ($replaceResources as $replace) {
         $this->replaceResource($replace[0], $replace[1], $xmlDoc);
     }
     // create a temporary XML file from the modified $xmlDoc
     $tempFile = $this->tempDirectory . DIRECTORY_SEPARATOR . uniqid() . '_' . $this->dropFolderFile->fileName;
     $xmlDoc->save($tempFile);
     $tempFileRealPath = realpath($tempFile);
     if (!$tempFileRealPath || !is_file($tempFileRealPath)) {
         $this->dropFolderFile->status = KalturaDropFolderFileStatus::ERROR_HANDLING;
         $this->dropFolderFile->errorCode = KalturaDropFolderFileErrorCode::ERROR_WRITING_TEMP_FILE;
         $this->dropFolderFile->errorDescription = "Error writing temporary file [{$tempFileRealPath}]";
         KalturaLog::err($this->dropFolderFile->errorDescription);
         $this->updateDropFolderFile();
         return false;
     }
     $conversionProfile = $this->getConversionProfile();
     // add bulk upload of type KalturaBulkUploadType::DROP_FOLDER_XML
     try {
         $this->impersonate($this->dropFolderFile->partnerId);
         $this->kClient->bulkUpload->add($conversionProfile->id, $tempFileRealPath, KalturaBulkUploadType::DROP_FOLDER_XML, $this->uploadedBy, $this->dropFolderFile->fileName);
         $this->unimpersonate();
     } catch (Exception $e) {
         $this->unimpersonate();
         $this->dropFolderFile->status = KalturaDropFolderFileStatus::ERROR_HANDLING;
         $this->dropFolderFile->errorCode = KalturaDropFolderFileErrorCode::ERROR_ADDING_BULK_UPLOAD;
         $this->dropFolderFile->errorDescription = 'Error adding bulk upload - ' . $e->getMessage();
         KalturaLog::err($this->dropFolderFile->errorDescription);
         $this->updateDropFolderFile();
         KalturaLog::err($this->dropFolderFile->errorDescription);
         return false;
     }
     //delete the temporary file
     @unlink($tempFileRealPath);
     $dropFolderFilePlugin = KalturaDropFolderClientPlugin::get($this->kClient);
     $dropFolderFilePlugin->dropFolderFile->updateStatus($this->dropFolderFile->id, KalturaDropFolderFileStatus::HANDLED);
     KalturaLog::debug('Drop folder file [' . $this->dropFolderFile->id . '] handled successfully');
     return true;
     // file handled
 }