luyadev/luya-module-admin

View on GitHub
src/aws/FlowActiveWindow.php

Summary

Maintainability
A
3 hrs
Test Coverage
F
0%
<?php

namespace luya\admin\aws;

use Flow\Config;
use Flow\File;
use Flow\Request;
use luya\admin\helpers\Storage;
use luya\admin\ngrest\base\ActiveWindow;
use luya\helpers\FileHelper;
use Yii;
use yii\base\InvalidConfigException;

/**
 * Flow Uploader ActiveWindow enables multi image upload with chunck ability.
 *
 * The Flow ActiveWindow will not store any data in the filemanager as its thought to be used in large image upload
 * scenarios like galleries. The image are chuncked into parts in order to enable large image uploads.
 *
 * Example use:
 *
 * ```php
 * public function ngRestActiveWindows()
 * {
 *   return [
 *       ['class' => \luya\admin\aws\FlowActiveWindow::class, 'label' => 'My Gallery'],
 *   ];
 * }
 * ```
 *
 * The attached model class must implement the interface {{\luya\admin\aws\FlowActiveWindowInterface}} in order to interact with thw Activ Window.
 *
 * There is also a helper Trait {{\luya\admin\aws\FlowActiveWindowTrait}} you can include in order to work with a relation table.
 *
 * @author Basil Suter <basil@nadar.io>
 * @since 1.0.0
 */
class FlowActiveWindow extends ActiveWindow
{
    /**
     * @var string The name of the module where the ActiveWindow is located in order to find the view path.
     */
    public $module = '@admin';

    /**
     * @inheritdoc
     */
    public function index()
    {
        return $this->render('index');
    }

    /**
     * @inheritdoc
     */
    public function defaultLabel()
    {
        return 'Flow Uploader';
    }

    /**
     * @inheritdoc
     */
    public function defaultIcon()
    {
        return 'cloud_upload';
    }

    /**
     * @inheritdoc
     */
    public function getModel()
    {
        $model = parent::getModel();

        if (!$model instanceof FlowActiveWindowInterface) {
            throw new InvalidConfigException("The model ".$this->model->className()."which attaches the FlowActiveWindow must be an instance of luya\admin\aws\FlowActiveWindowInterface.");
        }

        return $model;
    }

    /**
     * Returns a list of uploaded images.
     *
     * @return array
     */
    public function callbackList()
    {
        $data = $this->model->flowListImages();

        $images = [];
        foreach (Yii::$app->storage->findImages(['in', 'id', $data]) as $item) {
            $images[$item->id] = $item->applyFilter('small-crop')->toArray();
        }

        return $this->sendSuccess('list loaded', [
            'images' => $images,
        ]);
    }

    /**
     * Remove a given image from the collection.
     *
     * @param integer $imageId
     * @return array
     */
    public function callbackRemove($imageId)
    {
        $image = Yii::$app->storage->getImage($imageId);

        if ($image) {
            $this->model->flowDeleteImage($image);
            if (Storage::removeImage($image->id, true)) {
                return $this->sendSuccess('image has been removed');
            }
        }

        return $this->sendError('Unable to remove this image');
    }

    /**
     * Flow Uploader Upload.
     */
    public function callbackUpload()
    {
        $config = new Config();
        $config->setTempDir($this->getTempFolder());
        $file = new File($config);
        $request = new Request();

        if ($_SERVER['REQUEST_METHOD'] === 'GET') {
            if ($file->checkChunk()) {
                header("HTTP/1.1 200 Ok");
            } else {
                header("HTTP/1.1 204 No Content");
                exit;
            }
        } else {
            if ($file->validateChunk()) {
                $file->saveChunk();
            } else {
                // error, invalid chunk upload request, retry
                header("HTTP/1.1 400 Bad Request");
                exit;
            }
        }
        if ($file->validateFile() && $file->save($this->getUploadFolder() . '/'.$request->getFileName())) {
            // File upload was completed
            $file = Yii::$app->storage->addFile($this->getUploadFolder() . '/'.$request->getFileName(), $request->getFileName(), 0, true);

            if ($file) {
                @unlink($this->getUploadFolder() . '/'.$request->getFileName());

                $image = Yii::$app->storage->addImage($file->id);
                if ($image) {
                    $image->applyFilter('small-crop');

                    $this->model->flowSaveImage($image);
                    return 'done';
                }
            }
        } else {
            // This is not a final chunk, continue to upload
        }
    }

    protected function getTempFolder()
    {
        $folder = Yii::getAlias('@runtime/flow-cache');

        if (!file_exists($folder)) {
            FileHelper::createDirectory($folder, 0777);
        }

        return $folder;
    }

    protected function getUploadFolder()
    {
        $folder = Yii::getAlias('@runtime/flow-upload');

        if (!file_exists($folder)) {
            FileHelper::createDirectory($folder, 0777);
        }

        return $folder;
    }
}