Completed
Push — master ( ab1d0f...fb8034 )
by Tomáš
14:22
created

AdminModule/presenters/FilesystemPresenter.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace AdminModule;
4
5
use Nette\Utils\Finder;
6
7
/**
8
 * Filesystem presenter.
9
 * @author Tomáš Voslař <tomas.voslar at webcook.cz>
10
 * @package WebCMS2
11
 */
12
class FilesystemPresenter extends \AdminModule\BasePresenter
13
{
14
    const DESTINATION_BASE = './upload/';
15
16
    private $path;
17
18
    /* @var \WebCMS\Helpers\ThumbnailCreator */
19
    private $thumbnailCreator;
20
21 6
    protected function beforeRender()
22
    {
23 6
        parent::beforeRender();
24 6
    }
25
26 10
    protected function startup()
27
    {
28 10
        parent::startup();
29
30 10
        $thumbnails = $this->em->getRepository('WebCMS\Entity\Thumbnail')->findAll();
31
32 10
        $this->thumbnailCreator = new \WebCMS\Helpers\ThumbnailCreator($this->settings, $thumbnails);
33 10
    }
34
35 7
    public function actionDefault($path)
36
    {
37 7
        if (!empty($path)) {
38 2
            $this->path = self::DESTINATION_BASE.$path.'/';
39 2
        } else {
40 5
            $this->path = self::DESTINATION_BASE;
41
        }
42 7
    }
43
44 6
    public function renderDefault($path, $dialog, $multiple)
45
    {
46 5
        $finder = new \Nette\Utils\Finder();
47
48 5
        $files = $finder->findFiles('*')
49 5
                ->exclude('.htaccess')
50 5
                ->in(realpath($this->path));
51 5
        $directories = $finder->findDirectories('*')->in(realpath($this->path));
52
53 5
        if (empty($dialog)) {
54 4
            $this->reloadContent();
55 4
        } else {
56 1
            $this->reloadModalContent();
57
        }
58
59 5
        $this->path = str_replace(self::DESTINATION_BASE, '', $path).'/';
60
61 6
        $this->template->fsPath = $this->path;
62 5
        $this->template->backLink = $this->createBackLink($this->path);
63 5
        $this->template->files = $files;
64 5
        $this->template->directories = $directories;
65 6
        $this->template->multiple = $multiple;
66 6
        $this->template->maxUploadFileSize = $this->getMaxUploadFileSize();
0 ignored issues
show
The property $template is declared private in Nette\Application\UI\Control. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
Accessing maxUploadFileSize on the interface Nette\Templating\ITemplate suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
67 5
    }
68
69
        /**
70
         * @param string $path
71
         */
72 6
        private function createBackLink($path)
73 1
        {
74 6
            $exploded = explode('/', $path);
75
76 6
            array_pop($exploded);
77 6
            array_pop($exploded);
78
79 6
            return implode("/", $exploded);
80 6
        }
81
82 6
    public function handleMakeDirectory($name)
83 6
    {
84 6
        @mkdir($this->path.\Nette\Utils\Strings::webalize($name));
85
86 6
        $this->flashMessage('Directory has been created.', 'success');
87 1
    }
88
89 1
    public function handleUploadFile($path)
90
    {
91 1
        $files = $this->getRequest()->getFiles();
92 1
        $files = $files['file'];
93
94 1
        foreach ($files as $file) {
95 1
            $this->uploadSingleFile($file);
96 1
        }
97
98 1
        $this->reloadContent();
99 1
        $this->flashMessage($this->translation['File has been uploaded']);
100 1
        $this->sendPayload();
101
    }
102
103 1
    private function uploadSingleFile($file)
104
    {
105 1
        $filePath = $this->path.''.$file->getSanitizedName();
106 1
        $file->move($filePath);
107
108 1
        $f = new \SplFileInfo($filePath);
109
110 1
        if ($file->isImage()) {
111 1
            $this->thumbnailCreator->createThumbnails($f->getBasename(), str_replace($f->getBasename(), '', $filePath));
112 1
        }
113 1
    }
114
115 1
    public function handleDeleteFile($pathToRemove)
116
    {
117 1
        $pathToRemove = self::DESTINATION_BASE.$pathToRemove;
118 1
        if (is_file($pathToRemove)) {
119
            // delete all thumbnails if this file is image
120
            try {
121 1
                if (getimagesize($pathToRemove)) {
122 1
                    $image = \Nette\Image::fromFile($pathToRemove);
123
124 1
                    $thumbs = $this->em->getRepository('WebCMS\Entity\Thumbnail')->findAll();
125 1
                    foreach ($thumbs as $t) {
126 1
                        $file = pathinfo($pathToRemove);
127 1
                        $filename = $file['filename'].'.'.$file['extension'];
128
129
                // $this->path contains symlinked path, that is not the right way @see handleRegenerateThumbnails() function for the fix
130 1
                $toRemove = str_replace('upload', 'thumbnails', $pathToRemove);
131 1
                        $toRemove = str_replace($filename, $t->getKey().$filename, $toRemove);
132
133 1
                        unlink($toRemove);
134 1
                    }
135 1
                }
136 1
            } catch (UnknownImageFileException $exc) {
137
                // image is not file, so there is nothing to do
138
            }
139
140 1
            unlink($pathToRemove);
141 1
        }
142
143 1
        if (is_dir($pathToRemove)) {
144
            \WebCMS\Helpers\SystemHelper::rrmdir($pathToRemove);
145
            \WebCMS\Helpers\SystemHelper::rrmdir(str_replace('upload', 'thumbnails', $pathToRemove));
146
        }
147
148 1
        $this->flashMessage('File has been removed.', 'success');
149
150 1
        $this->forward('this');
151
    }
152
153 1
    public function actionDownloadFile($path)
154
    {
155 1
        $file = pathinfo($path);
156 1
        $filename = $file['filename'].'.'.$file['extension'];
157
158 1
        $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
159
160 1
        $path = self::DESTINATION_BASE.$path;
161 1
        $mimeType = finfo_file($finfo, $path);
162
163 1
        $this->sendResponse(new \Nette\Application\Responses\FileResponse($path, $filename, $mimeType));
164
    }
165
166 2
    public function actionFilesDialog($path)
167
    {
168 2
        if (!empty($path)) {
169
            $this->path = $path.'/';
170
        } else {
171 2
            $this->path = realpath(self::DESTINATION_BASE).'/';
172
        }
173 2
    }
174
175 1
    public function renderFilesDialog()
176
    {
177 1
        $finder = new \Nette\Utils\Finder();
178
179 1
        $template = $this->createTemplate();
180 1
        $template->setFile($this->template->basePathModule.'AdminModule/templates/Filesystem/filesDialog.latte');
181
182 1
        $template->files = $finder->findFiles('*')->in($this->path);
183 1
        $template->directories = $finder->findDirectories('*')->in($this->path);
184 1
        $template->setTranslator($this->translator);
185 1
        $template->registerHelperLoader('\WebCMS\Helpers\SystemHelper::loader');
186 1
        $template->backLink = strpos($this->createBackLink($this->path), self::DESTINATION_BASE) === false ? realpath(self::DESTINATION_BASE) : $this->createBackLink($this->path);
187
188 1
        $template->render();
189
190 1
        $this->terminate();
191
    }
192
193 1
    public function handleRegenerateThumbnails()
194
    {
195 1
        set_time_limit(0);
196
197 1
        \WebCMS\Helpers\SystemHelper::rrmdir('thumbnails', true);
198
199 1
        $timeStart = time();
200
201 1
        foreach (Finder::findFiles('*.jpg', '*.jpeg', '*.png', '*.gif')->from('upload') as $key => $file) {
202 1
            if (file_exists($key) && @getimagesize($key)) {
203 1
                $this->thumbnailCreator->createThumbnails($file->getBasename(), str_replace($file->getBasename(), '', $key));
204 1
            }
205 1
        }
206
207 1
        $timeOver = time();
208
209 1
        $seconds = $timeOver - $timeStart;
210
211 1
        $hours = floor($seconds / 3600);
212 1
        $mins = floor(($seconds - ($hours * 3600)) / 60);
213 1
        $secs = floor($seconds % 60);
214
        // TODO log spent time
215 1
        $this->flashMessage('Thumbnails has been regenerated by recent settings.', 'success');
216 1
        $this->forward('default');
217
    }
218
219
    /**
220
     * Get the maximal file upload size from the environment variables.
221
     *
222
     * @author Taken from the Drupal.org project
223
     * @license GPL 2
224
     * @return int
225
     */
226 5
    public function getMaxUploadFileSize()
227
    {
228 5
        static $max_size = -1;
229
230 5
        if ($max_size < 0) {
231
            // Start with post_max_size.
232 1
            $max_size = $this->parseFileSize(ini_get('post_max_size'));
233
234
            // If upload_max_size is less, then reduce. Except if upload_max_size is
235
            // zero, which indicates no limit.
236 1
            $upload_max = $this->parseFileSize(ini_get('upload_max_filesize'));
237
238 1
            if ($upload_max > 0 && $upload_max < $max_size) {
239 1
                $max_size = $upload_max;
240 1
            }
241 1
        }
242 5
        return $max_size;
243
    }
244
245
    /**
246
     * Parse file size.
247
     *
248
     * @author Taken from the Drupal.org project
249
     * @license GPL 2
250
     * @return int
251
     */
252 1
    public function parseFileSize($size)
253
    {
254 1
        $unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size.
255 1
        $size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size.
256 1
        if ($unit) {
257
            // Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
258 1
            return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
259
        } else {
260
            return round($size);
261
        }
262
    }
263
264
}
265