Completed
Pull Request — master (#54)
by Klochok
04:32
created

FileRender   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 14
dl 0
loc 165
ccs 0
cts 57
cp 0
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 9 2
A run() 0 5 1
A registerClientScript() 0 8 1
A renderHtml() 0 21 3
A getLink() 0 4 1
A getRoute() 0 8 2
A getExtIcon() 0 9 2
A addDownloadLinkButton() 0 41 1
1
<?php
2
/**
3
 * HiPanel core package.
4
 *
5
 * @link      https://hipanel.com/
6
 * @package   hipanel-core
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2014-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hipanel\widgets;
12
13
use hipanel\components\FileStorage;
14
use hipanel\helpers\ArrayHelper;
15
use hipanel\models\File;
16
use hipanel\widgets\filePreview\Dimensions;
17
use hipanel\widgets\filePreview\FilePreviewFactoryInterface;
18
use hipanel\widgets\filePreview\InsetDimensions;
19
use hipanel\widgets\filePreview\types\PdfPreviewGenerator;
20
use hipanel\widgets\filePreview\UnsupportedMimeTypeException;
21
use hiqdev\assets\lightbox2\LightboxAsset;
22
use Yii;
23
use yii\base\InvalidConfigException;
24
use yii\base\Widget;
25
use yii\helpers\Html;
26
use yii\helpers\Url;
27
28
/**
29
 * @property mixed iconOptions
30
 */
31
class FileRender extends Widget
32
{
33
    /**
34
     * @var File
35
     */
36
    public $file;
37
38
    /**
39
     * @var int
40
     */
41
    public $thumbWidth = 64;
42
43
    /**
44
     * @var int
45
     */
46
    public $thumbHeight = 64;
47
48
    /**
49
     * @var string Name of the file storage component
50
     */
51
    public $fileStorageComponent = 'fileStorage';
52
53
    /**
54
     * @var FileStorage
55
     */
56
    protected $fileStorage;
57
58
    /**
59
     * @var array Options that will be passed to [[Html::a()]] for the image lightbox
60
     */
61
    public $lightboxLinkOptions = [];
62
63
    public $imageOptions = [];
64
65
    public $iconOptions = [];
66
67
    /**
68
     * @var array
69
     */
70
    private $extMatch = [
71
        'pdf' => 'fa-file-pdf-o',
72
        'doc' => 'fa-file-word-o',
73
        'docx' => 'fa-file-word-o',
74
        'xls' => 'fa-file-excel-o',
75
        'xlsx' => 'fa-file-excel-o',
76
    ];
77
78
    public function init()
79
    {
80
        parent::init();
81
82
        if (!($this->file instanceof File)) {
83
            throw new InvalidConfigException('The "file" property must instance of File class.');
84
        }
85
        $this->fileStorage = Yii::$app->get($this->fileStorageComponent);
86
    }
87
88
    public function run()
89
    {
90
        $this->registerClientScript();
91
        return $this->renderHtml();
92
    }
93
94
    private function registerClientScript()
95
    {
96
        $view = $this->getView();
97
        LightboxAsset::register($view);
98
        // Fix: Incorrect resizing of image #122
99
        $view->registerCss('.lightbox  .lb-image { max-width: inherit!important; }');
100
        $this->addDownloadLinkButton();
101
    }
102
103
    private function renderHtml()
104
    {
105
        $file = $this->file;
106
        $path = $this->fileStorage->get($file);
107
108
        /** @var FilePreviewFactoryInterface $factory */
109
        $factory = Yii::createObject(FilePreviewFactoryInterface::class);
110
        try {
111
            $generator = $factory->createGenerator($path);
112
            $dimensions = new InsetDimensions($generator->getDimensions(), new Dimensions($this->thumbWidth, $this->thumbWidth));
113
            $src = 'data: ' . $generator->getContentType() . ';base64,' . base64_encode($generator->asBytes($dimensions));
114
            if ($generator instanceof PdfPreviewGenerator) {
115
                return Html::a(Html::img($src, $this->imageOptions), $this->getLink(), ['target' => '_blank']);
116
            } else {
117
                $linkOptions = ArrayHelper::merge(['data-lightbox' => 'file-' . $file->id], $this->lightboxLinkOptions);
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<hipanel\models\File>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
118
                return Html::a(Html::img($src, $this->imageOptions), $this->getLink(), $linkOptions);
119
            }
120
        } catch (UnsupportedMimeTypeException $e) {
121
            return Html::a($this->getExtIcon($file->type), $this->getLink(true));
122
        }
123
    }
124
125
    private function getLink($download = false)
126
    {
127
        return Url::to($this->getRoute($download));
0 ignored issues
show
Documentation introduced by
$download is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
128
    }
129
130
    /**
131
     * @param string $download whether to return route to download page
132
     *
133
     * @return array
134
     */
135
    public function getRoute($download)
136
    {
137
        if ($download) {
138
            return ['/file/get', 'id' => $this->file->id];
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<hipanel\models\File>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
139
        }
140
141
        return ['/file/view', 'id' => $this->file->id];
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<hipanel\models\File>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
142
    }
143
144
    private function getExtIcon($ext)
145
    {
146
        $defaultIcon = 'fa-file-text-o';
147
        $icon =  array_key_exists($ext, $this->extMatch) ? $this->extMatch[$ext] : $defaultIcon;
148
        $iconClasses = 'fa ' . $icon;
149
        Html::addCssClass($this->iconOptions, $iconClasses);
150
151
        return  Html::tag('i', null, $this->iconOptions);
152
    }
153
154
    private function addDownloadLinkButton()
155
    {
156
        $this->view->registerCss(<<<CSS
157
            .lb-data .lb-download-link, .lb-data .lb-download-link:hover {
158
                background: none;
159
                float: left;
160
                color: #d7d7d7;
161
                display: block;
162
                width: 30px;
163
                height: 30px;
164
                text-align: right;
165
                outline: none;
166
                filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
167
                opacity: 0.7;
168
                -webkit-transition: opacity 0.2s;
169
                -moz-transition: opacity 0.2s;
170
                -o-transition: opacity 0.2s;
171
                transition: opacity 0.2s;
172
            }
173
CSS
174
);
175
        $this->view->registerJs(<<<JS
176
        if ($('.lb-closeContainer').length) {
177
            $('.lb-closeContainer').append('<a class="lb-download-link"><i class="fa fa-cloud-download fa-2x" aria-hidden="true"></i></a>');
178
            $('.lb-download-link').on('click', function(e) {
179
                var win = window.open(e.currentTarget.attributes.href.value);
180
                win.focus();
181
            });
182
            var target = document.querySelector('.lb-image');
183
            var observer = new MutationObserver(function(mutations) {
184
                mutations.forEach(function(mutation) {
185
                    var src = mutation.target.attributes.src.value.replace('/file/', '/file/get/');
186
                    $('a.lb-download-link').attr({href: src});
187
                });
188
            });
189
            var config = { attributes: true, childList: false, characterData: true };
190
            observer.observe(target, config);
191
        }
192
JS
193
         );
194
    }
195
}
196