Skip to content

Commit

Permalink
PROJ-2283 Version 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
agileware-justin committed May 17, 2022
0 parents commit fabd87f
Show file tree
Hide file tree
Showing 17 changed files with 1,586 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/au.com.agileware.partneremailgreeting.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/php.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

667 changes: 667 additions & 0 deletions LICENSE.txt

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Partner and Spouse Email Greeting

Changes the Email Greeting to include the First Name of a Contact having an active Relationship of type: Partner Of or Spouse Of. For example: "Dear Fran and Justin", instead of the default "Dear Fran".

This allows emails to be sent to Contacts which have a shared email account and address both Contacts in the email.

Email Greeting will be changed to include the First Name of the related Contact when a Relationship of type: **Partner Of** or **Spouse Of** is **added** or **enabled**.

Email Greeting will be **reverted** to the standard greeting if these relationships are **deleted** or **disabled**.

If the related Contact does **not** have a **First Name** set, then the standard greeting will be set.

# Installation

1. Install and enable this CiviCRM extension like any normal CiviCRM extension.
1. Enable the Scheduled Job, `Update Partner Email Greeting`

# About the Authors

This CiviCRM extension was developed by the team at [Agileware](https://agileware.com.au).

[Agileware](https://agileware.com.au) provide a range of CiviCRM services including:

* CiviCRM migration
* CiviCRM integration
* CiviCRM extension development
* CiviCRM support
* CiviCRM hosting
* CiviCRM remote training services

Support your Australian [CiviCRM](https://civicrm.org) developers, [contact Agileware](https://agileware.com.au/contact) today!

![Agileware](images/agileware-logo.png)
20 changes: 20 additions & 0 deletions api/v3/Job/Partneremailgreeting.mgd.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
// This file declares a managed database record of type "Job".
// The record will be automatically inserted, updated, or deleted from the
// database as appropriate. For more details, see "hook_civicrm_managed" at:
// https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_managed
return [
[
'name' => 'Cron:Job.Partneremailgreeting',
'entity' => 'Job',
'params' => [
'version' => 3,
'name' => 'Update Partner Email Greeting',
'description' => 'Update email greetings for contacts having Partner Of or Spouse Of relationships',
'run_frequency' => 'Daily',
'api_entity' => 'Job',
'api_action' => 'Partneremailgreeting',
'parameters' => '',
],
],
];
103 changes: 103 additions & 0 deletions api/v3/Job/Partneremailgreeting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

use Civi\Api4\Contact;
use Civi\Api4\Relationship;
use CRM_Partneremailgreeting_ExtensionUtil as E;

/**
* Job.Partneremailgreeting API specification (optional)
* This is used for documentation and validation.
*
* @param array $spec description of fields supported by this API call
*
* @see https://docs.civicrm.org/dev/en/latest/framework/api-architecture/
*/
function _civicrm_api3_job_Partneremailgreeting_spec(&$spec) {
}

/**
* Job.Partneremailgreeting API
*
* @param array $params
*
* @return array
* API result descriptor
*
* @throws API_Exception
* @see civicrm_api3_create_success
*
*/
function civicrm_api3_job_Partneremailgreeting($params) {
try {

// Get all active Partner and Spouse relationships, update email greeting for each contact in the relationship

$relationships = Relationship::get()
->addWhere('is_active', '=', TRUE)
->addClause('OR', [
'relationship_type_id:name',
'=',
'Partner of',
], [
'relationship_type_id:name',
'=',
'Spouse of',
])
->execute();
foreach ($relationships as $relationship) {
$contacts = Contact::get()
->addSelect('first_name')
->addClause('OR', [
'id',
'=',
$relationship['contact_id_a'],
], [
'id',
'=',
$relationship['contact_id_b'],
])
->setLimit(2)
->execute()->getArrayCopy();

// Check that the first name is set for both contacts before setting the customised greeting
if ($contacts[0]['first_name'] && $contacts[1]['first_name']) {
Contact::update()
->addValue('email_greeting_custom', 'Dear ' . $contacts[0]['first_name'] . ' and ' . $contacts[1]['first_name'])
->addValue('email_greeting_id:name', 'Customized')
->addClause('OR', [
'id',
'=',
$relationship['contact_id_a'],
], [
'id',
'=',
$relationship['contact_id_b'],
])
->execute();
}
else {
// If the first name is not set for either contact then reset to the standard greeting
Contact::update()
->addValue('email_greeting_id:name', 'Dear {contact.first_name}')
->addClause('OR', [
'id',
'=',
$relationship['contact_id_a'],
], [
'id',
'=',
$relationship['contact_id_b'],
])
->execute();
}
}
return civicrm_api3_create_success(TRUE, $params, 'Partneremailgreeting', 'Partneremailgreeting');
}

catch
(API_Exception $e) {
$errorMessage = $e->getMessage();
CRM_Core_Error::debug_var('Job.Partneremailgreeting', $errorMessage);
return civicrm_api3_create_error($errorMessage);
}
}
Binary file added images/agileware-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0"?>
<extension key="au.com.agileware.partneremailgreeting" type="module">
<file>partneremailgreeting</file>
<name>Partner and Spouse Email Greeting</name>
<description>Changes the Email Greeting to include the First Name of a Contact having an active Relationship of type: Partner Of or Spouse Of. For example: "Dear Fran and Justin", instead of the default "Dear Fran".</description>
<license>AGPL-3.0</license>
<maintainer>
<author>Agileware</author>
<email>support@agileware.com.au</email>
</maintainer>
<urls>
<url desc="Main Extension Page">https://github.com/agileware/au.com.agileware.partneremailgreeting</url>
<url desc="Documentation">https://github.com/agileware/au.com.agileware.partneremailgreeting</url>
<url desc="Support">https://github.com/agileware/au.com.agileware.partneremailgreeting</url>
<url desc="Licensing">http://www.gnu.org/licenses/agpl-3.0.html</url>
</urls>
<releaseDate>2022-05-17</releaseDate>
<version>1.0</version>
<develStage>stable</develStage>
<compatibility>
<ver>5.0</ver>
</compatibility>
<comments></comments>
<classloader>
<psr4 prefix="Civi\" path="Civi"/>
</classloader>
<civix>
<namespace>CRM/Partneremailgreeting</namespace>
<format>22.05.0</format>
<angularModule>crmPartneremailgreeting</angularModule>
</civix>
<mixins>
<mixin>setting-php@1.0.0</mixin>
<mixin>mgd-php@1.0.0</mixin>
</mixins>
</extension>
42 changes: 42 additions & 0 deletions mixin/mgd-php@1.0.0.mixin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/**
* Auto-register "**.mgd.php" files.
*
* @mixinName mgd-php
* @mixinVersion 1.0.0
*
* @param CRM_Extension_MixInfo $mixInfo
* On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
* @param \CRM_Extension_BootCache $bootCache
* On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
*/
return function ($mixInfo, $bootCache) {

/**
* @param \Civi\Core\Event\GenericHookEvent $e
* @see CRM_Utils_Hook::managed()
*/
Civi::dispatcher()->addListener('hook_civicrm_managed', function ($event) use ($mixInfo) {
// When deactivating on a polyfill/pre-mixin system, listeners may not cleanup automatically.
if (!$mixInfo->isActive()) {
return;
}

$mgdFiles = CRM_Utils_File::findFiles($mixInfo->getPath(), '*.mgd.php');
sort($mgdFiles);
foreach ($mgdFiles as $file) {
$es = include $file;
foreach ($es as $e) {
if (empty($e['module'])) {
$e['module'] = $mixInfo->longName;
}
if (empty($e['params']['version'])) {
$e['params']['version'] = '3';
}
$event->entities[] = $e;
}
}
});

};
101 changes: 101 additions & 0 deletions mixin/polyfill.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

/**
* When deploying on systems that lack mixin support, fake it.
*
* @mixinFile polyfill.php
*
* This polyfill does some (persnickity) deduplication, but it doesn't allow upgrades or shipping replacements in core.
*
* Note: The polyfill.php is designed to be copied into extensions for interoperability. Consequently, this file is
* not used 'live' by `civicrm-core`. However, the file does need a canonical home, and it's convenient to keep it
* adjacent to the actual mixin files.
*
* @param string $longName
* @param string $shortName
* @param string $basePath
*/
return function ($longName, $shortName, $basePath) {
// Construct imitations of the mixin services. These cannot work as well (e.g. with respect to
// number of file-reads, deduping, upgrading)... but they should be OK for a few months while
// the mixin services become available.

// List of active mixins; deduped by version
$mixinVers = [];
foreach ((array) glob($basePath . '/mixin/*.mixin.php') as $f) {
[$name, $ver] = explode('@', substr(basename($f), 0, -10));
if (!isset($mixinVers[$name]) || version_compare($ver, $mixinVers[$name], '>')) {
$mixinVers[$name] = $ver;
}
}
$mixins = [];
foreach ($mixinVers as $name => $ver) {
$mixins[] = "$name@$ver";
}

// Imitate CRM_Extension_MixInfo.
$mixInfo = new class() {

/**
* @var string
*/
public $longName;

/**
* @var string
*/
public $shortName;

public $_basePath;

public function getPath($file = NULL) {
return $this->_basePath . ($file === NULL ? '' : (DIRECTORY_SEPARATOR . $file));
}

public function isActive() {
return \CRM_Extension_System::singleton()->getMapper()->isActiveModule($this->shortName);
}

};
$mixInfo->longName = $longName;
$mixInfo->shortName = $shortName;
$mixInfo->_basePath = $basePath;

// Imitate CRM_Extension_BootCache.
$bootCache = new class() {

public function define($name, $callback) {
$envId = \CRM_Core_Config_Runtime::getId();
$oldExtCachePath = \Civi::paths()->getPath("[civicrm.compile]/CachedExtLoader.{$envId}.php");
$stat = stat($oldExtCachePath);
$file = Civi::paths()->getPath('[civicrm.compile]/CachedMixin.' . md5($name . ($stat['mtime'] ?? 0)) . '.php');
if (file_exists($file)) {
return include $file;
}
else {
$data = $callback();
file_put_contents($file, '<' . "?php\nreturn " . var_export($data, 1) . ';');
return $data;
}
}

};

// Imitate CRM_Extension_MixinLoader::run()
// Parse all live mixins before trying to scan any classes.
global $_CIVIX_MIXIN_POLYFILL;
foreach ($mixins as $mixin) {
// If the exact same mixin is defined by multiple exts, just use the first one.
if (!isset($_CIVIX_MIXIN_POLYFILL[$mixin])) {
$_CIVIX_MIXIN_POLYFILL[$mixin] = include_once $basePath . '/mixin/' . $mixin . '.mixin.php';
}
}
foreach ($mixins as $mixin) {
// If there's trickery about installs/uninstalls/resets, then we may need to register a second time.
if (!isset(\Civi::$statics[__FUNCTION__][$mixin])) {
\Civi::$statics[__FUNCTION__][$mixin] = 1;
$func = $_CIVIX_MIXIN_POLYFILL[$mixin];
$func($mixInfo, $bootCache);
}
}
};
Loading

0 comments on commit fabd87f

Please sign in to comment.