See ../../AGENTS.md for shared workspace conventions (Docker, n script, coding standards, git rules).
- Mixed autoloading with order dependency. Composer classmap on
includes/plus manualrequire_onceinnewspack-newsletters.php. Interfaces and base classes must be required FIRST (before provider implementations). After adding a new class file, you must both add arequire_onceto the main plugin file AND runcomposer dump-autoload. npm run lintruns JS and SCSS only. PHP linting requires separatenpm run lint:php. Running onlynpm run lintwill miss PHP violations.- The Newsletters wizard UI lives in
newspack-plugin, not here. This repo provides ESP APIs, editor, blocks, and rendering. The settings page (Engagement > Newsletters) is in newspack-plugin. - Publishing or making a post private triggers an ESP campaign send. This is irreversible. The
transition_post_statushook in the service provider base class sends the newsletter automatically. Be extremely careful with post status transitions, especially bulk operations. - Campaign Monitor is deprecated. Code still exists in
service-providers/campaign_monitor/but has zero client usage. Do not extend it. Active ESPs are Mailchimp, ActiveCampaign, and Constant Contact. - Three namespace styles coexist.
Newspack\Newsletters(backslash, newer:Send_Lists,Subscription_Lists),Newspack_Newsletters(underscore namespace:Ads, tracking classes), and no namespace with underscore prefix (legacy:Newspack_Newsletters,Newspack_Newsletters_Contacts). UseNewspack\Newslettersfor new classes. - Inconsistent initialization patterns. Some classes self-init at EOF (e.g.,
Ads::init_hooks()at bottom ofclass-ads.php), others are explicitly called in the main plugin file (e.g.,Subscription_Lists::init()). Check both locations before adding initialization to avoid double-init. Subscription_Listuses a Mailchimp-specific trait. The core class (includes/class-subscription-list.php) importsNewspack_Newsletters_Mailchimp_Subscription_List_Trait. Changing this trait affects all subscription lists, not just Mailchimp.- All integration checks must be defensive. Use
class_exists()/function_exists()guards for newspack-plugin dependencies. The plugin must work standalone.
// includes/class-my-feature.php
namespace Newspack\Newsletters;
defined( 'ABSPATH' ) || exit;
class My_Feature {
public static function init() {
// Register hooks here.
}
}
My_Feature::init();Then in newspack-newsletters.php, add the require_once in the correct position (after interfaces/base classes, before dependent code):
require_once NEWSPACK_NEWSLETTERS_PLUGIN_FILE . 'includes/class-my-feature.php';Then run composer dump-autoload.
Requires PHP, JS, and registration. See Constant Contact or ActiveCampaign for simpler examples (Mailchimp is the most complex).
- Create
includes/service-providers/<name>/with a main class extendingNewspack_Newsletters_Service_Providerthat implementsNewspack_Newsletters_ESP_API_Interface, and a controller extendingNewspack_Newsletters_Service_Provider_Controller. - Add
require_oncelines innewspack-newsletters.php. Order matters: the main class must come after the base class and interface requires. - Register via the
newspack_newsletters_registered_providersfilter inincludes/class-newspack-newsletters.phpget_registered_providers(). - Add provider-specific UI in
src/service-providers/<name>/. Export an object matching the shape insrc/service-providers/index.js(ProviderSidebar,renderPreSendInfo,isCampaignSent), and add it to theSERVICE_PROVIDERSmap. - Run
composer dump-autoload. - Rebuild:
n build.