* @link https://getkirby.com * @copyright Bastian Allgeier GmbH * @license https://getkirby.com/license */ class FileBlueprint extends Blueprint { /** * `true` if the default accepted * types are being used * * @var bool */ protected $defaultTypes = false; public function __construct(array $props) { parent::__construct($props); // normalize all available page options $this->props['options'] = $this->normalizeOptions( $this->props['options'] ?? true, // defaults [ 'changeName' => null, 'create' => null, 'delete' => null, 'read' => null, 'replace' => null, 'update' => null, ] ); // normalize the accept settings $this->props['accept'] = $this->normalizeAccept($this->props['accept'] ?? []); } /** * @return array */ public function accept(): array { return $this->props['accept']; } /** * Returns the list of all accepted MIME types for * file upload or `*` if all MIME types are allowed * * @return string */ public function acceptMime(): string { // don't disclose the specific default types if ($this->defaultTypes === true) { return '*'; } $accept = $this->accept(); $restrictions = []; if (is_array($accept['mime']) === true) { $restrictions[] = $accept['mime']; } else { // only fall back to the extension or type if // no explicit MIME types were defined // (allows to set custom MIME types for the frontend // check but still restrict the extension and/or type) if (is_array($accept['extension']) === true) { // determine the main MIME type for each extension $restrictions[] = array_map(['Kirby\Toolkit\Mime', 'fromExtension'], $accept['extension']); } if (is_array($accept['type']) === true) { // determine the MIME types of each file type $mimes = []; foreach ($accept['type'] as $type) { if ($extensions = F::typeToExtensions($type)) { $mimes[] = array_map(['Kirby\Toolkit\Mime', 'fromExtension'], $extensions); } } $restrictions[] = array_merge(...$mimes); } } if ($restrictions !== []) { if (count($restrictions) > 1) { // only return the MIME types that are allowed by all restrictions $mimes = array_intersect(...$restrictions); } else { $mimes = $restrictions[0]; } // filter out empty MIME types and duplicates return implode(', ', array_filter(array_unique($mimes))); } // no restrictions, accept everything return '*'; } /** * @param mixed $accept * @return array */ protected function normalizeAccept($accept = null): array { if (is_string($accept) === true) { $accept = [ 'mime' => $accept ]; } elseif ($accept === true) { // explicitly no restrictions at all $accept = [ 'mime' => null ]; } elseif (empty($accept) === true) { // no custom restrictions $accept = []; } $accept = array_change_key_case($accept); $defaults = [ 'extension' => null, 'mime' => null, 'maxheight' => null, 'maxsize' => null, 'maxwidth' => null, 'minheight' => null, 'minsize' => null, 'minwidth' => null, 'orientation' => null, 'type' => null ]; // default type restriction if none are configured; // this ensures that no unexpected files are uploaded if ( array_key_exists('mime', $accept) === false && array_key_exists('extension', $accept) === false && array_key_exists('type', $accept) === false ) { $defaults['type'] = ['image', 'document', 'archive', 'audio', 'video']; $this->defaultTypes = true; } $accept = array_merge($defaults, $accept); // normalize the MIME, extension and type from strings into arrays if (is_string($accept['mime']) === true) { $accept['mime'] = array_map(function ($mime) { return $mime['value']; }, Str::accepted($accept['mime'])); } if (is_string($accept['extension']) === true) { $accept['extension'] = array_map('trim', explode(',', $accept['extension'])); } if (is_string($accept['type']) === true) { $accept['type'] = array_map('trim', explode(',', $accept['type'])); } return $accept; } }