FocusCropService   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 287
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 12
dl 0
loc 287
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getViewHelperImage() 0 19 5
A getCroppedImageSrcForViewHelper() 0 6 1
A getCroppedImageSrcByFileReference() 0 10 3
A getCroppedImageSrcByFile() 0 14 2
A emitTempImageCropped() 0 4 1
A getSignalSlotDispatcher() 0 8 2
A getObjectManager() 0 4 1
B getCroppedImageSrcBySrc() 0 71 7
A generateTempImageName() 0 29 3
A getTempImageFolder() 0 13 3
1
<?php
2
3
/**
4
 * Crop images via focus crop.
5
 */
6
7
namespace HDNET\Focuspoint\Service;
8
9
use HDNET\Focuspoint\Domain\Repository\FileStandaloneRepository;
10
use TYPO3\CMS\Core\Resource\FileInterface;
11
use TYPO3\CMS\Core\Resource\FileReference as CoreFileReference;
12
use TYPO3\CMS\Core\Resource\ResourceFactory;
13
use TYPO3\CMS\Core\Utility\GeneralUtility;
14
use TYPO3\CMS\Core\Utility\MathUtility;
15
use TYPO3\CMS\Core\Utility\PathUtility;
16
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
17
use TYPO3\CMS\Extbase\Object\ObjectManager;
18
use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
19
20
/**
21
 * Crop images via focus crop.
22
 */
23
class FocusCropService extends AbstractService
24
{
25
    const SIGNAL_tempImageCropped = 'tempImageCropped';
26
27
    /**
28
     * @var Dispatcher
29
     */
30
    protected $signalSlotDispatcher;
31
32
    /**
33
     * @var string
34
     */
35
    protected $tempImageFolder;
36
37
    /**
38
     * get the image.
39
     *
40
     * @param $src
41
     * @param $image
42
     * @param $treatIdAsReference
43
     *
44
     * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
45
     * @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
46
     *
47
     * @return \TYPO3\CMS\Core\Resource\File|FileInterface|CoreFileReference|\TYPO3\CMS\Core\Resource\Folder
48
     */
49
    public function getViewHelperImage($src, $image, $treatIdAsReference)
50
    {
51
        $resourceFactory = ResourceFactory::getInstance();
52
        if ($image instanceof \TYPO3\CMS\Core\Resource\FileReference) {
53
            return $image;
54
        }
55
        if ($image instanceof FileReference) {
56
            return $image->getOriginalResource();
57
        }
58
        if (!MathUtility::canBeInterpretedAsInteger($src)) {
59
            return $resourceFactory->retrieveFileOrFolderObject($src);
60
        }
61
        if (!$treatIdAsReference) {
62
            return $resourceFactory->getFileObject($src);
63
        }
64
        $image = $resourceFactory->getFileReferenceObject($src);
65
66
        return $image;
67
    }
68
69
    /**
70
     * Helper function for view helpers.
71
     *
72
     * @param $src
73
     * @param $image
74
     * @param $treatIdAsReference
75
     * @param $ratio
76
     *
77
     * @throws \TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
78
     * @throws \TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
79
     *
80
     * @return string
81
     */
82
    public function getCroppedImageSrcForViewHelper($src, $image, $treatIdAsReference, string $ratio)
83
    {
84
        $file = $this->getViewHelperImage($src, $image, $treatIdAsReference);
85
86
        return $this->getCroppedImageSrcByFile($file, $ratio);
0 ignored issues
show
Bug introduced by
It seems like $file defined by $this->getViewHelperImag...e, $treatIdAsReference) on line 84 can also be of type object<TYPO3\CMS\Core\Resource\Folder>; however, HDNET\Focuspoint\Service...CroppedImageSrcByFile() does only seem to accept object<TYPO3\CMS\Core\Resource\FileInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
87
    }
88
89
    /**
90
     * Get the cropped image.
91
     *
92
     * @param string $fileReference
93
     * @param string $ratio
94
     *
95
     * @return string The new filename
96
     */
