#3591885: Add `document` object $ref for linking locally hosted documents

Adds the document object $ref agreed in #3524130, note 1678367, mirroring the shipped video shape point for point.

What this branch does

  • schema.json: adds the document definition with src (required), title, description, filename, filesize, and mimetype. src carries contentMediaType: application/* — every agreed extension (pdf doc docx xls xlsx ppt pptm pptx key ai indd) resolves to the application MIME media type, and the wildcard is what makes field matching precise (see below).
  • JsonSchemaObjectRef: adds the Document case; canvas.json_schema.yml allows the new URI in the Choice constraint.
  • JsonSchemaType::computeStorablePropShape(): Document arm using the file_generic widget. src resolves the referenced File entity uri to an absolute URL; filename, filesize, and mimetype resolve from the File entity filename, filesize, and filemime properties.
  • ShapeMatchingHooks: maps Document to the File media source so sites with Media Library get the media picker, including filename/filesize/mimetype in each bundle branch. VideoFile extends File, so getMediaTypesForSource() now skips media types whose source has a more specific SCHEMA_TO_MEDIA_SOURCE entry — video media types stay out of document props.
  • First commit fixes a latent matcher bug this shape exposed: the UriTargetMediaType requirement was only applied for contentMediaType: image/* and video/*. With application/* falling through to the loose branch, the matcher accepted URI properties targeting any media type and assembled nonsense object matches (e.g. title from a file field description). The requirement now applies to every valid wildcard.
  • Docs: component-metadata.mdx gains a Document section.

Deviations from note 1678367

  • title and description are not resolved by the storable prop shape or the media mapping: FieldObjectPropsExpression requires every sub-expression to target the same field item, so the Media entity label is not reachable from the source field. Both stay populatable via static prop sources.
  • The code editor "Document" prop type is not included — video shipped its editor UI separately in #3534601, and this follows the same split. Follow-up issue to come.

AI-Generated: Yes (Used Claude Code to implement the agreed proposal, diagnose the wildcard contentMediaType matcher gap, and update tests and docs; reviewed by @mglaman).

Testing instructions

  • Enable sdc_test_all_props and confirm the all-props component exposes test_object_drupal_document with a file upload limited to the agreed document extensions.
  • Create a file source media type, re-open the component: the prop now offers the media library picker, and video media types are not selectable.
  • Place the component, select a PDF, confirm the rendered output shows the absolute file URL, filename, file size, and MIME type.
  • composer run phpunit -- tests/src/Kernel/PropShapeRepositoryTest.php tests/src/Kernel/MediaLibraryHookStoragePropAlterTest.php tests/src/Kernel/ShapeMatcher/

Merge request reports

Loading