| 1 |
<?php |
| 2 |
/** |
| 3 |
* File families and their icons. |
| 4 |
* |
| 5 |
* Shared by the metabox, the frontend list and the settings preview, so the |
| 6 |
* same file looks the same everywhere. |
| 7 |
* |
| 8 |
* @package WP_Attachments |
| 9 |
*/ |
| 10 |
|
| 11 |
/** |
| 12 |
* Reduce a MIME type to one of the icon families. |
| 13 |
* |
| 14 |
* @param string $mime_type MIME type. |
| 15 |
* @return string One of pdf, doc, sheet, slides, archive, audio, video, image, code, text, default. |
| 16 |
*/ |
| 17 |
function wpatt_get_file_type( $mime_type ) { |
| 18 |
$mime_type = strtolower( (string) $mime_type ); |
| 19 |
|
| 20 |
// Checked in order: the first prefix that matches wins, so the more |
| 21 |
// specific entries (text/csv) come before the broad ones (text/). |
| 22 |
$prefixes = array( |
| 23 |
'image/' => 'image', |
| 24 |
'video/' => 'video', |
| 25 |
'audio/' => 'audio', |
| 26 |
'text/csv' => 'sheet', |
| 27 |
'text/html' => 'code', |
| 28 |
'text/' => 'text', |
| 29 |
); |
| 30 |
foreach ( $prefixes as $prefix => $type ) { |
| 31 |
if ( strpos( $mime_type, $prefix ) === 0 ) { |
| 32 |
return $type; |
| 33 |
} |
| 34 |
} |
| 35 |
|
| 36 |
$needles = array( |
| 37 |
'pdf' => 'pdf', |
| 38 |
'wordprocessing' => 'doc', |
| 39 |
'msword' => 'doc', |
| 40 |
'opendocument.text' => 'doc', |
| 41 |
'rtf' => 'doc', |
| 42 |
'spreadsheet' => 'sheet', |
| 43 |
'ms-excel' => 'sheet', |
| 44 |
'presentation' => 'slides', |
| 45 |
'ms-powerpoint' => 'slides', |
| 46 |
'zip' => 'archive', |
| 47 |
'compressed' => 'archive', |
| 48 |
'tar' => 'archive', |
| 49 |
'gzip' => 'archive', |
| 50 |
'json' => 'code', |
| 51 |
'xml' => 'code', |
| 52 |
'javascript' => 'code', |
| 53 |
); |
| 54 |
foreach ( $needles as $needle => $type ) { |
| 55 |
if ( strpos( $mime_type, $needle ) !== false ) { |
| 56 |
return $type; |
| 57 |
} |
| 58 |
} |
| 59 |
|
| 60 |
return 'default'; |
| 61 |
} |
| 62 |
|
| 63 |
/** |
| 64 |
* Inline SVG icon for a file family. |
| 65 |
* |
| 66 |
* Inline rather than a font, sprite or CSS mask: crisp at any pixel density, |
| 67 |
* coloured by the surrounding text through currentColor, no extra request, |
| 68 |
* and nothing a theme has to support. |
| 69 |
* |
| 70 |
* Every family has its own shape, so the icons still tell the types apart |
| 71 |
* when they are shown in a single colour. |
| 72 |
* |
| 73 |
* @param string $type File family, from wpatt_get_file_type(). |
| 74 |
* @param string $class CSS class for the <svg>. |
| 75 |
* @return string |
| 76 |
*/ |
| 77 |
function wpatt_get_file_icon_svg( $type, $class = 'wpa-file-icon' ) { |
| 78 |
// Sheet of paper with a folded corner, shared by the document families. |
| 79 |
$page = '<path d="M14 2.75H7A2.25 2.25 0 0 0 4.75 5v14A2.25 2.25 0 0 0 7 21.25h10A2.25 2.25 0 0 0 19.25 19V8L14 2.75Z" fill="currentColor" fill-opacity=".13"/>' |
| 80 |
. '<path d="M14 2.75H7A2.25 2.25 0 0 0 4.75 5v14A2.25 2.25 0 0 0 7 21.25h10A2.25 2.25 0 0 0 19.25 19V8L14 2.75Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>' |
| 81 |
. '<path d="M13.75 3v4.25H18" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>'; |
| 82 |
|
| 83 |
// Rounded frame shared by the media families. |
| 84 |
$frame = '<rect x="3.75" y="4.75" width="16.5" height="14.5" rx="2.25" fill="currentColor" fill-opacity=".13"/>' |
| 85 |
. '<rect x="3.75" y="4.75" width="16.5" height="14.5" rx="2.25" stroke="currentColor" stroke-width="1.5"/>'; |
| 86 |
|
| 87 |
$glyphs = array( |
| 88 |
// Solid label band: tells a PDF from a text document without colour. |
| 89 |
'pdf' => $page |
| 90 |
. '<rect x="6.75" y="12.5" width="10.5" height="5.5" rx="1" fill="currentColor"/>', |
| 91 |
|
| 92 |
'doc' => $page |
| 93 |
. '<path d="M8 12.5h8M8 15.5h8M8 18.5h5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>', |
| 94 |
|
| 95 |
'text' => $page |
| 96 |
. '<path d="M8 13.5h8M8 16.5h5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>', |
| 97 |
|
| 98 |
'sheet' => $page |
| 99 |
. '<rect x="7.25" y="12.25" width="9.5" height="6.5" rx="1" stroke="currentColor" stroke-width="1.5"/>' |
| 100 |
. '<path d="M12 12.25v6.5M7.25 15.5h9.5" stroke="currentColor" stroke-width="1.5"/>', |
| 101 |
|
| 102 |
'slides' => $page |
| 103 |
. '<rect x="7.25" y="12.25" width="9.5" height="6.5" rx="1" stroke="currentColor" stroke-width="1.5"/>' |
| 104 |
. '<path d="M9.5 16.5l2-2 1.75 1.75 1.25-1.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>', |
| 105 |
|
| 106 |
'code' => $page |
| 107 |
. '<path d="M10.25 12.75 7.75 15.5l2.5 2.75M13.75 12.75l2.5 2.75-2.5 2.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>', |
| 108 |
|
| 109 |
'image' => $frame |
| 110 |
. '<circle cx="8.75" cy="10" r="1.5" fill="currentColor"/>' |
| 111 |
. '<path d="M4.75 17.5 9.5 12.75l3.25 3.25 2.25-1.75 4.25 3.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>', |
| 112 |
|
| 113 |
'video' => $frame |
| 114 |
. '<path d="M10.25 9.25v5.5l5-2.75-5-2.75Z" fill="currentColor"/>', |
| 115 |
|
| 116 |
'audio' => '<path d="M9.5 16.5V6.75l8.75-1.75V14.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>' |
| 117 |
. '<ellipse cx="7.25" cy="16.75" rx="2.75" ry="2.25" fill="currentColor"/>' |
| 118 |
. '<ellipse cx="16" cy="14.75" rx="2.75" ry="2.25" fill="currentColor"/>', |
| 119 |
|
| 120 |
'archive' => '<path d="M4.75 7.75h14.5V19A2.25 2.25 0 0 1 17 21.25H7A2.25 2.25 0 0 1 4.75 19V7.75Z" fill="currentColor" fill-opacity=".13"/>' |
| 121 |
. '<rect x="3.75" y="3.75" width="16.5" height="4" rx="1.25" stroke="currentColor" stroke-width="1.5"/>' |
| 122 |
. '<path d="M5 7.75V19A2.25 2.25 0 0 0 7.25 21.25h9.5A2.25 2.25 0 0 0 19 19V7.75" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>' |
| 123 |
. '<path d="M10.25 11.5h3.5M10.25 14.5h3.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>', |
| 124 |
|
| 125 |
'default' => $page, |
| 126 |
); |
| 127 |
|
| 128 |
$glyph = isset( $glyphs[ $type ] ) ? $glyphs[ $type ] : $glyphs['default']; |
| 129 |
|
| 130 |
// width/height attributes keep the icon small even where a theme's CSS |
| 131 |
// does not reach it (or resets svg sizing). |
| 132 |
return '<svg class="' . esc_attr( $class ) . '" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false">' |
| 133 |
. $glyph . '</svg>'; |
| 134 |
} |
| 135 |
|
| 136 |
/** |
| 137 |
* File extension of an attachment, upper case, from its URL. |
| 138 |
* |
| 139 |
* @param int $attachment_id Attachment ID. |
| 140 |
* @return string |
| 141 |
*/ |
| 142 |
function wpatt_get_file_extension( $attachment_id ) { |
| 143 |
$url = wp_get_attachment_url( $attachment_id ); |
| 144 |
// parse_url() first: a query string would otherwise end up in the extension. |
| 145 |
$path = $url ? wp_parse_url( $url, PHP_URL_PATH ) : ''; |
| 146 |
|
| 147 |
return $path ? strtoupper( pathinfo( $path, PATHINFO_EXTENSION ) ) : ''; |
| 148 |
} |
| 149 |
|