veda-consulting-company / uk.co.vedaconsulting.mosaico

Other
39 stars 75 forks source link

Plugin interface to Mosaico #347

Closed skyslasher closed 1 year ago

skyslasher commented 4 years ago

Hello,

I want to draw your attention to an enhancement plugin I wrote for Mosaico running in CiviCRM. It makes Wordpress content available to the newsletter engine.

To do so, I had to overwrite the Mosaico iframe URL route civicrm/mosaico/iframe because I needed to inject my plugin code into the Mosaico startup process.

For a clean code separation I implemented hooks for

You already implemented hooks for

that I am using for this plugin.

It would be great if you could consider including my hooks in your main branch, so I do not have to hijack the civicrm/mosaico/iframe route what I consider a dirty (but in this case necessary) hack. Also, with these hooks, other plugins for Mosaico in CiviCRM can be implemented pretty easy.

Regards Andreas

totten commented 4 years ago

I like the idea a lot.

Nice catch in recognizing how to override civicrm/mosaico/iframe from another extension.

Conventional wisdom might tell us to use the existing, eh, conventions for managing CSS/JS resources (e.g. hook_pageRun; Civi::resources()->addScriptFile()), but civicrm/mosaico/iframe is in an unusual position... it particularly needs to not use the defaults/libraries/layouts that normal pages use. I don't think the cost/benefit of adapting to Civi::resources() (or any other pre-existing resource listing) is good here. I think you're on a sensible path using a separate hook for Mosaico plugins.

If I could bikeshed a bit... I'd probably suggest one hook to define each logical "plugin" (including name, CSS/JS URLs, the JS init snippt) rather than 3 separate hooks for the different aspects. Spitballing what that might look like:

require_once 'mymod.civix.php';
use CRM_Mymod_ExtensionUtil as E;

/**
 * Implements hook_civicrm_mosaicoPlugins
 *
 * @param array $plugins
 *    Modifiable list of Mosaico plugins, including js+css assets
 */
function mymod_civicrm_mosaicoPlugins(&$plugins) {
  $plugins['hackyConsoleInspector'] = [
    // JS plugin/callback/init expression
    'plugin' => 'function( vm ) { window.viewModel = vm; }',
  ];
  $cacheSuffix = '?r=' . CRM_Core_Resources::singleton()->getCacheCode();
  $plugins['wordpressPostsWidgetPlugin'] = [
     // Array of Javascript files (URLs)
    'js' => [E::url('js/wppostid.js') . $cacheSuffix],
     // Array of stylesheets (URLs)
    'css' => [E::url('css/wppostid.css') . $cacheSuffix],
    // JS plugin/callback/init expression
    'plugin' => 'wordpressPostsWidgetPlugin',
  ];
}

Civi has something similar in hook_civicrm_angularModules. Compared to a hypothetical hc_angularScripts+hc_angularStyles+hc_angularModules, I'm pretty sure this made it easier for us later. When we pivoted away from SPA and toward more specialized/optimized pages, we were able to use the same data to do smarter autoloading (without requiring a major change in the hook API). I could see this contract allowing better autoloading and/or configuration-options in the future.

For Mosaico, having an explicit list of plugins might make it easier to write an admin UI to tweak out the plugins/configuration.

skyslasher commented 4 years ago

Combining the three hooks into one looks good! I will take that approach into my implementation.

IMO an admin UI is a good idea if it is an additional but not necessary step for installing Mosaico plugins, e.g. disabling/re-enabling specific Mosaico plugins if they are shipped in one CiviCRM plugin.

I think having an easy and standardized way to provide additional Mosaico plugins can be a door opener. The Mosaico plugin space does not look that big at a first look, if you take a look at the pros like Mailchimp or Newsletter2go (popular in Germany), making template blocks smarter and thus saving time composing newsletters is their top selling point. Combining template blocks with a specialized widget is a very powerful mix in Mosaico, that's why I implemented this plugin. It saves our organisation (union site group) hours in composing mails, skillset and learning curve for the mailing authors went down dramatically.

My next project is a template block with corresponding widget (aka Mosaico plugin) that does quite the same as the one-click inclusion of wordpress posts with WooCommerce products. With that functionality, charities can promote fanshop products a lot easier, an it can make CiviCRM attractive for small retailers.

christianwach commented 4 years ago

@skyslasher Firstly, thanks for writing de.ergomation.wp-civi-mosaico - you beat me to it :-)

You have basically highlighted the main issue that made me postpone and work on other stuff - i.e. the available hooks. I look forward to them being implemented so there can be an ecosystem of similar ways to extend Mosaico.

I'd also like to chat sometime about your decision to make this a CiviCRM extension rather than a WordPress plugin - but that's OT here, I guess.

skyslasher commented 4 years ago

@christianwach Thanks!

Regarding the extension decision, see here for a discussion on that topic.

mattwire commented 4 years ago

@skyslasher Did you make any progress with the mosaico extension hook?

skyslasher commented 3 years ago

@christianwach I reworked my plugin and split it into three parts:

Everything not specific to WordPress (i.e. Mosaico plugin injector, embedding images into CiviMail mailings) is now agnostic to the underlaying CMS, and the WordPress integration is now a native WordPress plugin.

@totten @mattwire See the first in the list for the generic plugin interface. A brief description is in the README.md, the code should be OK to read. Please let me know what you think.