Complex classes like Media 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 Media, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 24 | class Media extends Model implements Responsable, Htmlable |
||
| 25 | { |
||
| 26 | use IsSorted, |
||
| 27 | CustomMediaProperties; |
||
| 28 | |||
| 29 | const TYPE_OTHER = 'other'; |
||
| 30 | |||
| 31 | protected $guarded = []; |
||
| 32 | |||
| 33 | protected $casts = [ |
||
| 34 | 'manipulations' => 'array', |
||
| 35 | 'custom_properties' => 'array', |
||
| 36 | 'responsive_images' => 'array', |
||
| 37 | ]; |
||
| 38 | |||
| 39 | public function model(): MorphTo |
||
| 43 | |||
| 44 | /* |
||
| 45 | * Get the full url to a original media file. |
||
| 46 | */ |
||
| 47 | public function getFullUrl(string $conversionName = ''): string |
||
| 51 | |||
| 52 | /* |
||
| 53 | * Get the url to a original media file. |
||
| 54 | */ |
||
| 55 | public function getUrl(string $conversionName = ''): string |
||
| 61 | |||
| 62 | public function getTemporaryUrl(DateTimeInterface $expiration, string $conversionName = '', array $options = []): string |
||
| 68 | |||
| 69 | /* |
||
| 70 | * Get the path to the original media file. |
||
| 71 | */ |
||
| 72 | public function getPath(string $conversionName = ''): string |
||
| 78 | |||
| 79 | public function getImageGenerators(): Collection |
||
| 83 | |||
| 84 | public function getTypeAttribute(): string |
||
| 94 | |||
| 95 | public function getTypeFromExtension(): string |
||
| 107 | |||
| 108 | public function getTypeFromMime(): string |
||
| 120 | |||
| 121 | public function getExtensionAttribute(): string |
||
| 125 | |||
| 126 | public function getHumanReadableSizeAttribute(): string |
||
| 130 | |||
| 131 | public function getDiskDriverName(): string |
||
| 135 | |||
| 136 | /* |
||
| 137 | * Determine if the media item has a custom property with the given name. |
||
| 138 | */ |
||
| 139 | public function hasCustomProperty(string $propertyName): bool |
||
| 143 | |||
| 144 | /** |
||
| 145 | * Get the value of custom property with the given name. |
||
| 146 | * |
||
| 147 | * @param string $propertyName |
||
| 148 | * @param mixed $default |
||
| 149 | * |
||
| 150 | * @return mixed |
||
| 151 | */ |
||
| 152 | public function getCustomProperty(string $propertyName, $default = null) |
||
| 156 | |||
| 157 | /** |
||
| 158 | * @param string $name |
||
| 159 | * @param mixed $value |
||
| 160 | * |
||
| 161 | * @return $this |
||
| 162 | */ |
||
| 163 | public function setCustomProperty(string $name, $value): self |
||
| 173 | |||
| 174 | public function forgetCustomProperty(string $name): self |
||
| 184 | |||
| 185 | /* |
||
| 186 | * Get all the names of the registered media conversions. |
||
| 187 | */ |
||
| 188 | public function getMediaConversionNames(): array |
||
| 196 | |||
| 197 | public function hasGeneratedConversion(string $conversionName): bool |
||
| 203 | |||
| 204 | public function markAsConversionGenerated(string $conversionName, bool $generated): self |
||
| 205 | { |
||
| 206 | $this->setCustomProperty("generated_conversions.{$conversionName}", $generated); |
||
| 207 | |||
| 208 | return $this; |
||
| 209 | } |
||
| 210 | |||
| 211 | public function getGeneratedConversions(): Collection |
||
| 215 | |||
| 216 | /** |
||
| 217 | * Create an HTTP response that represents the object. |
||
| 218 | * |
||
| 219 | * @param \Illuminate\Http\Request $request |
||
| 220 | * |
||
| 221 | * @return \Illuminate\Http\Response |
||
| 222 | */ |
||
| 223 | public function toResponse($request) |
||
| 243 | |||
| 244 | public function getResponsiveImageUrls(string $conversionName = ''): array |
||
| 248 | |||
| 249 | public function hasResponsiveImages(string $conversionName = ''): bool |
||
| 253 | |||
| 254 | public function getSrcset(string $conversionName = ''): string |
||
| 258 | |||
| 259 | public function toHtml() |
||
| 263 | |||
| 264 | /** |
||
| 265 | * @param string|array $conversion |
||
| 266 | * @param array $extraAttributes |
||
| 267 | * |
||
| 268 | * @return string |
||
| 269 | */ |
||
| 270 | public function img($conversion = '', array $extraAttributes = []): string |
||
| 316 | |||
| 317 | public function move(HasMedia $model, $collectionName = 'default'): self |
||
| 325 | |||
| 326 | public function copy(HasMedia $model, $collectionName = 'default'): self |
||
| 345 | |||
| 346 | public function responsiveImages(string $conversionName = ''): RegisteredResponsiveImages |
||
| 350 | |||
| 351 | public function stream() |
||
| 357 | |||
| 358 | public function __invoke(...$arguments) |
||
| 362 | } |
||
| 363 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.