<?php
/*
+--------------------------------------------------------------------+
- | CiviCRM version 4.6 |
+ | CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2015 |
+--------------------------------------------------------------------+
*
* @package CiviCRM_Hook
* @copyright CiviCRM LLC (c) 2004-2015
- * $Id: $
- *
*/
abstract class CRM_Utils_Hook {
// by default - place content below existing content
const SUMMARY_BELOW = 1;
- // pace hook content above
+ // place hook content above
const SUMMARY_ABOVE = 2;
- // create your own summarys
+ // create your own summaries
const SUMMARY_REPLACE = 3;
static $_nullObject = NULL;
*/
private $commonCiviModules = array();
+ /**
+ * @var CRM_Utils_Cache_Interface
+ */
+ protected $cache;
+
/**
* Constructor and getter for the singleton instance.
*
if (self::$_singleton == NULL || $fresh) {
$config = CRM_Core_Config::singleton();
$class = $config->userHookClass;
- require_once str_replace('_', DIRECTORY_SEPARATOR, $config->userHookClass) . '.php';
self::$_singleton = new $class();
}
return self::$_singleton;
}
+ public function __construct() {
+ $this->cache = CRM_Utils_Cache::create(array(
+ 'name' => 'hooks',
+ 'type' => array('ArrayCache'),
+ 'prefetch' => 1,
+ ));
+ }
+
/**
* Invoke hooks.
*
// to reproduce the issue are pretty intricate.
$result = array();
- if ($civiModules !== NULL) {
- foreach ($civiModules as $module) {
- $fnName = "{$module}_{$fnSuffix}";
- if (function_exists($fnName)) {
- $fResult = array();
- switch ($numParams) {
- case 0:
- $fResult = $fnName();
- break;
-
- case 1:
- $fResult = $fnName($arg1);
- break;
-
- case 2:
- $fResult = $fnName($arg1, $arg2);
- break;
-
- case 3:
- $fResult = $fnName($arg1, $arg2, $arg3);
- break;
-
- case 4:
- $fResult = $fnName($arg1, $arg2, $arg3, $arg4);
- break;
-
- case 5:
- $fResult = $fnName($arg1, $arg2, $arg3, $arg4, $arg5);
- break;
-
- case 6:
- $fResult = $fnName($arg1, $arg2, $arg3, $arg4, $arg5, $arg6);
- break;
-
- default:
- CRM_Core_Error::fatal(ts('Invalid hook invocation'));
- break;
- }
-
- if (!empty($fResult) &&
- is_array($fResult)
- ) {
- $result = array_merge($result, $fResult);
+ $fnNames = $this->cache->get($fnSuffix);
+ if (!is_array($fnNames)) {
+ $fnNames = array();
+ if ($civiModules !== NULL) {
+ foreach ($civiModules as $module) {
+ $fnName = "{$module}_{$fnSuffix}";
+ if (function_exists($fnName)) {
+ $fnNames[] = $fnName;
}
}
+ $this->cache->set($fnSuffix, $fnNames);
+ }
+ }
+
+ foreach ($fnNames as $fnName) {
+ $fResult = array();
+ switch ($numParams) {
+ case 0:
+ $fResult = $fnName();
+ break;
+
+ case 1:
+ $fResult = $fnName($arg1);
+ break;
+
+ case 2:
+ $fResult = $fnName($arg1, $arg2);
+ break;
+
+ case 3:
+ $fResult = $fnName($arg1, $arg2, $arg3);
+ break;
+
+ case 4:
+ $fResult = $fnName($arg1, $arg2, $arg3, $arg4);
+ break;
+
+ case 5:
+ $fResult = $fnName($arg1, $arg2, $arg3, $arg4, $arg5);
+ break;
+
+ case 6:
+ $fResult = $fnName($arg1, $arg2, $arg3, $arg4, $arg5, $arg6);
+ break;
+
+ default:
+ CRM_Core_Error::fatal(ts('Invalid hook invocation'));
+ break;
+ }
+
+ if (!empty($fResult) &&
+ is_array($fResult)
+ ) {
+ $result = array_merge($result, $fResult);
}
}
*/
public static function pre($op, $objectName, $id, &$params) {
$event = new \Civi\Core\Event\PreEvent($op, $objectName, $id, $params);
- \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("hook_civicrm_pre", $event);
- \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("hook_civicrm_pre::$objectName", $event);
+ \Civi::service('dispatcher')->dispatch("hook_civicrm_pre", $event);
+ \Civi::service('dispatcher')->dispatch("hook_civicrm_pre::$objectName", $event);
return self::singleton()
->invoke(4, $op, $objectName, $id, $params, self::$_nullObject, self::$_nullObject, 'civicrm_pre');
}
*/
public static function post($op, $objectName, $objectId, &$objectRef) {
$event = new \Civi\Core\Event\PostEvent($op, $objectName, $objectId, $objectRef);
- \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("hook_civicrm_post", $event);
- \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("hook_civicrm_post::$objectName", $event);
+ \Civi::service('dispatcher')->dispatch("hook_civicrm_post", $event);
+ \Civi::service('dispatcher')->dispatch("hook_civicrm_post::$objectName", $event);
return self::singleton()
->invoke(4, $op, $objectName, $objectId, $objectRef, self::$_nullObject, self::$_nullObject, 'civicrm_post');
}
);
}
- /**
- * This hook is invoked during all CiviCRM form validation. An array of errors
- * detected is returned. Else we assume validation succeeded.
- *
- * @param string $formName
- * The name of the form.
- * @param array &$fields the POST parameters as filtered by QF
- * @param array &$files the FILES parameters as sent in by POST
- * @param array &$form the form object
- *
- * @return mixed
- * formRule hooks return a boolean or
- * an array of error messages which display a QF Error
- */
- public static function validate($formName, &$fields, &$files, &$form) {
- return self::singleton()
- ->invoke(4, $formName, $fields, $files, $form, self::$_nullObject, self::$_nullObject, 'civicrm_validate');
- }
-
/**
* This hook is invoked during all CiviCRM form validation. An array of errors
* detected is returned. Else we assume validation succeeded.
* The contactID for whom the dashboard is being rendered.
*
* @return null
+ * @deprecated Use tabset() instead.
*/
public static function tabs(&$tabs, $contactID) {
return self::singleton()->invoke(2, $tabs, $contactID,
}
/**
- * This hook is called when CiviCRM needs to edit/display a custom field with options (select, radio, checkbox,
- * adv multiselect)
+ * This hook is called when CiviCRM needs to edit/display a custom field with options
+ *
+ * @deprecated in favor of hook_civicrm_fieldOptions
*
* @param int $customFieldID
* The custom field ID.
* to be careful to not overwrite the array.
* Only add/edit/remove the specific field options you intend to affect.
* @param bool $detailedFormat
- * If true,.
- * the options are in an ID => array ( 'id' => ID, 'label' => label, 'value' => value ) format
+ * If true, the options are in an ID => array ( 'id' => ID, 'label' => label, 'value' => value ) format
* @param array $selectAttributes
* Contain select attribute(s) if any.
*
);
}
+ /**
+ * Hook for modifying field options
+ *
+ * @param string $entity
+ * @param string $field
+ * @param array $options
+ * @param array $params
+ *
+ * @return mixed
+ */
+ public static function fieldOptions($entity, $field, &$options, $params) {
+ return self::singleton()->invoke(5, $entity, $field, $options, $params,
+ self::$_nullObject, self::$_nullObject,
+ 'civicrm_fieldOptions'
+ );
+ }
+
/**
*
* This hook is called to display the list of actions allowed after doing a search.
* @param array $tasks
* The current set of tasks for that custom field.
* You can add/remove existing tasks.
- * Each task needs to have a title (eg 'title' => ts( 'Add Contacts to Group')) and a class
+ * Each task needs to have a title (eg 'title' => ts( 'Group - add contacts')) and a class
* (eg 'class' => 'CRM_Contact_Form_Task_AddToGroup').
* Optional result (boolean) may also be provided. Class can be an array of classes (not sure what that does :( ).
* The key for new Task(s) should not conflict with the keys for core tasks of that $objectType, which can be
);
}
+ /**
+ * This hook is called after getting the content of the mail and before tokenizing it.
+ *
+ * @param array $content
+ * Array fields include: html, text, subject
+ *
+ * @return mixed
+ */
+ public static function alterMailContent(&$content) {
+ return self::singleton()->invoke(1, $content,
+ self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject,
+ 'civicrm_alterMailContent'
+ );
+ }
+
/**
* This hook is called when rendering the Manage Case screen.
*
/**
* This hooks allows to change option values.
*
+ * @deprecated in favor of hook_civicrm_fieldOptions
+ *
* @param array $options
* Associated array of option values / id
* @param string $name
* fieldHeaders - field headers
* fields - import fields
*
- * @return void
+ * @return mixed
*/
public static function import($object, $usage, &$objectRef, &$params) {
return self::singleton()->invoke(4, $object, $usage, $objectRef, $params,
* @param array $selector
* the selector object. Allows you access to the context of the search
*
- * @return void
- * modify the header and values object to pass the data u need
+ * @return mixed
+ * modify the header and values object to pass the data you need
*/
public static function searchColumns($objectName, &$headers, &$rows, &$selector) {
return self::singleton()->invoke(4, $objectName, $headers, $rows, $selector,
* float $x x position in user units
* float $y y position in user units
* boolean $reseth if true reset the last cell height (default true).
- * int $stretch stretch carachter mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if
+ * int $stretch stretch character mode: <ul><li>0 = disabled</li><li>1 = horizontal scaling only if
* necessary</li><li>2 = forced horizontal scaling</li><li>3 = character spacing only if
* necessary</li><li>4 = forced character spacing</li></ul>
* boolean $ishtml set to true if $txt is HTML content (default = false).
);
}
+ /**
+ * This hook is called when a CiviMail mailing has completed
+ *
+ * @param int $mailingId
+ * Mailing ID
+ *
+ * @return mixed
+ */
+ public static function postMailing($mailingId) {
+ return self::singleton()->invoke(1, $mailingId,
+ self::$_nullObject, self::$_nullObject,
+ self::$_nullObject, self::$_nullObject, self::$_nullObject,
+ 'civicrm_postMailing'
+ );
+ }
+
/**
* This hook is called when Settings specifications are loaded.
*
self::singleton()
->invoke(2, $exception, $request, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, 'civicrm_unhandled_exception');
// == 4.4 ==
- //$event = new stdClass();
- //$event->exception = $exception;
- //CRM_Core_LegacyErrorHandler::handleException($event);
+ // $event = new stdClass();
+ // $event->exception = $exception;
+ // CRM_Core_LegacyErrorHandler::handleException($event);
// == 4.5+ ==
$event = new \Civi\Core\Event\UnhandledExceptionEvent($exception, self::$_nullObject);
- \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("hook_civicrm_unhandled_exception", $event);
+ \Civi::service('dispatcher')->dispatch("hook_civicrm_unhandled_exception", $event);
}
/**
* @return mixed
* @see Mail::factory
*/
- public static function alterMail(&$mailer, $driver, $params) {
+ public static function alterMailer(&$mailer, $driver, $params) {
return self::singleton()
->invoke(3, $mailer, $driver, $params, self::$_nullObject, self::$_nullObject, self::$_nullObject, 'civicrm_alterMailer');
}
+ /**
+ * Deprecated: Misnamed version of alterMailer(). Remove post-4.7.x.
+ * Modify or replace the Mailer object used for outgoing mail.
+ *
+ * @param object $mailer
+ * The default mailer produced by normal configuration; a PEAR "Mail" class (like those returned by Mail::factory)
+ * @param string $driver
+ * The type of the default mailer (eg "smtp", "sendmail", "mock", "CRM_Mailing_BAO_Spool")
+ * @param array $params
+ * The default mailer config options
+ *
+ * @return mixed
+ * @see Mail::factory
+ * @deprecated
+ */
+ public static function alterMail(&$mailer, $driver, $params) {
+ return CRM_Utils_Hook::alterMailer($mailer, $driver, $params);
+ }
+
/**
* This hook is called while building the core search query,
* so hook implementers can provide their own query objects which alters/extends core search.
* @param int $otherCaseId
* @param bool $changeClient
*
- * @return void
+ * @return mixed
*/
public static function pre_case_merge($mainContactId, $mainCaseId = NULL, $otherContactId = NULL, $otherCaseId = NULL, $changeClient = FALSE) {
return self::singleton()
* @param int $otherCaseId
* @param bool $changeClient
*
- * @return void
+ * @return mixed
*/
public static function post_case_merge($mainContactId, $mainCaseId = NULL, $otherContactId = NULL, $otherCaseId = NULL, $changeClient = FALSE) {
return self::singleton()
*/
public static function caseChange(\Civi\CCase\Analyzer $analyzer) {
$event = new \Civi\CCase\Event\CaseChangeEvent($analyzer);
- \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("hook_civicrm_caseChange", $event);
+ \Civi::service('dispatcher')->dispatch("hook_civicrm_caseChange", $event);
self::singleton()->invoke(1, $analyzer,
self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject,
);
}
+ /**
+ * Modify the CiviCRM container - add new services, parameters, extensions, etc.
+ *
+ * @code
+ * use Symfony\Component\Config\Resource\FileResource;
+ * use Symfony\Component\DependencyInjection\Definition;
+ *
+ * function mymodule_civicrm_container($container) {
+ * $container->addResource(new FileResource(__FILE__));
+ * $container->setDefinition('mysvc', new Definition('My\Class', array()));
+ * }
+ * @endcode
+ *
+ * Tip: The container configuration will be compiled/cached. The default cache
+ * behavior is aggressive. When you first implement the hook, be sure to
+ * flush the cache. Additionally, you should relax caching during development.
+ * In `civicrm.settings.php`, set define('CIVICRM_CONTAINER_CACHE', 'auto').
+ *
+ * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+ * @see http://symfony.com/doc/current/components/dependency_injection/index.html
+ */
+ public static function container(\Symfony\Component\DependencyInjection\ContainerBuilder $container) {
+ self::singleton()->invoke(1, $container, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, 'civicrm_container');
+ }
+
/**
* @param array <CRM_Core_FileSearchInterface> $fileSearches
* @return mixed
);
}
+ /**
+ * Check system status.
+ *
+ * @param array $messages
+ * Array<CRM_Utils_Check_Message>. A list of messages regarding system status.
+ * @return mixed
+ */
+ public static function check(&$messages) {
+ return self::singleton()
+ ->invoke(1, $messages, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, 'civicrm_check');
+ }
+
/**
* This hook is called when a query string of the CSV Batch export is generated.
+ *
+ * @param string $query
+ *
+ * @return mixed
*/
public static function batchQuery(&$query) {
return self::singleton()->invoke(1, $query, self::$_nullObject,
/**
* This hook is called when the entries of the CSV Batch export are mapped.
+ *
+ * @param array $results
+ * @param array $items
+ *
+ * @return mixed
*/
public static function batchItems(&$results, &$items) {
return self::singleton()->invoke(2, $results, $items,