Utils.pm 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package Trog::Utils;
  2. use 5.040;
  3. use re '/aasx';
  4. use warnings FATAL => 'all';
  5. use UUID;
  6. use Plack::MIME;
  7. use Mojo::File;
  8. use File::LibMagic;
  9. use Ref::Util qw{is_hashref};
  10. =head1 Trog::Utils
  11. Odds and ends which are needed in more than one place and belong to no
  12. particular subsystem.
  13. =head1 FUNCTIONS
  14. =head2 coerce_array(SCALAR|ARRAYREF param) = ARRAYREF
  15. Deal with Params which may or may not be arrays.
  16. Query parameters arrive as a bare scalar when the caller passed one of
  17. something and as an arrayref when they passed several, which means every
  18. consumer would otherwise have to check. Returns an empty arrayref for anything
  19. false, so the result is always safe to dereference.
  20. =cut
  21. sub coerce_array ($param) {
  22. my $p = $param || [];
  23. $p = [$param] if $param && ( ref $param ne 'ARRAY' );
  24. return $p;
  25. }
  26. =head2 strip_and_trunc(STRING s) = STRING
  27. Flatten a chunk of post body into something fit for a meta description or
  28. preview blurb -- tags stripped, truncated to 280 characters.
  29. Returns undef when handed nothing, rather than an empty string.
  30. =cut
  31. sub strip_and_trunc ($s) {
  32. return unless $s;
  33. $s =~ s/<[^>]*>//g;
  34. return substr $s, 0, 280;
  35. }
  36. =head2 uuid() = STRING
  37. A fresh UUID. Thin wrapper around UUID::uuid(), so that callers don't have to
  38. care which of the several UUID modules we ended up using.
  39. =cut
  40. sub uuid {
  41. return UUID::uuid();
  42. }
  43. #Stuff that isn't in upstream finders
  44. my %extra_types = (
  45. '.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  46. );
  47. =head2 mime_type(STRING file) = STRING
  48. Figure out a file's Content-Type.
  49. Tries the extension first, as that's cheap and right nearly all of the time,
  50. and only falls back to libmagic sniffing the file's contents when the extension
  51. tells us nothing. %extra_types patches in the handful of types the upstream
  52. finders don't know about.
  53. Returns undef if even libmagic can't say.
  54. =cut
  55. sub mime_type ($file) {
  56. # Use libmagic and if that doesn't work try guessing based on extension.
  57. my $mt;
  58. my $mf = Mojo::File->new($file);
  59. my $ext = '.' . $mf->extname();
  60. $mt = Plack::MIME->mime_type($ext) if $ext;
  61. $mt ||= $extra_types{$ext} if exists $extra_types{$ext};
  62. return $mt if $mt;
  63. # If all else fails, time for libmagic
  64. state $magic = File::LibMagic->new;
  65. my $maybe_ct = $magic->info_from_filename($file);
  66. $mt = $maybe_ct->{mime_type} if ( is_hashref($maybe_ct) && $maybe_ct->{mime_type} );
  67. return $mt;
  68. }
  69. 1;