Files
crmPRO/autoload/Domain/Tasks/TaskAttachmentRepository.php

258 lines
8.3 KiB
PHP

<?php
namespace Domain\Tasks;
class TaskAttachmentRepository
{
private $mdb;
private $upload_dir;
private $upload_url;
private $table_ready = false;
public function __construct( $mdb = null, $upload_dir = null, $upload_url = '/upload/task_attachments' )
{
if ( $mdb )
$this -> mdb = $mdb;
else
{
global $mdb;
$this -> mdb = $mdb;
}
$this -> upload_dir = $upload_dir ? rtrim( $upload_dir, '/\\' ) : getcwd() . DIRECTORY_SEPARATOR . 'upload' . DIRECTORY_SEPARATOR . 'task_attachments';
$this -> upload_url = rtrim( $upload_url, '/' );
}
public function listByTaskId( $task_id )
{
$this -> ensureStorage();
$rows = $this -> mdb -> select( 'tasks_attachments', '*', [
'AND' => [ 'task_id' => (int)$task_id, 'deleted' => 0 ],
'ORDER' => [ 'id' => 'DESC' ]
] );
if ( !is_array( $rows ) )
return [];
foreach ( $rows as &$row )
{
$row['title_effective'] = self::effectiveTitle( $row['title'], $row['original_name'] );
$row['url'] = $this -> buildPublicUrl( $row['relative_path'], $row['stored_name'] );
$row['size_human'] = $this -> formatSize( (int)$row['file_size'] );
}
return $rows;
}
public function upload( $task_id, $user_id, array $file )
{
$this -> ensureStorage();
if ( !isset( $file['error'] ) or $file['error'] !== UPLOAD_ERR_OK )
return [ 'status' => 'error', 'msg' => 'Nie udalo sie wgrac pliku.' ];
if ( !isset( $file['tmp_name'] ) or !is_uploaded_file( $file['tmp_name'] ) )
return [ 'status' => 'error', 'msg' => 'Nieprawidlowy plik.' ];
$original_name = trim( (string)$file['name'] );
if ( $original_name === '' )
return [ 'status' => 'error', 'msg' => 'Brak nazwy pliku.' ];
$safe_original_name = self::sanitizeFileName( $original_name );
$ext = strtolower( pathinfo( $safe_original_name, PATHINFO_EXTENSION ) );
$stored_name = uniqid( 'att_', true ) . ( $ext ? '.' . $ext : '' );
$relative_path = date( 'Y' ) . '/' . date( 'm' );
$target_dir = $this -> upload_dir . DIRECTORY_SEPARATOR . str_replace( '/', DIRECTORY_SEPARATOR, $relative_path );
if ( !is_dir( $target_dir ) )
@mkdir( $target_dir, 0777, true );
$target_file = $target_dir . DIRECTORY_SEPARATOR . $stored_name;
if ( !move_uploaded_file( $file['tmp_name'], $target_file ) )
return [ 'status' => 'error', 'msg' => 'Nie udalo sie zapisac pliku.' ];
return $this -> storeMeta( $task_id, $user_id, $safe_original_name, $stored_name, $relative_path, $ext, isset( $file['size'] ) ? (int)$file['size'] : 0 );
}
public function uploadFromContent( $task_id, $user_id, $original_name, $content )
{
$this -> ensureStorage();
$original_name = trim( (string)$original_name );
if ( $original_name === '' )
$original_name = 'zalacznik';
$safe_original_name = self::sanitizeFileName( $original_name );
$ext = strtolower( pathinfo( $safe_original_name, PATHINFO_EXTENSION ) );
$stored_name = uniqid( 'att_', true ) . ( $ext ? '.' . $ext : '' );
$relative_path = date( 'Y' ) . '/' . date( 'm' );
$target_dir = $this -> upload_dir . DIRECTORY_SEPARATOR . str_replace( '/', DIRECTORY_SEPARATOR, $relative_path );
if ( !is_dir( $target_dir ) )
@mkdir( $target_dir, 0777, true );
$target_file = $target_dir . DIRECTORY_SEPARATOR . $stored_name;
if ( file_put_contents( $target_file, (string)$content ) === false )
return [ 'status' => 'error', 'msg' => 'Nie udalo sie zapisac pliku.' ];
return $this -> storeMeta( $task_id, $user_id, $safe_original_name, $stored_name, $relative_path, $ext, strlen( (string)$content ) );
}
public function rename( $attachment_id, $title )
{
$this -> ensureStorage();
$title = trim( (string)$title );
return $this -> mdb -> update( 'tasks_attachments', [
'title' => $title !== '' ? $title : null
], [
'AND' => [ 'id' => (int)$attachment_id, 'deleted' => 0 ]
] );
}
public function delete( $attachment_id, $deleted_by_user_id = null )
{
$this -> ensureStorage();
$attachment = $this -> mdb -> get( 'tasks_attachments', '*', [
'AND' => [ 'id' => (int)$attachment_id, 'deleted' => 0 ]
] );
if ( !$attachment )
return false;
$file_path = $this -> upload_dir . DIRECTORY_SEPARATOR .
str_replace( '/', DIRECTORY_SEPARATOR, $attachment['relative_path'] ) .
DIRECTORY_SEPARATOR . $attachment['stored_name'];
if ( file_exists( $file_path ) )
@unlink( $file_path );
return $this -> mdb -> update( 'tasks_attachments', [
'deleted' => 1,
'deleted_by' => $deleted_by_user_id ? (int)$deleted_by_user_id : null,
'date_delete' => date( 'Y-m-d H:i:s' )
], [ 'id' => (int)$attachment_id ] );
}
public function purgeByTaskId( $task_id )
{
$this -> ensureStorage();
$rows = $this -> mdb -> select( 'tasks_attachments', '*', [
'task_id' => (int)$task_id
] );
if ( !is_array( $rows ) )
return false;
foreach ( $rows as $attachment )
{
$file_path = $this -> resolveFilePath( $attachment );
if ( $file_path !== '' and file_exists( $file_path ) )
@unlink( $file_path );
}
$this -> mdb -> delete( 'tasks_attachments', [ 'task_id' => (int)$task_id ] );
return true;
}
public static function effectiveTitle( $title, $fallback )
{
$title = trim( (string)$title );
return $title !== '' ? $title : (string)$fallback;
}
public static function sanitizeFileName( $name )
{
$name = preg_replace( '/[^\p{L}\p{N}\s\.\-_]+/u', '_', (string)$name );
$name = preg_replace( '/\s+/', '_', $name );
$name = trim( $name, '._-' );
return $name !== '' ? $name : 'zalacznik';
}
private function ensureStorage()
{
if ( !is_dir( $this -> upload_dir ) )
@mkdir( $this -> upload_dir, 0777, true );
if ( !$this -> table_ready )
{
$this -> ensureTable();
$this -> table_ready = true;
}
}
private function ensureTable()
{
$this -> mdb -> query(
'CREATE TABLE IF NOT EXISTS `tasks_attachments` (
`id` INT NOT NULL AUTO_INCREMENT,
`task_id` INT NOT NULL,
`user_id` INT NOT NULL,
`title` VARCHAR(255) NULL,
`original_name` VARCHAR(255) NOT NULL,
`stored_name` VARCHAR(255) NOT NULL,
`relative_path` VARCHAR(255) NOT NULL,
`file_ext` VARCHAR(20) NULL,
`file_size` INT UNSIGNED NOT NULL DEFAULT 0,
`date_add` DATETIME NOT NULL,
`deleted` TINYINT(1) NOT NULL DEFAULT 0,
`deleted_by` INT NULL,
`date_delete` DATETIME NULL,
PRIMARY KEY (`id`),
INDEX `idx_tasks_attachments_task` (`task_id`),
INDEX `idx_tasks_attachments_deleted` (`deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
);
}
private function storeMeta( $task_id, $user_id, $safe_original_name, $stored_name, $relative_path, $ext, $size )
{
$insert = $this -> mdb -> insert( 'tasks_attachments', [
'task_id' => (int)$task_id,
'user_id' => (int)$user_id,
'title' => null,
'original_name' => $safe_original_name,
'stored_name' => $stored_name,
'relative_path' => $relative_path,
'file_ext' => $ext,
'file_size' => (int)$size,
'date_add' => date( 'Y-m-d H:i:s' ),
'deleted' => 0
] );
if ( !$insert )
return [ 'status' => 'error', 'msg' => 'Nie udalo sie zapisac zalacznika w bazie.' ];
$attachment_id = $this -> mdb -> id();
return [ 'status' => 'success', 'id' => (int)$attachment_id, 'relative_path' => $relative_path, 'stored_name' => $stored_name ];
}
private function buildPublicUrl( $relative_path, $stored_name )
{
return $this -> upload_url . '/' . trim( $relative_path, '/' ) . '/' . rawurlencode( $stored_name );
}
private function formatSize( $bytes )
{
if ( $bytes < 1024 )
return $bytes . ' B';
$kb = $bytes / 1024;
if ( $kb < 1024 )
return number_format( $kb, 1, '.', '' ) . ' KB';
return number_format( $kb / 1024, 1, '.', '' ) . ' MB';
}
private function resolveFilePath( array $attachment )
{
if ( !isset( $attachment['relative_path'] ) or !isset( $attachment['stored_name'] ) )
return '';
return $this -> upload_dir . DIRECTORY_SEPARATOR .
str_replace( '/', DIRECTORY_SEPARATOR, (string)$attachment['relative_path'] ) .
DIRECTORY_SEPARATOR . (string)$attachment['stored_name'];
}
}