logger = $logger;
$this->db = $db;
}
/**
* @CronJob("*\/10 * * * *")
*/
public function sendFileNotifications(string $scope)
{
// Get archives with notifications enabled
$Root = PageModel::findBy(array("sd_nc_enable = ?","type = 'root'"),'1');
if ($Root !== null)
{
while ($Root->next())
{
// Do we have new items
$Members = $this->db->executeQuery("SELECT s.pid FROM tl_member_secureDownloads s INNER JOIN tl_files f ON f.uuid = s.uuid WHERE s.nc_sent != '1' GROUP BY s.pid");
// Load groups and notification models if we have news to share
if ($Members->rowCount() && ($Notification = Notification::findByPk($Root->sd_nc_notification)) !== null)
{
foreach ($Members->iterateAssociative() as $member)
{
if (($Member = MemberModel::findOneBy(array("disable != '1'","login = '1'","email LIKE '%@%'","id = ?"),array($member['pid']))) !== null)
{
$Files = $this->db->executeQuery("SELECT s.id, f.uuid, s.ctime FROM tl_member_secureDownloads s INNER JOIN tl_files f ON f.uuid = s.uuid WHERE s.pid = ? AND s.nc_sent != '1' ORDER BY s.ctime DESC, f.name",[$Member->id]);
$arrFileIds = [];
if ($Files->rowCount())
{
$arrDownloads = array();
foreach ($Files->iterateAssociative() as $file)
{
if (($File = FilesModel::findByUuid($file['uuid'])) !== null)
{
$arrDownloads[] = date('d.m.Y', $file['ctime']) . " - " . $File->name;
$arrFileIds[] = $file['id'];
}
}
$Notification->send(array
(
'member_email' => $Member->email,
'member_firstname' => $Member->firstname,
'member_lastname' => $Member->lastname,
'downloads' => implode("\n",$arrDownloads),
'downloads_html' => "
\n- ".implode("
\n- ",$arrDownloads)."
\n
"
),$GLOBALS['TL_LANGUAGE']);
}
// Flag news as sent
$this->db->executeStatement("UPDATE tl_member_secureDownloads SET nc_sent = '1' WHERE id IN (" . implode(',', $arrFileIds) . ")");
}
}
$this->logger->log(LogLevel::INFO, 'Secure downloads notifications has been sent (' . $Members->rowCount() . ')', array('contao' => new ContaoContext(__METHOD__, 'CRON')));
}
}
}
}
/**
* @CronJob("* * * * *")
*/
public function importFiles(string $scope)
{
$objRoots = PageModel::findPublishedRootPages();
$intFileCount = 0;
// No root pages available
if ($objRoots === null)
{
return;
}
// Iterate page roots
while ($objRoots->next())
{
if (System::getContainer()->getParameter('kernel.debug'))
{
$this->logger->log(LogLevel::DEBUG, sprintf('Starting secure downloads import for %s', $objRoots->title), array('contao' => new ContaoContext(__METHOD__, 'CRON')));
}
// Continue if secure downloads is disabled
if (!$objRoots->secureDownloadsEnabled)
{
continue;
}
// Get folder models
$objFolder = FilesModel::findByUuid($objRoots->secureDownloadsSRC);
$objTarget = FilesModel::findByUuid($objRoots->secureDownloadsTarget);
// Continue if folder doesn't exist
if ($objFolder === null || !file_exists(TL_ROOT . "/".$objFolder->path) || $objTarget === null || !file_exists(TL_ROOT . "/".$objTarget->path))
{
$this->logger->log(LogLevel::WARNING, sprintf('Source or target folder is missing for page root %s. %s %s', $objRoots->title,$objFolder->path,$objTarget->path), array('contao' => new ContaoContext(__METHOD__, 'ERROR')));
continue;
}
// Read files inside folder
$objFiles = FilesModel::findByPid($objFolder->uuid);
// Continue if folder is empty
if ($objFiles === null)
{
continue;
}
// Escape single quotes in fragment regexp
$objRoots->secureDownloadsRegExp = addcslashes($objRoots->secureDownloadsRegExp,'\'');
// Iterate files
while ($objFiles->next())
{
// Skip subfolders and special files
if ($objFiles->type == 'folder' || strpos($objFiles->name,'.') === 0)
{
continue;
}
// Continue if file doesn't exist
if (!file_exists(TL_ROOT . "/".$objFiles->path))
{
continue;
}
$objFile = new File($objFiles->path);
// Check for fragments
if (!preg_match('/'.$objRoots->secureDownloadsRegExp.'/U',$objFile->filename,$fragments))
{
$this->logger->log(LogLevel::WARNING, sprintf('File "%s" is missing a member fragment or has the wrong syntax.', $objFile->name), array('contao' => new ContaoContext(__METHOD__, 'ERROR')));
continue;
}
// Find member
$arrColumns = array();
$arrValues = array();
foreach (StringUtil::deserialize($objRoots->secureDownloadsFields, true) as $i => $field)
{
$arrColumns[] = "$field = ?";
$arrValues[] = $fragments[$i+1];
}
$objMember = MemberModel::findOneBy($arrColumns,$arrValues);
// Continue if no member found
if ($objMember === null) {
$this->logger->log(LogLevel::WARNING, sprintf('Could not find member for file "%s". (%s) [%s]', $objFile->name, implode(' AND ',$arrColumns),implode(', ',$arrValues)), array('contao' => new ContaoContext(__METHOD__, 'ERROR')));
continue;
}
// Remove fragments from file name
$baseFilename = preg_replace('/'.$objRoots->secureDownloadsRegExp.'/U','',$objFile->filename);
$sanitizedFilename = $baseFilename.'.'.$objFile->extension;
// Check or create folder structure
$strSubFolder = sprintf("%03d",ceil(($objMember->id+1)/100)-1).'/'.$objMember->id;
$strTargetFolder = $objTarget->path.'/'.$strSubFolder;
$arrFolders = explode('/',$strTargetFolder);
$strStartPath = '';
foreach ($arrFolders as $folder)
{
if (!is_dir(TL_ROOT . '/' . $strStartPath . $folder))
{
Files::getInstance()->mkdir($strStartPath . $folder);
}
$strStartPath .= $folder . '/';
}
// Do not overwrite existing files
$copyId = 1;
while(file_exists(TL_ROOT . "/".$strTargetFolder.'/'.$sanitizedFilename))
{
$sanitizedFilename = $baseFilename.'_'.$copyId++.'.'.$objFile->extension;
}
// Try to copy file
if (!Files::getInstance()->copy($objFile->path,$strTargetFolder.'/'.$sanitizedFilename))
{
$this->logger->log(LogLevel::WARNING, sprintf('Could not import file "%s" for member ID "%s".', $objFile->name, $objMember->id), array('contao' => new ContaoContext(__METHOD__, 'ERROR')));
continue;
}
$File = Dbafs::addResource($strTargetFolder.'/'.$sanitizedFilename,false);
// Add file to DB and delete source
$arrData = array(
'pid' => $objMember->id,
'uuid' => ($File !== null ? $File->uuid : ''),
'tstamp' => time(),
'ctime' => time(),
// 'name' => $sanitizedFilename,
// 'path' => $strTargetFolder.'/'.$sanitizedFilename
);
$this->db->insert('tl_member_secureDownloads',$arrData);
if (!$objFile->delete()) {
$this->logger->log(LogLevel::WARNING, sprintf('Could not delete source file "%s" for member ID "%s".', $objFile->name, $objMember->id), array('contao' => new ContaoContext(__METHOD__, 'ERROR')));
}
$intFileCount++;
}
}
if ($intFileCount)
{
$this->logger->log(LogLevel::INFO, sprintf("Imported %s files for secure member downloads",$intFileCount), array('contao' => new ContaoContext(__METHOD__, 'CRON')));
}
}
}