Commit 25f6a8bc authored by Andrei Mondoc's avatar Andrei Mondoc
Browse files

initial commit

parents
<?php
use CRM_Autofileoncase_ExtensionUtil as E;
/**
* Auto File class.
*
* @since 1.0
*/
class CRM_Autofileoncase_AutoFile extends CRM_Autofileoncase_HookBase {
/**
* Files an Activity on Case if applicable.
*
* @uses 'hook_civicrm_post'
*
* @since 1.0
* @param $action
* @param $entity
* @param $id
* @param $object
*/
public function maybeFileOnCase() {
if ($this->entity != 'Activity') return;
if ($this->action != 'create') return;
// bail if no matching activity type
if (!in_array(
$this->event->object->activity_type_id,
Civi::settings()->get('autofileoncase_activity_types') ?? []
)) {
return;
}
$targetsParams = [
'activity_id' => $this->event->id
];
// for Email activities we don't have a target
// quite yet so don't add record type param
if (
!in_array(
CRM_Core_Pseudoconstant::getName(
'CRM_Activity_BAO_Activity',
'activity_type_id',
$this->event->object->activity_type_id
),
['Email']
)
) {
$targetsParams['record_type_id'] = 'Activity Targets';
}
try {
$activityTargets = civicrm_api3('ActivityContact', 'get', $targetsParams);
} catch (CiviCRM_API3_Exception $e) {
// ignore exception
$activityTargets = false;
}
// bail if no targets
if (!$activityTargets || !$activityTargets['count'] ) return;
$activityTargets = array_column($activityTargets['values'], 'contact_id');
// only one open case
try {
$case = civicrm_api3('Case', 'get', [
'contact_id' => $activityTargets[0], // assume first contact
'status_id' => 'Open',
'options' => ['limit' => 1, 'sort' => 'id desc']
]);
} catch (CiviCRM_API3_Exception $e) {
// ignore exception
$case = false;
}
// bail if more than one or none open cases
if (!$case) return;
// bail if no matching case type
if (!in_array(
$case['case_type_id'],
Civi::settings()->get('autofileoncase_case_types') ?? []
)) {
return;
}
// we have all the data, good to go
$params = [
'caseID' => $case['id'],
'activityID' => $this->event->id,
'contactID' => $activityTargets[0],
'newSubject' => $this->event->object->subject ?? '',
'targetContactIds' => implode(',', $activityTargets),
'mode' => 'file'
];
// file on case
CRM_Activity_Page_AJAX::_convertToCaseActivity($params);
}
}
<?php
/**
* Hook base class.
*
* @since 1.0
*/
abstract class CRM_Autofileoncase_HookBase {
/**
* The Hook Event.
*
* @since 1.0
* @var Civi\Core\Event\GenericHookEvent
*/
protected $event;
/**
* Constructor.
*
* @since 1.0
* @param Civi\Core\Event\GenericHookEvent $event
*/
public function __construct(Civi\Core\Event\GenericHookEvent $event) {
$this->event = $event;
}
/**
* Getter.
*
* @since 1.0
*/
public function &__get($name) {
if (isset($this->event->$name)) {
return $this->event->$name;
}
}
/**
* Setter.
*
* @since 1.0
*/
public function __set($name, $value) {
if (isset($this->event->$name)) {
$this->event->$name = $value;
}
}
}
<?php
use CRM_Autofileoncase_ExtensionUtil as E;
/**
* Hook Registry class.
*
* @since 1.0
*/
class CRM_Autofileoncase_HookRegistry {
/**
* Post hook callback.
*
* @uses 'hook_civicrm_post'
*
* @since 1.0
* @param Civi\Core\Event\GenericHookEvent $event The event object
*/
public static function post(Civi\Core\Event\GenericHookEvent $event) {
(new CRM_Autofileoncase_AutoFile($event))->maybeFileOnCase();
}
}
<?php
use CRM_Autofileoncase_ExtensionUtil as E;
/**
* Utils class.
*
* @since 1.0
*/
class CRM_Autofileoncase_Utils {
/**
* Retrieve Case types.
*
* @since 1.0
* @return array $caseTypes
*/
public static function getCaseTypes(): array {
return CRM_Case_BAO_Case::buildOptions('case_type_id');
}
/**
* Retrieve Activity types.
*
* @since 1.0
* @return array $activityTypes
*/
public static function getActivityTypes(): array {
return CRM_Activity_BAO_Activity::buildOptions('activity_type_id');
}
}
This diff is collapsed.
# cc.tadpole.autofileoncase
![Screenshot](/images/autofile_on_case.png)
Adds the functionality to auto file activities on case for a set of given case types and activity types. The Activities will be auto filed against the latest Open case created for the activity target (useful for use cases where only one Case can be opened at at the same time).
The extension is licensed under [AGPL-3.0](LICENSE.txt).
## Requirements
- PHP v7.0+
- CiviCRM 5.8+
## Installation (Web UI)
This extension has not yet been published for installation via the web UI.
## Installation (CLI, Zip)
Sysadmins and developers may download the `.zip` file for this extension and
install it with the command-line tool [cv](https://github.com/civicrm/cv).
```bash
cd <extension-dir>
cv dl cc.tadpole.autofileoncase@https://github.com/FIXME/cc.tadpole.autofileoncase/archive/master.zip
```
## Installation (CLI, Git)
Sysadmins and developers may clone the [Git](https://en.wikipedia.org/wiki/Git) repo for this extension and
install it with the command-line tool [cv](https://github.com/civicrm/cv).
```bash
git clone https://github.com/FIXME/cc.tadpole.autofileoncase.git
cv en autofileoncase
```
## Usage
To set up the Case Types and Activity Types that should be automatically filed, navigate to **Administer -> CiviCase -> Auto File Activities Settings**.
## Known Issues
(_ FIXME _)
<?php
// AUTO-GENERATED FILE -- Civix may overwrite any changes made to this file
/**
* The ExtensionUtil class provides small stubs for accessing resources of this
* extension.
*/
class CRM_Autofileoncase_ExtensionUtil {
const SHORT_NAME = "autofileoncase";
const LONG_NAME = "cc.tadpole.autofileoncase";
const CLASS_PREFIX = "CRM_Autofileoncase";
/**
* Translate a string using the extension's domain.
*
* If the extension doesn't have a specific translation
* for the string, fallback to the default translations.
*
* @param string $text
* Canonical message text (generally en_US).
* @param array $params
* @return string
* Translated text.
* @see ts
*/
public static function ts($text, $params = array()) {
if (!array_key_exists('domain', $params)) {
$params['domain'] = array(self::LONG_NAME, NULL);
}
return ts($text, $params);
}
/**
* Get the URL of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: 'http://example.org/sites/default/ext/org.example.foo'.
* Ex: 'http://example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function url($file = NULL) {
if ($file === NULL) {
return rtrim(CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME), '/');
}
return CRM_Core_Resources::singleton()->getUrl(self::LONG_NAME, $file);
}
/**
* Get the path of a resource file (in this extension).
*
* @param string|NULL $file
* Ex: NULL.
* Ex: 'css/foo.css'.
* @return string
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo'.
* Ex: '/var/www/example.org/sites/default/ext/org.example.foo/css/foo.css'.
*/
public static function path($file = NULL) {
// return CRM_Core_Resources::singleton()->getPath(self::LONG_NAME, $file);
return __DIR__ . ($file === NULL ? '' : (DIRECTORY_SEPARATOR . $file));
}
/**
* Get the name of a class within this extension.
*
* @param string $suffix
* Ex: 'Page_HelloWorld' or 'Page\\HelloWorld'.
* @return string
* Ex: 'CRM_Foo_Page_HelloWorld'.
*/
public static function findClass($suffix) {
return self::CLASS_PREFIX . '_' . str_replace('\\', '_', $suffix);
}
}
use CRM_Autofileoncase_ExtensionUtil as E;
/**
* (Delegated) Implements hook_civicrm_config().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_config
*/
function _autofileoncase_civix_civicrm_config(&$config = NULL) {
static $configured = FALSE;
if ($configured) {
return;
}
$configured = TRUE;
$template =& CRM_Core_Smarty::singleton();
$extRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR;
$extDir = $extRoot . 'templates';
if (is_array($template->template_dir)) {
array_unshift($template->template_dir, $extDir);
}
else {
$template->template_dir = array($extDir, $template->template_dir);
}
$include_path = $extRoot . PATH_SEPARATOR . get_include_path();
set_include_path($include_path);
}
/**
* (Delegated) Implements hook_civicrm_xmlMenu().
*
* @param $files array(string)
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_xmlMenu
*/
function _autofileoncase_civix_civicrm_xmlMenu(&$files) {
foreach (_autofileoncase_civix_glob(__DIR__ . '/xml/Menu/*.xml') as $file) {
$files[] = $file;
}
}
/**
* Implements hook_civicrm_install().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
*/
function _autofileoncase_civix_civicrm_install() {
_autofileoncase_civix_civicrm_config();
if ($upgrader = _autofileoncase_civix_upgrader()) {
$upgrader->onInstall();
}
}
/**
* Implements hook_civicrm_postInstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_postInstall
*/
function _autofileoncase_civix_civicrm_postInstall() {
_autofileoncase_civix_civicrm_config();
if ($upgrader = _autofileoncase_civix_upgrader()) {
if (is_callable(array($upgrader, 'onPostInstall'))) {
$upgrader->onPostInstall();
}
}
}
/**
* Implements hook_civicrm_uninstall().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
*/
function _autofileoncase_civix_civicrm_uninstall() {
_autofileoncase_civix_civicrm_config();
if ($upgrader = _autofileoncase_civix_upgrader()) {
$upgrader->onUninstall();
}
}
/**
* (Delegated) Implements hook_civicrm_enable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
*/
function _autofileoncase_civix_civicrm_enable() {
_autofileoncase_civix_civicrm_config();
if ($upgrader = _autofileoncase_civix_upgrader()) {
if (is_callable(array($upgrader, 'onEnable'))) {
$upgrader->onEnable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_disable().
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
* @return mixed
*/
function _autofileoncase_civix_civicrm_disable() {
_autofileoncase_civix_civicrm_config();
if ($upgrader = _autofileoncase_civix_upgrader()) {
if (is_callable(array($upgrader, 'onDisable'))) {
$upgrader->onDisable();
}
}
}
/**
* (Delegated) Implements hook_civicrm_upgrade().
*
* @param $op string, the type of operation being performed; 'check' or 'enqueue'
* @param $queue CRM_Queue_Queue, (for 'enqueue') the modifiable list of pending up upgrade tasks
*
* @return mixed based on op. for 'check', returns array(boolean) (TRUE if upgrades are pending)
* for 'enqueue', returns void
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_upgrade
*/
function _autofileoncase_civix_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
if ($upgrader = _autofileoncase_civix_upgrader()) {
return $upgrader->onUpgrade($op, $queue);
}
}
/**
* @return CRM_Autofileoncase_Upgrader
*/
function _autofileoncase_civix_upgrader() {
if (!file_exists(__DIR__ . '/CRM/Autofileoncase/Upgrader.php')) {
return NULL;
}
else {
return CRM_Autofileoncase_Upgrader_Base::instance();
}
}
/**
* Search directory tree for files which match a glob pattern
*
* Note: Dot-directories (like "..", ".git", or ".svn") will be ignored.
* Note: In Civi 4.3+, delegate to CRM_Utils_File::findFiles()
*
* @param $dir string, base dir
* @param $pattern string, glob pattern, eg "*.txt"
* @return array(string)
*/
function _autofileoncase_civix_find_files($dir, $pattern) {
if (is_callable(array('CRM_Utils_File', 'findFiles'))) {
return CRM_Utils_File::findFiles($dir, $pattern);
}
$todos = array($dir);
$result = array();
while (!empty($todos)) {
$subdir = array_shift($todos);
foreach (_autofileoncase_civix_glob("$subdir/$pattern") as $match) {
if (!is_dir($match)) {
$result[] = $match;
}
}
if ($dh = opendir($subdir)) {
while (FALSE !== ($entry = readdir($dh))) {
$path = $subdir . DIRECTORY_SEPARATOR . $entry;
if ($entry{0} == '.') {
}
elseif (is_dir($path)) {
$todos[] = $path;
}
}
closedir($dh);
}
}
return $result;
}
/**
* (Delegated) Implements hook_civicrm_managed().
*
* Find any *.mgd.php files, merge their content, and return.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_managed
*/
function _autofileoncase_civix_civicrm_managed(&$entities) {
$mgdFiles = _autofileoncase_civix_find_files(__DIR__, '*.mgd.php');
sort($mgdFiles);
foreach ($mgdFiles as $file) {
$es = include $file;
foreach ($es as $e) {
if (empty($e['module'])) {
$e['module'] = E::LONG_NAME;
}
if (empty($e['params']['version'])) {
$e['params']['version'] = '3';
}
$entities[] = $e;
}
}
}
/**
* (Delegated) Implements hook_civicrm_caseTypes().
*
* Find any and return any files matching "xml/case/*.xml"
*
* Note: This hook only runs in CiviCRM 4.4+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_caseTypes
*/
function _autofileoncase_civix_civicrm_caseTypes(&$caseTypes) {
if (!is_dir(__DIR__ . '/xml/case')) {
return;
}
foreach (_autofileoncase_civix_glob(__DIR__ . '/xml/case/*.xml') as $file) {
$name = preg_replace('/\.xml$/', '', basename($file));
if ($name != CRM_Case_XMLProcessor::mungeCaseType($name)) {
$errorMessage = sprintf("Case-type file name is malformed (%s vs %s)", $name, CRM_Case_XMLProcessor::mungeCaseType($name));
CRM_Core_Error::fatal($errorMessage);
// throw new CRM_Core_Exception($errorMessage);
}
$caseTypes[$name] = array(
'module' => E::LONG_NAME,
'name' => $name,
'file' => $file,
);
}
}
/**
* (Delegated) Implements hook_civicrm_angularModules().
*
* Find any and return any files matching "ang/*.ang.php"
*
* Note: This hook only runs in CiviCRM 4.5+.
*
* @link http://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_angularModules
*/
function _autofileoncase_civix_civicrm_angularModules(&$angularModules) {
if (!is_dir(__DIR__ . '/ang')) {
return;
}
$files = _autofileoncase_civix_glob(__DIR__ . '/ang/*.ang.php');
foreach ($files as $file) {
$name = preg_replace(':\.ang\.php$:', '', basename($file));
$module = include $file;
if (empty($module['ext'])) {
$module['ext'] = E::LONG_NAME;
}
$angularModules[$name] = $module;
}
}
/**
* Glob wrapper which is guaranteed to return an array.
*
* The documentation for glob() says, "On some systems it is impossible to
* distinguish between empty match and an error." Anecdotally, the return
* result for an empty match is sometimes array() and sometimes FALSE.
* This wrapper provides consistency.
*
* @link http://php.net/glob
* @param string $pattern
* @return array, possibly empty
*/
function _autofileoncase_civix_glob($pattern) {
$result = glob($pattern);
return is_array($result) ? $result : array();
}
/**
* Inserts a navigation menu item at a given place in the hierarchy.
*
* @param array $menu - menu hierarchy