I found a way:
Code: Select all
/*
addAttachmentToPost
Downloads a file from a given $url to the local server and adds it as an attachment to the post with the given $postId. This post must exist.
The attachment's $comment is optional and HTML-Code will not be escaped. You have to apply htmlspecialchars() on forign/user-input content given as comment!
If $dispatchEvent is true, the core.modify_attachment_sql_ary_on_submit will be triggered to allow other extensions to work on the attachment.
If $topicId, $forumId AND the poster's $userId (which is not always the current user's ID) of the given post are known, they can be given to save one SQL-query.
$realFileName can be given; if empty, the file name is taken from the url.
Returns an array holding the error information. If successfull, first array element is 'SUCCESS', second element the ID of the new attachment, and third element again the post ID.
*/
private function addAttachmentToPost ($url, $postId, $comment='', $dispatchEvent=true, $topicId=0, $forumId=0, $userId=0, $realFileName='') {
if (getType($url) != 'string' || getType($postId) != 'integer' || getType($comment) != 'string' || getType($dispatchEvent) != 'boolean' || getType($topicId) != 'integer' || getType($forumId) != 'integer' || getType($userId) != 'integer') throw 'Type Missmatch';
if ($postId <= 0) throw 'Post ID cannot be zero!';
// if not given, get missing IDs
if ($topicId == 0 || $forumId == 0 || $userId == 0) {
$idRow = $this->db->sql_fetchrow($this->db->sql_query('SELECT post_id, topic_id, forum_id, poster_id FROM '.$this->table_prefix.'posts WHERE post_id = '.$postId));
if (!$idRow)
return ['POST_NOT_EXISTS'];
$topicId = intval($idRow['topic_id']);
$forumId = intval($idRow['topic_id']);
$userId = intval($idRow['poster_id']);
}
// check attachment count
if (intval($this->config['max_attachments']) >= 0) {
$cnt = $this->db->sql_fetchrow($this->db->sql_query('SELECT COUNT(*) as cnt FROM '.$this->table_prefix.'attachments WHERE post_msg_id = '.$postId))['cnt'];
if ($cnt >= intval($this->config['max_attachments']))
return ['MAX_ATTACHMENTS_PER_POST_EXCEEDED'];
}
// get required classes
$upload = $this->phpbb_container->get('files.upload');
$cache = $this->phpbb_container->get('cache');
$attach = $this->phpbb_container->get('attachment.upload');
// load file from remote location to local server
$upload->set_disallowed_content([]);
$extensions = $cache->obtain_attach_extensions($forumId);
$extensionArr = array_keys($extensions['_allowed_']);
$upload->set_allowed_extensions($extensionArr);
$tempFile = $upload->handle_upload('files.types.remote', $url);
if (count($tempFile->error) > 0) {
$ext = '.';
if (strrpos($url, '.') !== false) $ext = substr($url, strrpos($url, '.')+1);
if ($tempFile->error[0] == 'URL_INVALID' && !in_array($ext, $extensionArr)) return ['FILE_EXTENSION_NOT_ALLOWED', 'EXTENSION=.'.htmlspecialchars($ext)];
return $tempFile->error;
}
$tempFileData = [
'realname' => (($realFileName == '')?$tempFile->get('realname'):htmlspecialchars($realFileName)),
'size' => $tempFile->get('filesize'),
'type' => $tempFile->get('mimetype'),
];
// create attachment from temp file
if (!function_exists('create_thumbnail'))
require($this->phpbb_root_path.'includes/functions_posting.php');
$attachmentFileData = $attach->upload('', $forumId, true, $tempFile->get('filename'), false, $tempFileData);
if (!$attachmentFileData['post_attach'])
return ['FILE_ATTACH_ERROR'];
if (count($attachmentFileData['error']) > 0)
return $attachmentFileData['error'];
$sql_ary = array(
'physical_filename' => $attachmentFileData['physical_filename'],
'attach_comment' => $comment,
'real_filename' => $attachmentFileData['real_filename'],
'extension' => $attachmentFileData['extension'],
'mimetype' => $attachmentFileData['mimetype'],
'filesize' => $attachmentFileData['filesize'],
'filetime' => $attachmentFileData['filetime'],
'thumbnail' => $attachmentFileData['thumbnail'],
'is_orphan' => 0,
'in_message' => 0,
'poster_id' => $userId,
'post_msg_id' => $postId,
'topic_id' => $topicId,
);
if ($dispatchEvent) {
$dispatcher = $this->phpbb_container->get('dispatcher');
$vars = array('sql_ary');
extract($dispatcher->trigger_event('core.modify_attachment_sql_ary_on_submit', compact($vars)));
}
$this->db->sql_query('INSERT INTO '.$this->table_prefix.'attachments '.$this->db->sql_build_array('INSERT', $sql_ary));
$newAttachmentID = intval($this->db->sql_nextid());
if ($newAttachmentID == 0) return ['SQL_ATTACHMENT_INSERT_ERROR'];
$this->db->sql_query('UPDATE '.$this->table_prefix.'posts SET post_attachment = 1 WHERE post_id = '.$postId);
return ['SUCCESS', $newAttachmentID, $postId];
}
This function requires:
- $this->db to be \phpbb\db\driver\driver_interface - '@dbal.conn'
- $this->config to be \phpbb\config\config - '@config'
- $this->phpbb_container to be dependency injector - '@service_container'
- $this->table_prefix to be a string representing the phpBB's table prefix including the first _
- $this->phpbb_root_path the root path to import other phpBB files - '%core.root_path%'
Please note, that html-code given as $comment will not be escaped. For some applications, it is helpful to keep some HTML-codes for file comments - but never use the quote-character ", because the comment can be the alt-attribute for images. But you can hide the comment by putting <!-- --> around it. This way you ~can~ store i.e. special file ids for each attachment.
If the database is not configured to store 4-byte-unicode-chars, you will need to perform utf8_encode_ucr on $comment and $realFileName.
I should be able to synchronize file extensions from telegram with the forum, soon.