97
    public function getCroppedImageSrcByFileReference($fileReference, string $ratio)
98
    {
99
        if ($fileReference instanceof FileReference) {
100
            $fileReference = $fileReference->getOriginalResource();
101
        }
102
        if ($fileReference instanceof CoreFileReference) {
103
            return $this->getCroppedImageSrcByFile($fileReference->getOriginalFile(), $ratio);
104
        }
105
        throw new \InvalidArgumentException('The given argument is not a valid file reference', 1475144027);
106
    }
107
108
    /**
109
     * Get the cropped image by File Object.
110
     *
111
     * @param FileInterface $file
112
     * @param string        $ratio
113
     *
114
     * @return string The new filename
115
     */
116
    public function getCroppedImageSrcByFile(FileInterface $file, string $ratio)
117
    {
118
        $result = $this->getCroppedImageSrcBySrc(
119
            $file->getForLocalProcessing(false),
120
            $ratio,
121
            $file->getProperty('focus_point_x'),
122
            $file->getProperty('focus_point_y')
123
        );
124
        if ('' === $result) {
125
            return $file->getPublicUrl();
126
        }
127
128
        return $result;
129
    }
130
131
    /**
132
     * Get the cropped image by src.
133
     *
134
     * @param string $src   Relative file name
135
     * @param string $ratio
136
     * @param int    $x
137
     * @param int    $y
138
     *
139
     * @return string The new filename
140
     */
141
    public function getCroppedImageSrcBySrc(string $src, string $ratio, int $x, int $y): string
142
    {
143
        $absoluteImageName = GeneralUtility::getFileAbsFileName($src);
144
        if (!\is_file($absoluteImageName)) {
145
            return '';
146
        }
147
148
        /** @var \TYPO3\CMS\Core\Http\NormalizedParams $params */
149
        $params = $GLOBALS['TYPO3_REQUEST']->getAttribute('normalizedParams');
150
        $docRoot = \rtrim($params->getDocumentRoot(), '/') . '/';
151
        $relativeSrc = \str_replace($docRoot, '', $absoluteImageName);
152
        $focusPointX = MathUtility::forceIntegerInRange((int) $x, -100, 100, 0);
153
        $focusPointY = MathUtility::forceIntegerInRange((int) $y, -100, 100, 0);
154
155
        if (0 === $focusPointX && 0 === $focusPointY) {
156
            $row = GeneralUtility::makeInstance(FileStandaloneRepository::class)->findOneByRelativeFilePath($relativeSrc);
157
            if (isset($row['focus_point_x'])) {
158
                $focusPointX = MathUtility::forceIntegerInRange((int) $row['focus_point_x'], -100, 100, 0);
159
                $focusPointY = MathUtility::forceIntegerInRange((int) $row['focus_point_y'], -100, 100, 0);
160
            }
161
        }
162
163
        $tempImageFolder = $this->getTempImageFolder();
164
        $tempImageName = $this->generateTempImageName($absoluteImageName, $ratio, $focusPointX, $focusPointY);
165
        $tempImageName = $tempImageFolder . $tempImageName;
166
167
        $absoluteTempImageName = GeneralUtility::getFileAbsFileName($tempImageName);
168
169
        if (\is_file($absoluteTempImageName)) {
170
            return $tempImageName;
171
        }
172
173
        $absoluteTempImageFolder = GeneralUtility::getFileAbsFileName($tempImageFolder);
174
        if (!\is_dir($absoluteTempImageFolder)) {
175
            GeneralUtility::mkdir_deep($absoluteTempImageFolder);
176
        }
177
178
        $imageSizeInformation = \getimagesize($absoluteImageName);
179
        $width = $imageSizeInformation[0];
180
        $height = $imageSizeInformation[1];
181
182
        // dimensions
183
        /** @var DimensionService $dimensionService */
184
        $dimensionService = GeneralUtility::makeInstance(DimensionService::class);
185
        list($focusWidth, $focusHeight) = $dimensionService->getFocusWidthAndHeight($width, $height, $ratio);
186
187
        $cropMode = $dimensionService->getCropMode($width, $height, $ratio);
188
        list($sourceX, $sourceY) = $dimensionService->calculateSourcePosition(
189
            $cropMode,
190
            $width,
191
            $height,
192
            $focusWidth,
193
            $focusHeight,
194
            $focusPointX,
195
            $focusPointY
196
        );
197
198
        $cropService = GeneralUtility::makeInstance(CropService::class);
199
        $cropService->createImage(
200
            $absoluteImageName,
201
            $focusWidth,
202
            $focusHeight,
203
            $sourceX,
204
            $sourceY,
205
            $absoluteTempImageName
206
        );
207
208
        $this->emitTempImageCropped($tempImageName);
209
210
        return $tempImageName;
211
    }
