PMC Plugins
Pmc Digital Daily

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:

  1. 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.
  2. pmc-gutenberg: editorial interface and data handling for Larva modules
  3. pmc-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:

  1. The block-* modules in pmc-wwd-2021 are ported to the Larva monorepo.
  2. Relevant CSS and JS is ported to the Larva monorepo or the assets build in this plugin.
  3. The relevant block classes in pmc-gutenberg are refactored into Larva module controllers in pmc-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:

  1. digital_daily_is_full_view
  2. digital_daily_is_landing_view
  3. digital_daily_issue_date - accepts any date string compatible with strtotime().

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

  1. All methods have docblocks with descriptions and complete argument documentation.
  2. All method arguments are strictly typed (unless used as a filter callback that passes ambiguous or complex data types).
  3. All methods have return types.
  4. All files adhere to an 80-character line length for legibility and easier code review.
  5. All methods have test coverage. Coverage-ignores are used only when lines are untestable (exit calls or class_exists() checks) or tests would be duplicative (such as Table_of_Contents\Parser::_do()).
  6. For legibility and to reduce repetition, use use statements rather than verbose references.
  7. 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(), and Meta::get_special_edition_header_image_id(). This approach reduces the need to continually reference the get_singleton() method.