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

452 lines
16 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}