portal.mkgtu.ru/common/components/AttachmentManager.php

452 lines
16 KiB
PHP
Raw Permalink Normal View History

2024-03-28 09:51:45 +03:00
<?php
namespace common\components;
use common\components\attachmentSaveHandler\exceptions\AttachmentViolationException;
use common\components\filesystem\FilterFilename;
use common\components\ReferenceTypeManager\ReferenceTypeManager;
use common\models\Attachment;
use common\models\attachment\attachmentCollection\BaseAttachmentCollection;
use common\models\AttachmentType;
use common\models\dictionary\DocumentType;
use common\models\EmptyCheck;
use common\models\errors\RecordNotValid;
use common\models\interfaces\ArchiveModelInterface;
use common\models\interfaces\AttachmentLinkableEntity;
use common\models\interfaces\FileToSendInterface;
use common\models\SendingFile;
use common\models\UserRegulation;
use common\modules\abiturient\models\File;
use common\modules\abiturient\models\interfaces\ApplicationConnectedInterface;
use common\modules\abiturient\models\interfaces\IReceivedFile;
use common\modules\abiturient\models\interfaces\QuestionaryConnectedInterface;
use Yii;
use yii\base\UserException;
use yii\db\ActiveQuery;
use yii\db\Exception;
use yii\db\Query;
use yii\helpers\ArrayHelper;
class AttachmentManager
{
private const INITIAL_CONFIG_TYPES = [
'other' => ['doc', 'docx', 'docm'],
'pdf' => ['pdf']
];
private static $rememberedInitialConfigTypes = [];
private static function getSystemTypesInitialSettings($typeId): array
{
$settings = [
AttachmentType::SYSTEM_TYPE_TARGET => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Документы целевых договоров"; для менеджера скан-копий: `Документы целевых договоров`'
),
'required' => true,
'related_entity' => PageRelationManager::RELATED_ENTITY_APPLICATION,
'from1c' => false,
'campaign_code' => null,
'document_type' => null,
'is_using' => true,
'hidden' => false,
],
AttachmentType::SYSTEM_TYPE_PREFERENCE => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Документы льгот и преимущественных прав"; для менеджера скан-копий: `Документы льгот и преимущественных прав`'
),
'required' => true,
'related_entity' => PageRelationManager::RELATED_ENTITY_APPLICATION,
'is_using' => true,
'hidden' => false,
],
AttachmentType::SYSTEM_TYPE_INDIVIDUAL_ACHIEVEMENT => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Документы индивидуальных достижений"; для менеджера скан-копий: `Документы индивидуальных достижений`'
),
'required' => false,
'related_entity' => PageRelationManager::RELATED_ENTITY_APPLICATION,
'is_using' => true,
'hidden' => false,
],
AttachmentType::SYSTEM_TYPE_ABITURIENT_AVATAR => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Фото поступающего"; для менеджера скан-копий: `Фото поступающего`'
),
'required' => true,
'related_entity' => PageRelationManager::RELATED_ENTITY_QUESTIONARY,
'is_using' => true,
'hidden' => false,
],
AttachmentType::SYSTEM_TYPE_FULL_RECOVERY_SPECIALITY => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Договоры об оказании платных образовательных услуг"; для менеджера скан-копий: `Договоры об оказании платных образовательных услуг`'
),
'required' => false,
'related_entity' => PageRelationManager::RELATED_ENTITY_APPLICATION,
'document_type_guid' => Yii::$app->configurationManager->getCode('paid_contract_document_type'),
'is_using' => true,
'hidden' => false,
],
AttachmentType::SYSTEM_TYPE_IDENTITY_DOCUMENT => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Документы подтверждающие личность"; для менеджера скан-копий: `Документы подтверждающие личность`'
),
'required' => true,
'related_entity' => PageRelationManager::RELATED_ENTITY_QUESTIONARY,
'is_using' => true,
'hidden' => false,
],
AttachmentType::SYSTEM_TYPE_EDUCATION_DOCUMENT => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Документы об образовании"; для менеджера скан-копий: `Документы об образовании`'
),
'required' => true,
'related_entity' => PageRelationManager::RELATED_ENTITY_APPLICATION,
'is_using' => true,
'hidden' => false,
],
AttachmentType::SYSTEM_TYPE_APPLICATION_RETURN => [
'name' => Yii::t(
'abiturient/attachment-widget/attachment-manager',
'Имя типа документа "Заявление на отзыв документов"; для менеджера скан-копий: `Заявление на отзыв документов`'
),
'required' => false,
'related_entity' => PageRelationManager::RELATED_ENTITY_APPLICATION,
'is_using' => true,
'hidden' => false,
],
];
return $settings[$typeId];
}
public static function GetSystemAttachmentType($typeId)
{
if (!in_array($typeId, AttachmentType::GetSystemTypes(), true)) {
throw new UserException('При поиске системного типа документа был передан неверный идентификатор системного типа документа.');
}
$type = AttachmentType::findOne([
'system_type' => $typeId,
]);
if (!$type) {
$type = new AttachmentType(static::getSystemTypesInitialSettings($typeId));
$type->system_type = $typeId;
$type->save(false);
}
return $type;
}
public static function linkAttachment(AttachmentLinkableEntity $en, Attachment $attachment)
{
$junction_data = [
$en::getEntityTableLinkAttribute() => $en->id,
$en::getAttachmentTableLinkAttribute() => $attachment->id
];
$already_linked = (new Query())->from($en::getTableLink())->where($junction_data)->exists();
if (!$already_linked) {
\Yii::$app->db->createCommand()->insert($en::getTableLink(), $junction_data)->execute();
}
}
public static function unlinkAttachment(AttachmentLinkableEntity $en, Attachment $attachment): int
{
return \Yii::$app->db->createCommand()->delete($en->getTableLink(), [
$en::getEntityTableLinkAttribute() => $en->id,
$en::getAttachmentTableLinkAttribute() => $attachment->id
])->execute();
}
public static function unlinkAllAttachment(AttachmentLinkableEntity $en): int
{
return \Yii::$app->db->createCommand()
->delete($en->getTableLink(), [
$en::getEntityTableLinkAttribute() => $en->id
])
->execute();
}
public static function unlinkAttachmentFromAll(Attachment $attachment): int
{
$errorFrom = '';
$deleteSuccess = true;
$id = $attachment->id;
if (!EmptyCheck::isEmpty($id)) {
foreach ($attachment->getAttachmentLinkDependency() as $class) {
$link = new $class();
$tableLink = $link->getTableLink();
$exists = (new Query())->from($tableLink)->where(['attachment_id' => $id])->exists();
if ($exists) {
$deleteSuccess = Yii::$app->db
->createCommand()
->delete($tableLink, ['attachment_id' => $id])
->execute();
if (!$deleteSuccess) {
$errorFrom .= "{$tableLink} -> attachment_id -> {$id}\n";
break;
}
}
}
}
if (!$deleteSuccess) {
Yii::error("Ошибка при удалении данных с портала. В таблице: {$errorFrom}");
}
return $deleteSuccess;
}
public static function GetEntityWithEmptyFilesQuery(AttachmentLinkableEntity $en): ActiveQuery
{
$table = $en::getTableLink();
$entityAttr = $en::getEntityTableLinkAttribute();
$attachmentAttr = $en::getAttachmentTableLinkAttribute();
$mainTableName = $en::getDbTableSchema()->name;
$query = $en::getModel()::find()
->leftJoin("{$table} tt", "tt.{$entityAttr} = {$mainTableName}.id")
->where([
"tt.{$attachmentAttr}" => null,
]);
if ($en instanceof ArchiveModelInterface) {
$query->andWhere([
'not', [$en::getModel()::tableName() . '.' . $en::getArchiveColumn() => $en::getArchiveValue()]
]);
}
return $query;
}
public static function handleAttachmentUpload(array $attachments, array $regulations = []): array
{
$resultAttachments = [];
foreach ($attachments as $attachment) {
try {
$newAttachments = $attachment->getAttachmentSaveHandler()->save();
} catch (AttachmentViolationException $exception) {
$attachment->addAttachmentsErrors([
$exception->getFileName() => $exception->getValidationErrors()
]);
}
if (!empty($newAttachments)) {
$attachment->attachments = array_merge($attachment->attachments, $newAttachments);
$resultAttachments = array_merge($resultAttachments, $newAttachments);
}
}
foreach ($regulations as $regulation) {
$regAttachment = $regulation->getAttachmentCollection();
if ($regAttachment !== null) {
$newAttachments = [];
try {
$regAttachment->getAttachmentSaveHandler()->setHistoryInitiator($regulation->owner);
$newAttachments = $regAttachment->getAttachmentSaveHandler()->save();
} catch (AttachmentViolationException $exception) {
$regAttachment->addAttachmentsErrors([
$exception->getFileName() => $exception->getValidationErrors()
]);
}
foreach ($newAttachments as $regulation_attachment) {
$regulation->link('rawAttachments', $regulation_attachment);
}
$resultAttachments = array_merge($resultAttachments, $newAttachments);
}
}
return $resultAttachments;
}
public static function buildAttachmentArrayTo1C(FileToSendInterface $table, DocumentType $file_document_type, $file_name = null)
{
if ((isset($table->deleted) && $table->deleted) || (isset($table->attachmentType) && $table->attachmentType->hidden)) {
return null;
}
$abs_path = $table->getAbsPath();
if ($abs_path && file_exists($abs_path) && !is_dir($abs_path)) {
if (!$file_name) {
$file_name = pathinfo($table->filename)['filename'];
}
$fileToSend = new SendingFile($table->linkedFile);
return $fileToSend->buildArrayTo1C($file_document_type, $file_name);
}
return null;
}
public static function buildFileTo1C(File $file, DocumentType $document_type, ?string $filename, ?array $file_parts): array
{
if (!$filename) {
$filename = pathinfo($file->upload_name)['filename'];
}
$filename = FilterFilename::sanitize($filename, false);
$result = [
'FileUID' => (string)$file->uid,
'FileHash' => (string)$file->content_hash,
'FileName' => (string)$filename,
'FileExt' => (string)$file->extension,
'FileTypeRef' => ReferenceTypeManager::GetReference($document_type),
];
if ($file_parts) {
$result['FileParts'] = $file_parts;
}
$result['Removed'] = 0;
return $result;
}
public static function GetInitialPreviewConfigTypeByExtension($extension)
{
$extension = strtolower($extension);
if (array_key_exists($extension, static::$rememberedInitialConfigTypes)) {
return static::$rememberedInitialConfigTypes[$extension];
}
foreach (static::INITIAL_CONFIG_TYPES as $initialConfigType => $supportedExtensions) {
if (in_array($extension, $supportedExtensions)) {
static::$rememberedInitialConfigTypes[$extension] = $initialConfigType;
return $initialConfigType;
}
}
static::$rememberedInitialConfigTypes[$extension] = 'image';
return 'image';
}
public static function GetMimeType($extension)
{
switch ($extension) {
case 'pdf':
return 'application/pdf';
break;
default:
return 'image/jpeg';
break;
}
}
public static function AttachFileToLinkableEntity(AttachmentLinkableEntity $entity, IReceivedFile $receivingFile): Attachment
{
$attachment_type = $entity->getAttachmentType();
$application = ArrayHelper::getValue($entity, 'application');
$questionary = ArrayHelper::getValue($entity, 'abiturientQuestionary');
if (!$application && !$questionary) {
$error_msg = "У сущности {$entity->getName()} отсутствует связь с анкетой или заявлением";
Yii::error($error_msg);
throw new UserException($error_msg);
}
$attachmentAttributes = [
'attachment_type_id' => $attachment_type->id,
];
if ($application) {
$attachmentAttributes['owner_id'] = $application->user_id;
$attachmentAttributes['application_id'] = $application->id;
} else {
$attachmentAttributes['owner_id'] = $questionary->user_id;
$attachmentAttributes['questionary_id'] = $questionary->id;
}
$attachment = $entity->getAttachments()
->joinWith(['linkedFile'])
->andWhere([
'attachment_type_id' => $attachment_type->id,
])
->andWhere([
File::tableName() . '.content_hash' => $receivingFile->getHash(),
])
->one();
if (!$attachment) {
$attachment = new Attachment();
$attachment->setAttributes($attachmentAttributes);
$attachment->scenario = Attachment::SCENARIO_RECOVER;
if (!$attachment->save()) {
throw new RecordNotValid($attachment);
}
}
$file = $receivingFile->getFile($attachment);
$attachment->LinkFile($file);
AttachmentManager::linkAttachment($entity, $attachment);
return $attachment;
}
}