HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers95/rentman.io/app/Komma/Kms/Transfer/AbstractFolderImporter.php
<?php

namespace App\Komma\Kms\Transfer;

use App\Komma\Documents\Kms\DocumentService;
use App\Komma\Documents\Kms\DocumentServiceInterface;
use App\Komma\Kms\Core\Attributes\Models\ImageProperty;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\MessageBag;

/**
 * Class AbstractFolderImporter
 *
 * Knows how to import data from folders. Used to import images, pdfs etc and usually link them to eloquent models.
 */
abstract class AbstractFolderImporter implements DocumentImporterInterface
{
    protected $attributeValueReferenceKey = 'documents';

    /** @var string */
    protected $fromStorageAppFolder;

    /** @var string */
    protected $toPublicUploadsSubFolder;

    /** @var DocumentService */
    protected $documentService;

    public function __construct()
    {
        if (! $this->fromStorageAppFolder) {
            throw new \RuntimeException('Please set the fromStorageAppFolder variable first');
        }
        $this->createStorageFolderIfNotExists($this->fromStorageAppFolder);

        if (! $this->toPublicUploadsSubFolder) {
            throw new \RuntimeException('Please set the toPublicUploadsSubFolder variable first');
        }
        $this->createFolderIfNotExists(public_path('uploads'.DIRECTORY_SEPARATOR.$this->toPublicUploadsSubFolder));

        $this->documentService = \App::make(DocumentServiceInterface::class);
    }

    /**
     * Creates a folder in the current storage if it does not exists
     *
     * @param string $folder
     */
    private function createStorageFolderIfNotExists(string $folder)
    {
        if (! Storage::exists($folder)) {
            Storage::makeDirectory($folder);
        }
    }

    /**
     * Creates a folder in the current folder if it does not exists
     *
     * @param string $folder
     */
    private function createFolderIfNotExists(string $folder)
    {
        if (! file_exists($folder)) {
            if (! @mkdir($folder)) {
                throw new \RuntimeException('Could not create directory: '.$folder);
            }
        }
    }

    /**
     * Imports documents. For example images and pdfs
     * And return a message bag with messages that occured during this process
     *
     * @return MessageBag
     */
    public function importDocuments(): MessageBag
    {
        $messageBag = new MessageBag();

        $files = Storage::files($this->fromStorageAppFolder);

        //Prevent memory exhaustion errors
        $maxMemoryForImport = 128000000; //128 Megabytes (128000000 bytes). Php default
        \Debugbar::disable();
        set_time_limit(0);
        ini_set('memory_limit', $maxMemoryForImport);

        foreach ($files as $sourceFilePath) {
//            \Log::debug('Mem usage: '.(memory_get_usage(true) / 1024 / 1024));
            if (memory_get_usage(true) >= $maxMemoryForImport * .5) {
                $messageBag->add('errors', __('kms/transfer.memory_exhaustion_files'));

                return $messageBag;
            }

            $sourceFilePath = storage_path('app'.DIRECTORY_SEPARATOR.$sourceFilePath);
            $fileName = pathinfo($sourceFilePath, PATHINFO_FILENAME);
            $model = $this->getModelFromFileName($fileName);
            if ($model) {
                if (! $this->documentService->fileLinkedForModel($model, $fileName)) {
                    $this->documentService->linkFileToModelAsDocument($model, $sourceFilePath, $this->toPublicUploadsSubFolder, $this->imageProperties(), $this->attributeValueReferenceKey);
                    $messageBag->add('successes', __('kms/transfer.folderImport.document_import_success', ['filename' => $fileName]));
                } else {
                    @unlink($sourceFilePath);
                    $messageBag->add('successes', __('kms/transfer.folderImport.document_import_skipped', ['filename' => $fileName]));
                }
            } else {
                $messageBag->add('errors', __('kms/transfer.folderImport.document_import_error', ['filename' => $fileName]));
                if (! unlink($sourceFilePath)) {
                    throw new \RuntimeException("Could not delete file '".$sourceFilePath."'. Please contact your administrator for help.");
                }
            }
        }

        return $messageBag;
    }

    /**
     * Tries to get an eloquent model that belongs to the specified filename.
     * You could for example have a filename defined like a EAN code, that references an unique ean attribute on an eloquent model.
     * By this you should be able with this method to return an eloquent model. If not, just return or return null
     *
     * @param string $filename
     * @return Model|null
     */
    abstract public function getModelFromFileName(string $filename):?Model;

    /**
     * Returns an array of image properties that are used when imported documents are images.
     * Note: The image properties names without "image_url" suffixed to it, must correspond to the column names of the Documents model table. Or otherwise how the document service specifies it.
     * @return array
     */
    public function imageProperties():array
    {
        return [
            //            (new ImageProperty())->setName('original')->setCropMethod(ImageProperty::CropFit)->setWidth(2000)->setHeight(8000), //exhausts php memory on some installations and causes errors like this: Allowed memory size of 134217728 bytes exhausted (tried to allocate 38400001 bytes or internal server errors
            (new ImageProperty())->setName('thumb')->setCropMethod(ImageProperty::Fit)->setWidth(100),
            (new ImageProperty())->setName('small')->setCropMethod(ImageProperty::Fit)->setWidth(240),
            (new ImageProperty())->setName('medium')->setCropMethod(ImageProperty::Fit)->setWidth(460),
            (new ImageProperty())->setName('large')->setCropMethod(ImageProperty::Fit)->setWidth(500),
        ];
    }
}