prefix}desktop_mode_stored_files`. Unlike * every other built-in type, the placement OWNS the entity — see * the deletion contract in `stored-files-store.php`. * * @package OpenStation */ defined( 'ABSPATH' ) || exit; /** * The `upload` desktop file type. */ class OpenStation_Upload_File extends OpenStation_File { /** * Get the file type identifier. * * @return string */ public static function type(): string { return 'upload'; } /** * Whether the stored-file row still exists in the database. * * @return bool */ public function exists(): bool { return null !== $this->row(); } /** * Get the display name, falling back to a generic label. * * @return string */ public function title(): string { $row = $this->row(); if ( ! $row ) { return __( '(missing file)', 'desktop-mode' ); } return '' !== (string) $row['display_name'] ? (string) $row['display_name'] : __( 'file', 'desktop-mode' ); } /** * Resolve a Dashicon class based on the coarse mime category. * * @return string */ public function icon(): string { switch ( $this->kind() ) { case 'image': return 'dashicons-format-image'; case 'video': return 'dashicons-format-video'; case 'audio': return 'dashicons-format-audio'; case 'pdf': return 'dashicons-pdf'; case 'archive': return 'dashicons-archive'; case 'text': return 'dashicons-media-text'; default: return 'dashicons-media-default'; } } /** * Delegate to the stored-file capability resolver. * * @param int $user_id * @return bool */ public function can_read( int $user_id ): bool { $row = $this->row(); if ( ! $row ) { return false; } return openstation_stored_file_user_can_read( (int) $row['id'], $user_id ); } /** * Augment the base serialized shape with owner id, size, mime, * kind slug, and whether the Media Library would accept the file. * * @return array */ public function serialize(): array { $shape = parent::serialize(); $row = $this->row(); $shape['ownerId'] = $row ? (int) $row['owner_id'] : 0; $shape['sizeBytes'] = $row ? (int) $row['size_bytes'] : 0; $shape['mime'] = $row ? (string) $row['mime'] : ''; $shape['kind'] = $this->kind(); $shape['isMedia'] = $row && function_exists( 'openstation_stored_file_is_media' ) ? openstation_stored_file_is_media( $row ) : false; return $shape; } /** * Coarse mime-category slug used for the tile icon and by the * JS type for rendering decisions. * * @return string image|video|audio|pdf|archive|text|file */ private function kind(): string { $row = $this->row(); $mime = $row ? strtolower( (string) $row['mime'] ) : ''; if ( '' === $mime ) { return 'file'; } $major = strtok( $mime, '/' ); if ( in_array( $major, array( 'image', 'video', 'audio' ), true ) ) { return $major; } if ( 'application/pdf' === $mime ) { return 'pdf'; } if ( preg_match( '#^application/(zip|x-tar|x-gzip|gzip|x-7z-compressed|x-rar-compressed|x-bzip2?)$#', $mime ) ) { return 'archive'; } if ( 'text' === $major || in_array( $mime, array( 'application/json', 'application/xml' ), true ) ) { return 'text'; } return 'file'; } /** * Lazily resolve the stored-file row from the database. * * @return array|null Null when the row is gone or the ref is invalid. */ private function row(): ?array { $id = (int) $this->ref; if ( $id <= 0 || ! function_exists( 'openstation_stored_files_get' ) ) { return null; } return openstation_stored_files_get( $id ); } }