212
213
    /**
214
     * Emit tempImageCropped signal.
215
     *
216
     * @param string $tempImageName
217
     *
218
     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
219
     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException
220
     */
221
    protected function emitTempImageCropped(string $tempImageName)
222
    {
223
        $this->getSignalSlotDispatcher()->dispatch(__CLASS__, self::SIGNAL_tempImageCropped, [$tempImageName]);
224
    }
225
226
    /**
227
     * Get the SignalSlot dispatcher.
228
     *
229
     * @return Dispatcher
230
     */
231
    protected function getSignalSlotDispatcher()
232
    {
233
        if (!isset($this->signalSlotDispatcher)) {
234
            $this->signalSlotDispatcher = $this->getObjectManager()->get(Dispatcher::class);
235
        }
236
237
        return $this->signalSlotDispatcher;
238
    }
239
240
    /**
241
     * Gets the ObjectManager.
242
     *
243
     * @return ObjectManager
244
     */
245
    protected function getObjectManager()
246
    {
247
        return GeneralUtility::makeInstance(ObjectManager::class);
248
    }
249
250
    /**
251
     * @param string $absoluteImageName
252
     * @param string $ratio
253
     * @param int    $focusPointX
254
     * @param int    $focusPointY
255
     *
256
     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
257
     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException
258
     *
259
     * @return string
260
     */
261
    protected function generateTempImageName(string $absoluteImageName, string $ratio, int $focusPointX, int $focusPointY): string
262
    {
263
        $name = '';
264
265
        list($name) = $this->getSignalSlotDispatcher()->dispatch(__CLASS__, __FUNCTION__, [
266
            $name,
267
            $absoluteImageName,
268
            $ratio,
269
            $focusPointX,
270
            $focusPointY,
271
        ]);
272
273
        if ($name) {
274
            return $name;
275
        }
276
277
        $hash = \function_exists('sha1_file') ? \sha1_file($absoluteImageName) : \md5_file($absoluteImageName);
278
        $name = $hash . '-fp-' . \preg_replace(
279
            '/[^0-9a-z-]/',
280
            '-',
281
            $ratio
282
        ) . '-' . $focusPointX . '-' . $focusPointY . '.' . PathUtility::pathinfo(
283
            $absoluteImageName,
284
            PATHINFO_EXTENSION
285
        );
286
        $name = \preg_replace('/--+/', '-', $name);
287
288
        return $name;
289
    }
290
291
    /**
292
     * Return the folder for generated images.
293
     *
294
     * @return string Path relative to PATH_site
295
     */
296
    protected function getTempImageFolder(): string
297
    {
298
        if (null === $this->tempImageFolder) {
299
            $extConf = \unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['focuspoint']);
300
            if (isset($extConf['tempImageFolder'])) {
301
                $this->tempImageFolder = $extConf['tempImageFolder'];
302
            } else {
303
                $this->tempImageFolder = 'typo3temp/focuscrop/';
304
            }
305
        }
306
307
        return $this->tempImageFolder;
308
    }
309
}
310