| Total Complexity | 40 |
| Total Lines | 336 |
| Duplicated Lines | 0 % |
| Changes | 1 | ||
| Bugs | 0 | Features | 0 |
Complex classes like MediaFileService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use MediaFileService, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 61 | class MediaFileService |
||
| 62 | { |
||
| 63 | public const EDIT_RESTRICTIONS = [ |
||
| 64 | 'locked', |
||
| 65 | ]; |
||
| 66 | |||
| 67 | public const PRIVACY_RESTRICTIONS = [ |
||
| 68 | 'none', |
||
| 69 | 'privacy', |
||
| 70 | 'confidential', |
||
| 71 | ]; |
||
| 72 | |||
| 73 | public const EXTENSION_TO_FORM = [ |
||
| 74 | 'jpg' => 'jpeg', |
||
| 75 | 'tif' => 'tiff', |
||
| 76 | ]; |
||
| 77 | |||
| 78 | /** |
||
| 79 | * What is the largest file a user may upload? |
||
| 80 | */ |
||
| 81 | public function maxUploadFilesize(): string |
||
| 90 | } |
||
| 91 | |||
| 92 | /** |
||
| 93 | * Returns the given size from an ini value in bytes. |
||
| 94 | * |
||
| 95 | * @param string $size |
||
| 96 | * |
||
| 97 | * @return int |
||
| 98 | */ |
||
| 99 | private function parseIniFileSize(string $size): int |
||
| 100 | { |
||
| 101 | $number = (int) $size; |
||
| 102 | |||
| 103 | switch (substr($size, -1)) { |
||
| 104 | case 'g': |
||
| 105 | case 'G': |
||
| 106 | return $number * 1073741824; |
||
| 107 | case 'm': |
||
| 108 | case 'M': |
||
| 109 | return $number * 1048576; |
||
| 110 | case 'k': |
||
| 111 | case 'K': |
||
| 112 | return $number * 1024; |
||
| 113 | default: |
||
| 114 | return $number; |
||
| 115 | } |
||
| 116 | } |
||
| 117 | |||
| 118 | /** |
||
| 119 | * A list of key/value options for media types. |
||
| 120 | * |
||
| 121 | * @param string $current |
||
| 122 | * |
||
| 123 | * @return array<string,string> |
||
| 124 | */ |
||
| 125 | public function mediaTypes($current = ''): array |
||
| 132 | } |
||
| 133 | |||
| 134 | /** |
||
| 135 | * A list of media files not already linked to a media object. |
||
| 136 | * |
||
| 137 | * @param Tree $tree |
||
| 138 | * @param FilesystemInterface $data_filesystem |
||
| 139 | * |
||
| 140 | * @return array<string> |
||
| 141 | */ |
||
| 142 | public function unusedFiles(Tree $tree, FilesystemInterface $data_filesystem): array |
||
| 170 | } |
||
| 171 | |||
| 172 | /** |
||
| 173 | * Store an uploaded file (or URL), either to be added to a media object |
||
| 174 | * or to create a media object. |
||
| 175 | * |
||
| 176 | * @param ServerRequestInterface $request |
||
| 177 | * |
||
| 178 | * @return string The value to be stored in the 'FILE' field of the media object. |
||
| 179 | */ |
||
| 180 | public function uploadFile(ServerRequestInterface $request): string |
||
| 181 | { |
||
| 182 | $tree = $request->getAttribute('tree'); |
||
| 183 | assert($tree instanceof Tree); |
||
| 184 | |||
| 185 | $data_filesystem = Factory::filesystem()->data(); |
||
| 186 | |||
| 187 | $params = (array) $request->getParsedBody(); |
||
| 188 | $file_location = $params['file_location']; |
||
| 189 | |||
| 190 | switch ($file_location) { |
||
| 191 | case 'url': |
||
| 192 | $remote = $params['remote']; |
||
| 193 | |||
| 194 | if (str_contains($remote, '://')) { |
||
| 195 | return $remote; |
||
| 196 | } |
||
| 197 | |||
| 198 | return ''; |
||
| 199 | |||
| 200 | case 'unused': |
||
| 201 | $unused = $params['unused']; |
||
| 202 | |||
| 203 | if ($tree->mediaFilesystem($data_filesystem)->has($unused)) { |
||
| 204 | return $unused; |
||
| 205 | } |
||
| 206 | |||
| 207 | return ''; |
||
| 208 | |||
| 209 | case 'upload': |
||
| 210 | default: |
||
| 211 | $folder = $params['folder']; |
||
| 212 | $auto = $params['auto']; |
||
| 213 | $new_file = $params['new_file']; |
||
| 214 | |||
| 215 | /** @var UploadedFileInterface|null $uploaded_file */ |
||
| 216 | $uploaded_file = $request->getUploadedFiles()['file']; |
||
| 217 | if ($uploaded_file === null || $uploaded_file->getError() !== UPLOAD_ERR_OK) { |
||
| 218 | return ''; |
||
| 219 | } |
||
| 220 | |||
| 221 | // The filename |
||
| 222 | $new_file = strtr($new_file, ['\\' => '/']); |
||
| 223 | if ($new_file !== '' && !str_contains($new_file, '/')) { |
||
| 224 | $file = $new_file; |
||
| 225 | } else { |
||
| 226 | $file = $uploaded_file->getClientFilename(); |
||
| 227 | } |
||
| 228 | |||
| 229 | // The folder |
||
| 230 | $folder = strtr($folder, ['\\' => '/']); |
||
| 231 | $folder = trim($folder, '/'); |
||
| 232 | if ($folder !== '') { |
||
| 233 | $folder .= '/'; |
||
| 234 | } |
||
| 235 | |||
| 236 | // Generate a unique name for the file? |
||
| 237 | if ($auto === '1' || $tree->mediaFilesystem($data_filesystem)->has($folder . $file)) { |
||
| 238 | $folder = ''; |
||
| 239 | $extension = pathinfo($uploaded_file->getClientFilename(), PATHINFO_EXTENSION); |
||
| 240 | $file = sha1((string) $uploaded_file->getStream()) . '.' . $extension; |
||
| 241 | } |
||
| 242 | |||
| 243 | try { |
||
| 244 | $tree->mediaFilesystem($data_filesystem)->putStream($folder . $file, $uploaded_file->getStream()->detach()); |
||
| 245 | |||
| 246 | return $folder . $file; |
||
| 247 | } catch (RuntimeException | InvalidArgumentException $ex) { |
||
| 248 | FlashMessages::addMessage(I18N::translate('There was an error uploading your file.')); |
||
| 249 | |||
| 250 | return ''; |
||
| 251 | } |
||
| 252 | } |
||
| 253 | } |
||
| 254 | |||
| 255 | /** |
||
| 256 | * Convert the media file attributes into GEDCOM format. |
||
| 257 | * |
||
| 258 | * @param string $file |
||
| 259 | * @param string $type |
||
| 260 | * @param string $title |
||
| 261 | * @param string $note |
||
| 262 | * |
||
| 263 | * @return string |
||
| 264 | */ |
||
| 265 | public function createMediaFileGedcom(string $file, string $type, string $title, string $note): string |
||
| 266 | { |
||
| 267 | // Tidy non-printing characters |
||
| 268 | $type = trim(preg_replace('/\s+/', ' ', $type)); |
||
| 269 | $title = trim(preg_replace('/\s+/', ' ', $title)); |
||
| 270 | |||
| 271 | $gedcom = '1 FILE ' . $file; |
||
| 272 | |||
| 273 | $format = strtolower(pathinfo($file, PATHINFO_EXTENSION)); |
||
| 274 | $format = self::EXTENSION_TO_FORM[$format] ?? $format; |
||
| 275 | |||
| 276 | if ($format !== '') { |
||
| 277 | $gedcom .= "\n2 FORM " . $format; |
||
| 278 | } elseif ($type !== '') { |
||
| 279 | $gedcom .= "\n2 FORM"; |
||
| 280 | } |
||
| 281 | |||
| 282 | if ($type !== '') { |
||
| 283 | $gedcom .= "\n3 TYPE " . $type; |
||
| 284 | } |
||
| 285 | |||
| 286 | if ($title !== '') { |
||
| 287 | $gedcom .= "\n2 TITL " . $title; |
||
| 288 | } |
||
| 289 | |||
| 290 | if ($note !== '') { |
||
| 291 | // Convert HTML line endings to GEDCOM continuations |
||
| 292 | $gedcom .= "\n1 NOTE " . strtr($note, ["\r\n" => "\n2 CONT "]); |
||
| 293 | } |
||
| 294 | |||
| 295 | return $gedcom; |
||
| 296 | } |
||
| 297 | |||
| 298 | /** |
||
| 299 | * Fetch a list of all files on disk (in folders used by any tree). |
||
| 300 | * |
||
| 301 | * @param FilesystemInterface $data_filesystem Fileystem to search |
||
| 302 | * @param string $media_folder Root folder |
||
| 303 | * @param bool $subfolders Include subfolders |
||
| 304 | * |
||
| 305 | * @return Collection<string> |
||
| 306 | */ |
||
| 307 | public function allFilesOnDisk(FilesystemInterface $data_filesystem, string $media_folder, bool $subfolders): Collection |
||
| 308 | { |
||
| 309 | $array = $data_filesystem->listContents($media_folder, $subfolders); |
||
| 310 | |||
| 311 | return Collection::make($array) |
||
| 312 | ->filter(static function (array $metadata): bool { |
||
| 313 | return |
||
| 314 | $metadata['type'] === 'file' && |
||
| 315 | !str_contains($metadata['path'], '/thumbs/') && |
||
| 316 | !str_contains($metadata['path'], '/watermark/'); |
||
| 317 | }) |
||
| 318 | ->map(static function (array $metadata): string { |
||
| 319 | return $metadata['path']; |
||
| 320 | }); |
||
| 321 | } |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Fetch a list of all files on in the database. |
||
| 325 | * |
||
| 326 | * @param string $media_folder Root folder |
||
| 327 | * @param bool $subfolders Include subfolders |
||
| 328 | * |
||
| 329 | * @return Collection<string> |
||
| 330 | */ |
||
| 331 | public function allFilesInDatabase(string $media_folder, bool $subfolders): Collection |
||
| 348 | } |
||
| 349 | |||
| 350 | /** |
||
| 351 | * Generate a list of all folders in either the database or the filesystem. |
||
| 352 | * |
||
| 353 | * @param FilesystemInterface $data_filesystem |
||
| 354 | * |
||
| 355 | * @return Collection<string,string> |
||
| 356 | */ |
||
| 357 | public function allMediaFolders(FilesystemInterface $data_filesystem): Collection |
||
| 397 | }); |
||
| 398 | } |
||
| 400 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.