PMC Digital Daily
A plugin to produce magazine-style layouts using Gutenberg. Issues can include articles, galleries, videos, and other brand-specific content types. Exclusive articles are supported, as are Special Editions.
Terminology
Views
There are two views to every issue: landing-page and full. The Landing Page view includes summaries of most articles and often displays content in columns. Full View includes full article content in a vertical layout that removes the columns. Articles created exclusively for Special Editions show full content in both views.
Structure
The Digital Daily feature relies on three plugins:
pmc-digital-daily: post types, manipulation of front-end for both views, ads, analytics, print support, and other feature-specific elements such as the Table of Contents.pmc-gutenberg: editorial interface and data handling for Larva modulespmc-larva: front-end display
Caveats
Currently, this plugin can only be used with pmc-wwd-2021 because the block
templates are part of that theme. For this to be used on another brand, the
following must happen:
- The
block-*modules inpmc-wwd-2021are ported to the Larva monorepo. - Relevant CSS and JS is ported to the Larva monorepo or the assets build in this plugin.
- The relevant block classes in
pmc-gutenbergare refactored into Larva module controllers inpmc-larva.
How Views Work
As noted in the Terminology section, each issue is made up
of two views. Both are rendered using the same template, with some elements
limited to one view or the other using a conditional provided by the
PMC\Digital_Daily\Full_View class.
The landing-page view is a standard Gutenberg rendering of the blocks added to each issue.
To present Full View in a single column, the Full_View class overrides
block rendering and uses the PMC\Digital_Daily\Block_Flattener class to
remove any Columns blocks (both core/columns and core/column) present in
the content, then calls Core's do_blocks function using the flattened
block list.
To keep readers within the Digital Daily issue as much as possible, all permalinks in the landing-page view are overridden to link to the issue's full view. In full view, only gallery and runway-review blocks include permalinks to the original content due to the specialized templates each of those content types use.
Class Notes
Ads
Three custom ad conditions are registered to allow ads to be targeted to Digital Daily issues:
digital_daily_is_full_viewdigital_daily_is_landing_viewdigital_daily_issue_date- accepts any date string compatible withstrtotime().
Skins are automatically disabled on all issues.
To improve the reading experience, space for ad slots is reserved by automatically enabling PMC Ad Manager's "CLS Optimization" feature even if the site does not normally use it.
Analytics
In addition to a site's default Google Analytics integration, click events
and pageviews can be recorded for individual story blocks, interactions with
the table of contents, and more. Selectors are customized by the theme
through the pmc_digital_daily_analytics_settings filter.
If a reader exits a Digital Daily issue or archive page into another part of the site, the Digital Daily URL will appear in the site's main GA profile as a referrer.
Block_Flattener
There are two features that require a simplified version of a Digital Daily
issue, one free of columns and groups. These features are supported by the
Block_Flattener class, which, as the name indicates, un-nests blocks into a
single-column, flattened representation. The Full_View and
Table_of_Contents\Parser classes use the Block_Flattener to create the
single-column layout called for by the Full View and to generate the data
needed to render the table of contents, respectively.
Full_View
The Full_View class contains a mix of static and non-static methods; many
of the static methods are convenience wrappers for non-static methods,
introduced to make using the class less verbose. In templates, especially,
there can be numerous references to methods in the Full_View class, which
are simplified by not repeatedly referencing the get_singleton() method.
Most of the non-static methods are intended for use as filter callbacks and are
not meant for use outside the class.
To determine if the current request is for an issue's full-view
representation, the Full_View::is() method is provided.
To retrieve an issue's full-view permalink, the Full_View::get_permalink()
method is provided.
As noted in the How Views Work section, readers are kept
within the Digital Daily issue by overridding permalinks to direct the user
to an issue's full view. These filters can be toggled on and off using the
Full_View::add_permalink_filters() and Full_View::remove_permalink_filters()
methods.
Table_Of_Contents
On post save, this class applies the Table_of_Contents\Parser class to a
post's content and saves the resulting data in post meta. Its get() method
is used to retrieve and format that data for front-end output.
Integrations\Edit_Flow
To support articles published exclusively for use in a Digital Daily issue, the plugin registers a "Digital Daily Published" post status for the "post" post type.
Integrations\Elasticsearch
Custom post types and statuses registered by this plugin will not be searchable
in story blocks (or any other blocks that rely on the REST API for search)
unless added to the allowlists modified by this class. Some statuses are added
to the allowlist via \PMC_Feature::elasticpress_index_other_statuses() if
they are useful to other Gutenberg blocks that aren't specific to the Digital
Daily.
Integrations\Exacttarget
To allow newsletters to link to posts as they appear in the Digital Daily,
the plugin hooks into the Exacttarget plugin's post-processing and overrides
permalinks. If set, it also applies title, excerpt, content, and
featured-image overrides as captured by Table_Oof_Contents\Parser.
Table_of_Contents\Parser
To support the Table_Of_Contents and Integrations\Exacttarget classes,
the Table_of_Contents\Parser class extends the Block_Flattener class to
produce an array of post IDs and post-data overrides extracted from the
flattened list of blocks present in a Digital Daily issue.
Coding Standards
- All methods have docblocks with descriptions and complete argument documentation.
- All method arguments are strictly typed (unless used as a filter callback that passes ambiguous or complex data types).
- All methods have return types.
- All files adhere to an 80-character line length for legibility and easier code review.
- All methods have test coverage. Coverage-ignores are used only when lines
are untestable (
exitcalls orclass_exists()checks) or tests would be duplicative (such asTable_of_Contents\Parser::_do()). - For legibility and to reduce repetition, use
usestatements rather than verbose references. - Often-used class methods are provided static shortuct methods placed at the
top of the class file, ahead of the constructor. Examples include helpers
like
Full_View::is(),Full_View::add_permalink_filters(), andMeta::get_special_edition_header_image_id(). This approach reduces the need to continually reference theget_singleton()method.