forked from eileenmcnaughton/civicrm_entity
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcivicrm_entity_controller.inc
158 lines (146 loc) · 5.55 KB
/
civicrm_entity_controller.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?php
/**
* Entity Controller for CiviCRM entities
*/
class CivicrmEntityController extends EntityAPIController {
/**
* Implements DrupalEntityControllerInterface::load().
*
* @param array $ids
* @param array $conditions
*
* @return array
*/
public function load($ids = array(), $conditions = array()) {
$entities = array();
if (!civicrm_initialize(TRUE)) {
return;
}
// Not sure about revisioning out at this stage - I don't know if
// it could have any later use. Revisions are not statically
// cached, and require a different query to other conditions, so
// separate the revision id into its own variable.
if ($this->revisionKey && isset($conditions[$this->revisionKey])) {
$revision_id = $conditions[$this->revisionKey];
unset($conditions[$this->revisionKey]);
}
else {
$revision_id = FALSE;
}
/*
* this seems 'harmless' - but not necessarily relevant?
* ie. deals with caching on the drupal side
*/
// Create a new variable which is either a prepared version of the $ids
// array for later comparison with the entity cache, or FALSE if no $ids
// were passed. The $ids array is reduced as items are loaded from cache,
// and we need to know if it's empty for this reason to avoid querying the
// database when all requested entities are loaded from cache.
$passed_ids = !empty($ids) ? array_flip((array) $ids) : FALSE;
// Try to load entities from the static cache, if the entity type supports
// static caching.
if ($this->cache && !$revision_id) {
$entities += $this->cacheGet($ids, $conditions);
// If any entities were loaded, remove them from the ids still to load.
if ($passed_ids) {
$ids = array_keys(array_diff_key($passed_ids, $entities));
}
}
/*
* OK - here is where we will actually 'Do' something that is Civi-Specific
* In drupal land $ids = FALSE would load all - let's only do specific
*/
// Load any remaining entities from the database. This is the case if $ids
// is set to FALSE (so we load all entities), if there are any ids left to
// load, if loading a revision, or if $conditions was passed without $ids.
if ($ids === FALSE || $ids || $revision_id || ($conditions && !$passed_ids)) {
// Build the query.
try {
if ($conditions) {
$civicrm_entities = civicrm_api3($this->entityInfo['description'], 'get', $conditions);
}
foreach ($ids as $id) {
// we can't rely on civicrm api accepting the 'IN' => array(1,5,6) for all entities
$civicrm_entities = civicrm_api3($this->entityInfo['description'], 'get', array('id' => $id));
if ($civicrm_entities['count']) {
foreach ($civicrm_entities['values'] as $id => $civicrm_entity) {
// @TODO improve this casting.
$queried_entities[$id] = new CivicrmEntity($civicrm_entity, $this->entityType);
}
}
}
}
catch (Exception $e) {
watchdog('civicrm_entity', 'Failed to load ' . $this->entityInfo['description'], $conditions);
}
}
// Pass all entities loaded from the database through $this->attachLoad(),
// which attaches fields (if supported by the entity type) and calls the
// entity type specific load callback, for example hook_node_load().
if (!empty($queried_entities)) {
$this->attachLoad($queried_entities, $revision_id);
$entities += $queried_entities;
}
if ($this->cache) {
// Add entities to the cache if we are not loading a revision.
if (!empty($queried_entities) && !$revision_id) {
$this->cacheSet($queried_entities);
}
}
// Ensure that the returned array is ordered the same as the original
// $ids array if this was passed in and remove any invalid ids.
if ($passed_ids) {
// Remove any invalid ids from the array.
$passed_ids = array_intersect_key($passed_ids, $entities);
foreach ($entities as $entity) {
$passed_ids[$entity->{$this->idKey}] = $entity;
}
$entities = $passed_ids;
}
return $entities;
}
/**
* Implements EntityAPIControllerInterface.
*
* @param $entity
* @param DatabaseTransaction $transaction
* Optionally a DatabaseTransaction object to use. Allows
* overrides to pass in their transaction object.
*
* @throws Exception
*/
public function save($entity, DatabaseTransaction $transaction = NULL) {
if (!civicrm_initialize()) {
throw new Exception('civicrm inaccessible');
}
$params = (array)$entity;
unset($params['is_new']);
$params['version'] = 3;
$params['sequential'] = 1;
try {
$entity->is_new = !empty($entity->is_new) || empty($entity->{$this->idKey});
// @TODO should we call this hook when drupal saves (as opposed
// to Civi?) ditto insert, update.
$this->invoke('presave', $entity);
if ($entity->is_new) {
$result = civicrm_api(substr($this->entityType, 8), 'create', $params);
// $this->invoke('insert', $entity);
}
else {
$result = civicrm_api(substr($this->entityType, 8), 'update', $params);
// $this->invoke('update', $entity);
}
unset($entity->is_new);
unset($entity->is_new_revision);
unset($entity->original);
if (!civicrm_error($result)) {
return (object) $result['values'][0];
}
throw new Exception($result['error_message']);
}
catch (Exception $e) {
watchdog_exception($this->entityType, $e);
throw $e;
}
}
}