Commit 826fbcf7 authored by Mark Harding's avatar Mark Harding
Browse files

Merge branch 'goal/pro-logo-upload' into 'master'

Pro logo and background upload

Closes #970 and #963

See merge request !375
parents d1de8a39 0f17d362
Loading
Loading
Loading
Loading
+138 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * settings assets
 * @author edgebal
 */

namespace Minds\Controllers\api\v2\pro\settings;

use Exception;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Manager;
use Minds\Core\Pro\Assets\Manager as AssetsManager;
use Minds\Core\Session;
use Minds\Entities\User;
use Minds\Interfaces;
use Minds\Api\Factory;
use Zend\Diactoros\ServerRequest;

class assets implements Interfaces\Api
{
    /** @var ServerRequest */
    public $request;
    
    /**
     * Equivalent to HTTP GET method
     * @param array $pages
     * @return mixed|null
     */
    public function get($pages)
    {
        return Factory::response([]);
    }

    /**
     * Equivalent to HTTP POST method
     * @param array $pages
     * @return mixed|null
     * @throws Exception
     */
    public function post($pages)
    {
        $type = $pages[0] ?? null;

        // Check and validate user

        $user = Session::getLoggedinUser();

        if (isset($pages[1]) && $pages[1]) {
            if (!Session::isAdmin()) {
                return Factory::response([
                    'status' => 'error',
                    'message' => 'You are not authorized',
                ]);
            }

            $user = new User($pages[1]);
        }

        // Check uploaded file

        /** @var \Zend\Diactoros\UploadedFile[] $files */
        $files = $this->request->getUploadedFiles();

        if (!$files || !isset($files['file'])) {
            return Factory::response([
                'status' => 'error',
                'message' => 'Missing file',
            ]);
        }

        $file = $files['file'];

        if ($file->getError()) {
            return Factory::response([
                'status' => 'error',
                'message' => sprintf('Error %s when uploading file', $files['file']->getError()),
            ]);
        }

        // Get Pro managers

        /** @var Manager $manager */
        $manager = Di::_()->get('Pro\Manager');
        $manager
            ->setUser($user)
            ->setActor(Session::getLoggedinUser());

        if (!$manager->isActive()) {
            return Factory::response([
                'status' => 'error',
                'message' => 'You are not Pro',
            ]);
        }

        /** @var AssetsManager $assetsManager */
        $assetsManager = Di::_()->get('Pro\Assets\Manager');
        $assetsManager
            ->setType($type)
            ->setUser($user)
            ->setActor(Session::getLoggedinUser());

        try {
            $success = $assetsManager
                ->set($file);

            if (!$success) {
                throw new Exception(sprintf("Cannot save Pro %s asset", $type));
            }
        } catch (\Exception $e) {
            return Factory::response([
                'status' => 'error',
                'message' => $e->getMessage(),
            ]);
        }

        return Factory::response([]);
    }

    /**
     * Equivalent to HTTP PUT method
     * @param array $pages
     * @return mixed|null
     */
    public function put($pages)
    {
        return Factory::response([]);
    }

    /**
     * Equivalent to HTTP DELETE method
     * @param array $pages
     * @return mixed|null
     */
    public function delete($pages)
    {
        return Factory::response([]);
    }
}
+42 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * pro
 * @author edgebal
 */

namespace Minds\Controllers\fs\v1;

use Minds\Core\Pro\Assets\Asset;
use Minds\Interfaces;

class pro implements Interfaces\FS
{
    /**
     * Equivalent to HTTP GET method
     * @param array $pages
     * @return mixed|null
     * @throws \IOException
     * @throws \InvalidParameterException
     * @throws \Exception
     */
    public function get($pages)
    {
        $asset = new Asset();
        $asset
            ->setType($pages[1] ?? null)
            ->setUserGuid($pages[0] ?? null);

        $file = $asset->getFile();
        $file->open('read');

        $contents = $file->read();

        header(sprintf("Content-Type: %s", $asset->getMimeType()));
        header(sprintf("Expires: %s", date('r', time() + 864000)));
        header('Pragma: public');
        header('Cache-Control: public');

        echo $contents;
        exit;
    }
}
+19 −0
Original line number Original line Diff line number Diff line
@@ -49,6 +49,17 @@ class Manager
        return $this->image->getImageBlob();
        return $this->image->getImageBlob();
    }
    }


    public function getPng()
    {
        if (!$this->image) {
            throw new \Exception('Output was not generated');
        }

        $this->image->setImageFormat('png');

        return $this->image->getImageBlob();
    }

    /**
    /**
     * @param $value
     * @param $value
     * @return $this
     * @return $this
@@ -61,6 +72,14 @@ class Manager
        return $this;
        return $this;
    }
    }


    public function setImageFromBlob($blob, $fileName = null)
    {
        $this->image = new \Imagick();
        $this->image->readImageBlob($blob, $fileName);

        return $this;
    }

    /**
    /**
     * @return $this
     * @return $this
     */
     */
+95 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * Info
 * @author edgebal
 */

namespace Minds\Core\Pro\Assets;

use ElggFile;
use Exception;
use Minds\Traits\MagicAttributes;

/**
 * Class Asset
 * @package Minds\Core\Pro\Assets
 * @method string getType()
 * @method int|string getUserGuid()
 * @method Asset setUserGuid(int|string $userGuid)
 */
class Asset
{
    use MagicAttributes;

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

    /** @var int|string */
    protected $userGuid;

    /** @var string[] */
    const TYPES = ['logo', 'background'];

    /**
     * @param string $type
     * @return Asset
     * @throws Exception
     */
    public function setType(string $type): Asset
    {
        if (!in_array($type, static::TYPES, true)) {
            throw new Exception('Invalid Asset type');
        }

        $this->type = $type;
        return $this;
    }

    /**
     * @return string
     * @throws Exception
     */
    public function getExt(): string
    {
        switch ($this->type) {
            case 'logo':
                return 'png';

            case 'background':
                return 'jpg';
        }

        throw new Exception('Invalid Asset');
    }

    /**
     * @return string
     * @throws Exception
     */
    public function getMimeType(): string
    {
        switch ($this->type) {
            case 'logo':
                return 'image/png';

            case 'background':
                return 'image/jpg';
        }

        throw new Exception('Invalid Asset');
    }

    /**
     * @return ElggFile
     * @throws Exception
     */
    public function getFile(): ElggFile
    {
        $file = new ElggFile();

        $file->owner_guid = $this->userGuid;
        $file->setFilename(sprintf("pro/%s.%s", $this->type, $this->getExt()));

        return $file;
    }
}
+129 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * Manager
 * @author edgebal
 */

namespace Minds\Core\Pro\Assets;

use ElggFile;
use Exception;
use Minds\Core\Di\Di;
use Minds\Core\Media\Imagick\Manager as ImageManager;
use Minds\Entities\User;
use Zend\Diactoros\UploadedFile;

class Manager
{
    /** @var ImageManager */
    protected $imageManager;

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

    /** @var User */
    protected $user;

    /** @var User */
    protected $actor;

    /**
     * Manager constructor.
     * @param ImageManager $imageManager
     */
    public function __construct(
        $imageManager = null
    ) {
        $this->imageManager = $imageManager ?: Di::_()->get('Media\Imagick\Manager');
    }

    /**
     * @param string $type
     * @return Manager
     */
    public function setType(string $type): Manager
    {
        $this->type = $type;
        return $this;
    }

    /**
     * @param User $user
     * @return Manager
     */
    public function setUser(User $user): Manager
    {
        $this->user = $user;
        return $this;
    }

    /**
     * @param User $actor
     * @return Manager
     */
    public function setActor(User $actor): Manager
    {
        $this->actor = $actor;
        return $this;
    }

    /**
     * @param UploadedFile $file
     * @param Asset|null $asset
     * @return bool
     * @throws Exception
     */
    public function set(UploadedFile $file, Asset $asset = null)
    {
        if (!$this->user) {
            throw new Exception('Invalid user');
        } elseif (!$this->type || !in_array($this->type, Asset::TYPES, true)) {
            throw new Exception('Invalid asset type');
        }

        // Load image

        $this->imageManager
            ->setImageFromBlob(
                $file->getStream()->getContents(),
                $file->getClientFilename()
            );

        // Setup asset

        if (!$asset) {
            $asset = new Asset();
        }

        $asset
            ->setType($this->type)
            ->setUserGuid($this->user->guid);

        // Handle asset type

        switch ($this->type) {
            case 'logo':
                $blob = $this->imageManager
                    ->resize(1920, 1080, false, false) // Max: 2K
                    ->getPng();
                break;

            case 'background':
                $blob = $this->imageManager
                    ->autorotate()
                    ->resize(3840, 2160, false, false) // Max: 4K
                    ->getJpeg(85);
                break;

            default:
                throw new Exception('Invalid asset type handler');
        }

        $file = $asset->getFile();
        $file->open('write');
        $file->write($blob);
        $file->close();

        return true;
    }
}
Loading