Skip to content
Snippets Groups Projects
Commit 0fe491cb authored by totten's avatar totten Committed by GitHub
Browse files

Merge pull request #171 from totten/master-symfony-ev

CRM-19813 - Document support for hooks via Symfony
parents 9a18f1c5 316fc894
No related branches found
No related tags found
No related merge requests found
...@@ -6,11 +6,11 @@ This hook is called while preparing a profile form. ...@@ -6,11 +6,11 @@ This hook is called while preparing a profile form.
## Definition ## Definition
buildProfile($name) buildProfile($profileName)
## Parameters ## Parameters
- $name - the (machine readable) name of the profile. - $profileName - the (machine readable) name of the profile.
## Returns ## Returns
...@@ -21,9 +21,9 @@ immediately obvious how I can use this. I could do something like this: ...@@ -21,9 +21,9 @@ immediately obvious how I can use this. I could do something like this:
function myext_civicrm_buildProfile($name) { function myext_civicrm_buildProfile($profileName) {
if ($name === 'MyTargetedProfile) { if ($profileName === 'MyTargetedProfile) {
CRM_Core_Resources::singleton()->addScriptFile('org.example.myext', 'some/fancy.js', 100); CRM_Core_Resources::singleton()->addScriptFile('org.example.myext', 'some/fancy.js', 100);
......
...@@ -18,7 +18,7 @@ the list of contacts to display. ...@@ -18,7 +18,7 @@ the list of contacts to display.
## Definition ## Definition
hook_civicrm_contactListQuery( &$query, $name, $context, $id ) hook_civicrm_contactListQuery( &$query, $queryText, $context, $id )
## Parameters ## Parameters
...@@ -29,7 +29,7 @@ the list of contacts to display. ...@@ -29,7 +29,7 @@ the list of contacts to display.
- the contact 'data' to display in the autocomplete dropdown - the contact 'data' to display in the autocomplete dropdown
(usually contact.sort_name - aliased as 'data') (usually contact.sort_name - aliased as 'data')
- the contact IDs - the contact IDs
- $name - the name string to execute the query against (this is the - $queryText - the name string to execute the query against (this is the
value being typed in by the user) value being typed in by the user)
- $context - the context in which this ajax call is being made (for - $context - the context in which this ajax call is being made (for
example: 'customfield', 'caseview') example: 'customfield', 'caseview')
...@@ -56,7 +56,7 @@ This example limits contacts in my contact reference field lookup ...@@ -56,7 +56,7 @@ This example limits contacts in my contact reference field lookup
$query = " $query = "
SELECT c.sort_name as data, c.id SELECT c.sort_name as data, c.id
FROM civicrm_contact c, civicrm_group_contact cg FROM civicrm_contact c, civicrm_group_contact cg
WHERE c.sort_name LIKE '$name%' WHERE c.sort_name LIKE '$queryText%'
AND cg.group_id IN ( 5 ) AND cg.group_id IN ( 5 )
AND cg.contact_id = c.id AND cg.contact_id = c.id
AND cg.status = 'Added' AND cg.status = 'Added'
......
...@@ -12,13 +12,13 @@ hook to add/remove options from the option group. ...@@ -12,13 +12,13 @@ hook to add/remove options from the option group.
## Definition ## Definition
```php ```php
hook_civicrm_optionValues(&$options, $name) hook_civicrm_optionValues(&$options, $groupName)
``` ```
## Parameters ## Parameters
- array `$options` - the current set of options - array `$options` - the current set of options
- string `$name` - the name of the option group - string `$groupName` - the name of the option group
## Returns ## Returns
......
...@@ -6,11 +6,11 @@ This hook is called processing a valid profile form submission (e.g. for "civicr ...@@ -6,11 +6,11 @@ This hook is called processing a valid profile form submission (e.g. for "civicr
## Definition ## Definition
processProfile($name) processProfile($profileName)
## Parameters ## Parameters
- $name - the (machine readable) name of the profile. - $profileName - the (machine readable) name of the profile.
!!! Tip !!! Tip
In SQL, this corresponds to the "name" column of table "civicrm_uf_group" In SQL, this corresponds to the "name" column of table "civicrm_uf_group"
......
...@@ -7,11 +7,11 @@ profile). ...@@ -7,11 +7,11 @@ profile).
## Definition ## Definition
searchProfile($name) searchProfile($profileName)
## Parameters ## Parameters
- $name - the (machine readable) name of the profile. - $profileName - the (machine readable) name of the profile.
## Returns ## Returns
......
...@@ -6,11 +6,11 @@ This hook is called while validating a profile form submission. ...@@ -6,11 +6,11 @@ This hook is called while validating a profile form submission.
## Definition ## Definition
validateProfile($name) validateProfile($profileName)
## Parameters ## Parameters
- $name - the (machine readable) name of the profile. - $profileName - the (machine readable) name of the profile.
## Returns ## Returns
......
...@@ -6,11 +6,11 @@ This hook is called while preparing a read-only profile screen. ...@@ -6,11 +6,11 @@ This hook is called while preparing a read-only profile screen.
## Definition ## Definition
viewProfile($name) viewProfile($profileName)
## Parameters ## Parameters
- $name - the (machine readable) name of the profile. - $profileName - the (machine readable) name of the profile.
## Returns ## Returns
......
## Overview
The [__Symfony EventDispatcher__](http://symfony.com/components/EventDispatcher) is an
event library used by several PHP applications and frameworks. For example,
Symfony SE, Drupal 8, Magento, Laravel, CiviCRM, and many others support
`EventDispatcher`. It provides a common mechanism for dispatching and listening
to events.
In CiviCRM v4.7.19+, you can use Symfony `EventDispatcher` with hooks.
```php
Civi::dispatcher()->addListener('hook_civicrm_EXAMPLE', $callback, $priority);
```
Using `EventDispatcher` is useful if you need more advanced features, such as:
* Setting the priority of an event-listener
* Registering an object-oriented event-listener
* Registering a dynamic, on-the-fly event-listener
* Registering multiple listeners for the same event
* Registering for internal/unpublished events
For a general introduction or background on `EventDispatcher`, consult the [Symfony documentation](http://symfony.com/doc/2.7/components/event_dispatcher.html).
## Example: `Civi::dispatcher()`
In this case, we have a CiviCRM extension or Drupal module named `example`.
During the system initialization, we lookup the `EventDispatcher`, call
`addListener()`, and listen for `hook_civicrm_alterContent`.
```php
function example_civicrm_config(&$config) {
if (isset(Civi::$statics[__FUNCTION__])) { return; }
Civi::$statics[__FUNCTION__] = 1;
Civi::dispatcher()->addListener('hook_civicrm_alterContent', '_example_say_hello');
}
function _example_say_hello($event) {
$event->content = 'hello ' . $event->content;
}
```
!!! tip "Using the `$event` object"
Hook parameters are passed as an object, `$event`.
For example, [`hook_civicrm_alterContent`](/hooks/hook_civicrm_alterContent/)
has the parameters `(&$content, $context, $tplName, &$object)`.
You can access the data as `$event->content`, `$event->context`, `$event->tplName`, and `$event->object`.
!!! tip "Using `hook_civicrm_config`"
In some environments, `hook_civicrm_config` runs multiple times. The flag
`Civi::$statics[__FUNCTION__]` prevents duplicate listeners.
## Example: `Container::findDefinition()`
In this case, we have a CiviCRM extension or Drupal module named `example`.
We lookup the defintion of the `dispatcher` service and amend it.
```php
function example_civicrm_container($container) {
$container->findDefinition('dispatcher')
->addMethodCall('addListener', array('hook_civicrm_alterContent', '_example_say_hello'));
}
function _example_say_hello($event) {
$event->content = 'hello ' . $event->content;
}
```
<!--
TODO: an example using a container-service and tag. See "Registering Event Listeners
in the Service Container" from http://symfony.com/doc/2.7/components/event_dispatcher.html
-->
## Events
CiviCRM broadcasts many different events through the `EventDispatcher`. These
events fall into two categories:
* __External Events/Hooks__ (v4.7.19+): These have a prefix `hook_civicrm_*`. They extend
the class [`GenericHookEvent`](https://github.com/civicrm/civicrm-core/blob/master/Civi/Core/Event/GenericHookEvent.php)
(which, in turn, extends [`Event`](http://api.symfony.com/2.7/Symfony/Component/EventDispatcher/Event.html)).
Hooks are simulcast across `EventDispatcher` as well as CMS-specific event systems.
* __Internal Events__ (v4.5.0+): These have a prefix `civi.*`. They extend
the class [`Event`](http://api.symfony.com/2.7/Symfony/Component/EventDispatcher/Event.html).
They are *only* broadcast via `EventDispatcher` (**not** CMS-specific event systems).
You can recognize these events by their naming convention. Compare:
```php
// Listen to a hook. Note the prefix, "hook_civicrm_*".
Civi::dispatcher()->addListener('hook_civicrm_alterContent', $callback, $priority);
// Listen to an internal event. Note the prefix, "civi.*".
Civi::dispatcher()->addListener('civi.api.resolve', $callback, $priority);
```
## Methods
The `EventDispatcher` has several different methods for registering a
listener. Our examples have focused on the simplest one, `addListener()`,
but the Symfony documentation describes other methods (`addSubscriber()`,
`addListenerService()`, and `addSubscriberService()`). See also:
* [Symfony EventDispatcher](http://symfony.com/doc/2.7/components/event_dispatcher.html)
* [Symfony ContainerAwareEventDispatcher](http://symfony.com/doc/2.7/components/event_dispatcher/container_aware_dispatcher.html)
!!! tip "Using `addListener()`"
When calling `addListener()`, you _can_ pass any [PHP callable](http://php.net/manual/en/language.types.callable.php).
However, _in practice_, the safest bet is to pass a string (function-name) or array
(class-name, function-name). Other formats may not work with the
[container-cache](http://symfony.com/doc/2.7/components/dependency_injection/compilation.html).
## History
* _CiviCRM v4.5.0_: Introduced Symfony EventDispatcher for internal use (within `civicrm-core`). For example,
APIv3 dispatches the events `civi.api.resolve` and `civi.api.authorize` while executing an API call.
* _CiviCRM v4.7.0_: Introduced `hook_civicrm_container`.
* _CiviCRM v4.7.0_: Integrated the Symfony `Container` and `EventDispatcher`.
* _CiviCRM v4.7.19_: Integrated `hook_civicrm_*` with the Symfony `EventDispatcher`.
* _CiviCRM v4.7.19_: Added the `Civi::dispatcher()` function.
## Limitations
* _Boot-critical hooks_: `hook_civicrm_config`, `hook_civicrm_container`, and `hook_civicrm_entityTypes`
are fired during the bootstrap process -- before the Symfony subsystems are fully online. Consequently,
you may not be able to listen for these hooks.
* _Opaque CMS listeners_: Most hooks are dispatched through `EventDispatcher` as well as the traditional
hook systems for Drupal modules, Joomla plugins, WordPress plugins, and/or CiviCRM extensions.
This is accomplished by _daisy-chaining_: first, the event is dispatched with `EventDispatcher`; then, the
listener `CiviEventDispatcher::delegateToUF()` passes the event down to the other systems.
If you inspect `EventDispatcher`, there will be one listener (`delegateToUF()`)
which represents _all_ CMS-based listeners.
...@@ -86,6 +86,7 @@ pages: ...@@ -86,6 +86,7 @@ pages:
- Hooks: - Hooks:
- Using hooks: hooks.md # page-tree = NEED_PAGE_MOVE to /hooks/usage.md - Using hooks: hooks.md # page-tree = NEED_PAGE_MOVE to /hooks/usage.md
- Setup: - Setup:
- Hooks with Symfony: hooks/setup/symfony.md
- Hooks with Joomla: hooks/setup/joomla.md - Hooks with Joomla: hooks/setup/joomla.md
- Hooks with Drupal: hooks/setup/drupal.md - Hooks with Drupal: hooks/setup/drupal.md
- Hooks with Wordpress: hooks/setup/wordpress.md - Hooks with Wordpress: hooks/setup/wordpress.md
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment