~fabiocbalbuquerque/sahana-agasti/web-services

« back to all changes in this revision

Viewing changes to apps/frontend/lib/util/agEntityAddressHelper.class.php

  • Committer: Chad Heuschober
  • Date: 2011-06-06 13:37:45 UTC
  • mfrom: (1.1.1244 trunk)
  • mto: This revision was merged to the branch mainline in revision 17.
  • Revision ID: chad.heuschober@mail.cuny.edu-20110606133745-850mdvnjtv392zta
Pulled in most recent batch of changes from the cuny sps trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
<?php
 
2
 
2
3
/**
3
4
 * Provides person name helper functions and inherits several methods and properties from the
4
5
 * EntityContactHelper.
15
16
 */
16
17
class agEntityAddressHelper extends agEntityContactHelper
17
18
{
 
19
 
18
20
  public    $agAddressHelper,
19
21
            $defaultIsPrimary = FALSE,
20
22
            $defaultIsStrType = FALSE;
21
 
 
22
23
  protected $_batchSizeModifier = 2,
23
 
            $_contactTableMetadata = array( 'table' => 'agEntityAddressContact',
 
24
            $_contactTableMetadata = array('table' => 'agEntityAddressContact',
24
25
                                            'method' => 'getEntityAddress',
25
26
                                            'type' => 'address_contact_type_id',
26
27
                                            'value' => 'address_id');
31
32
   */
32
33
  public function getAgAddressHelper()
33
34
  {
34
 
    if (! isset($this->agAddressHelper)) { $this->agAddressHelper = agAddressHelper::init() ; }
35
 
    return $this->agAddressHelper ;
 
35
    if (!isset($this->agAddressHelper)) {
 
36
      $this->agAddressHelper = agAddressHelper::init();
 
37
    }
 
38
    return $this->agAddressHelper;
36
39
  }
37
40
 
38
41
  /**
43
46
   * be returned as an ID value or its string equivalent.
44
47
   * @return Doctrine_Query An agDoctrineQuery object.
45
48
   */
46
 
  private function _getEntityAddressQuery($entityIds = NULL, $strType = NULL)
 
49
  private function _getEntityAddressQuery(array $entityIds = NULL, $strType = NULL)
47
50
  {
48
51
    // if no (null) ID's are passed, get the addressId's from the class property
49
 
    $entityIds = $this->getRecordIds($entityIds) ;
 
52
    $entityIds = $this->getRecordIds($entityIds);
50
53
 
51
54
    // if strType is not passed, get the default
52
 
    if (is_null($strType)) { $strType = $this->defaultIsStrType ; }
 
55
    if (is_null($strType)) {
 
56
      $strType = $this->defaultIsStrType;
 
57
    }
53
58
 
54
59
    // the most basic version of this query
55
60
    $q = agDoctrineQuery::create()
56
 
      ->select('eac.entity_id')
57
 
          ->addSelect('eac.address_id')
58
 
          ->addSelect('eac.created_at')
59
 
          ->addSelect('eac.updated_at')
60
 
        ->from('agEntityAddressContact eac')
61
 
        ->whereIn('eac.entity_id', $entityIds)
62
 
        ->orderBy('eac.priority') ;
 
61
            ->select('eac.entity_id')
 
62
            ->addSelect('eac.address_id')
 
63
            ->addSelect('eac.created_at')
 
64
            ->addSelect('eac.updated_at')
 
65
            ->from('agEntityAddressContact eac')
 
66
            ->whereIn('eac.entity_id', $entityIds)
 
67
            ->orderBy('eac.priority');
63
68
 
64
69
    // here we determine whether to return the address_contact_type_id or its string value
65
 
    if ($strType)
66
 
    {
 
70
    if ($strType) {
67
71
      $q->addSelect('act.address_contact_type')
68
 
        ->innerJoin('eac.agAddressContactType act') ;
69
 
    }
70
 
    else
71
 
    {
72
 
      $q->addSelect('eac.address_contact_type_id') ;
 
72
          ->innerJoin('eac.agAddressContactType act');
 
73
    } else {
 
74
      $q->addSelect('eac.address_contact_type_id');
73
75
    }
74
76
 
75
 
    return $q ;
 
77
    return $q;
76
78
  }
77
79
 
78
80
  /**
91
93
   * @return array A two or three dimensional array (depending up on the setting of the $primary
92
94
   * parameter), by entityId, by addressContactType.
93
95
   */
94
 
  public function getEntityAddressByType ($entityIds = NULL,
95
 
                                          $strType = NULL,
96
 
                                          $primary = NULL,
 
96
  public function getEntityAddressByType(array $entityIds = NULL,
 
97
                                          $strType = FALSE, $primary = FALSE,
97
98
                                          $addressHelperMethod = NULL,
98
 
                                          $addressArgs = array())
 
99
                                          array $addressArgs = array())
99
100
  {
100
101
    // initial results declarations
101
 
    $entityAddresses = array() ;
102
 
    $addressHelperArgs = array(array()) ;
 
102
    $entityAddresses = array();
 
103
    $addressHelperArgs = array(array());
103
104
 
104
105
    // if primary is not passed, get the default
105
 
    if (is_null($primary)) { $primary = $this->defaultIsPrimary ; }
 
106
    if (is_null($primary)) {
 
107
      $primary = $this->defaultIsPrimary;
 
108
    }
106
109
 
107
110
    // build our query object
108
 
    $q = $this->_getEntityAddressQuery($entityIds, $strType) ;
 
111
    $q = $this->_getEntityAddressQuery($entityIds, $strType);
109
112
 
110
113
    // if this is a primary query we add the restrictor
111
 
    if ($primary)
112
 
    {
 
114
    if ($primary) {
113
115
      $q->addWhere(' EXISTS (
114
116
        SELECT s.id
115
117
          FROM agEntityAddressContact s
116
118
          WHERE s.entity_id = eac.entity_id
117
119
            AND s.address_contact_type_id = eac.address_contact_type_id
118
 
          HAVING MIN(s.priority) = eac.priority )') ;
 
120
          HAVING MIN(s.priority) = eac.priority )');
119
121
    }
120
122
 
121
123
    // build this as custom hydration to 'double tap' the data
122
 
    $rows = $q->execute(array(), Doctrine_Core::HYDRATE_NONE) ;
123
 
    foreach ($rows as $row)
124
 
    {
125
 
      $entityAddresses[$row[0]][$row[4]][] = array($row[1], $row[2], $row[3]) ;
 
124
    $rows = $q->execute(array(), Doctrine_Core::HYDRATE_NONE);
 
125
    foreach ($rows as $row) {
 
126
      $entityAddresses[$row[0]][$row[4]][] = array($row[1], $row[2], $row[3]);
126
127
 
127
128
      // here we build the mono-dimensional addressId array, excluding dupes as we go; only useful
128
129
      // if we're actually going to use the address helper
129
 
      if (! is_null($addressHelperMethod) && ! in_array($row[1], $addressHelperArgs[0]))
130
 
      {
131
 
        $addressHelperArgs[0][] = $row[1] ;
 
130
      if (!is_null($addressHelperMethod) && !in_array($row[1], $addressHelperArgs[0])) {
 
131
        $addressHelperArgs[0][] = $row[1];
132
132
      }
133
133
    }
134
134
 
135
135
    // if no address helper method was passed, assume that all we need are the address id's and
136
136
    // stop right here!
137
 
    if (is_null($addressHelperMethod))
138
 
    {
139
 
      return $entityAddresses ;
 
137
    if (is_null($addressHelperMethod)) {
 
138
      return $entityAddresses;
140
139
    }
141
140
 
142
141
    // otherwise... we keep going and lazily load our address helper, 'cause we'll need her
143
 
    $addressHelper = $this->getAgAddressHelper() ;
144
 
    
 
142
    $addressHelper = $this->getAgAddressHelper();
 
143
 
145
144
    // finish appending the rest of our address helper args
146
 
    foreach ($addressArgs as $arg)
147
 
    {
148
 
      $addressHelperArgs[] = $arg ;
 
145
    foreach ($addressArgs as $arg) {
 
146
      $addressHelperArgs[] = $arg;
149
147
    }
150
148
 
151
149
    // use the address helper to format the address results
152
 
    $userFunc = array($addressHelper,$addressHelperMethod) ;
153
 
    $formattedAddresses = call_user_func_array($userFunc,$addressHelperArgs) ;
 
150
    $userFunc = array($addressHelper, $addressHelperMethod);
 
151
    $formattedAddresses = call_user_func_array($userFunc, $addressHelperArgs);
154
152
 
155
153
    // we can release the address helper args, since we don't need them anymore
156
 
    unset($addressHelperArgs) ;
 
154
    unset($addressHelperArgs);
157
155
 
158
156
    // now loop through our entities and attach their addresses
159
 
    foreach ($entityAddresses as $entityId => $addressTypes)
160
 
    {
161
 
      foreach ($addressTypes as $addressType => $addresses)
162
 
      {
 
157
    foreach ($entityAddresses as $entityId => $addressTypes) {
 
158
      foreach ($addressTypes as $addressType => $addresses) {
163
159
        // if we're only returning the primary, change the third dimension from an array to a value
164
160
        // NOTE: because of the restricted query, we can trust there is only one component per type
165
161
        // in our output and safely make this assumption
166
 
        if ($primary)
167
 
        {
 
162
        if ($primary) {
168
163
          // flatten the results
169
 
          $addresses = $addresses[0] ;
170
 
          $addresses[0] = $formattedAddresses[$addresses[0]] ;
 
164
          $addresses = $addresses[0];
 
165
          $addresses[0] = $formattedAddresses[$addresses[0]];
171
166
 
172
 
          $entityAddresses[$entityId][$addressType][0] = $addresses ;
 
167
          $entityAddresses[$entityId][$addressType][0] = $addresses;
173
168
        }
174
169
        // if not primary, we have one more loop in our return for another array nesting
175
 
        else
176
 
        {
177
 
          foreach ($addresses as $index => $address)
178
 
          {
179
 
            $entityAddresses[$entityId][$addressType][$index][0] = $formattedAddresses[$address[0]] ;
 
170
        else {
 
171
          foreach ($addresses as $index => $address) {
 
172
            $entityAddresses[$entityId][$addressType][$index][0] = $formattedAddresses[$address[0]];
180
173
          }
181
174
        }
182
175
      }
183
176
    }
184
177
 
185
 
    return $entityAddresses ;
 
178
    return $entityAddresses;
186
179
  }
187
180
 
188
181
  /**
208
201
   *   ... )
209
202
   * </code>
210
203
   */
211
 
  public function getEntityAddress ($entityIds = NULL,
 
204
  public function getEntityAddress(array $entityIds = NULL,
212
205
                                    $strType = NULL,
213
206
                                    $primary = NULL,
214
207
                                    $addressHelperMethod = NULL,
215
 
                                    $addressArgs = array())
 
208
                                    array $addressArgs = array())
216
209
  {
217
210
    // initial results declarations
218
 
    $entityAddresses = array() ;
219
 
    $addressHelperArgs = array(array()) ;
 
211
    $entityAddresses = array();
 
212
    $addressHelperArgs = array(array());
220
213
 
221
214
    // if primary is not passed, get the default
222
 
    if (is_null($primary)) { $primary = $this->defaultIsPrimary ; }
 
215
    if (is_null($primary)) {
 
216
      $primary = $this->defaultIsPrimary;
 
217
    }
223
218
 
224
219
    // build our query object
225
 
    $q = $this->_getEntityAddressQuery($entityIds, $strType) ;
 
220
    $q = $this->_getEntityAddressQuery($entityIds, $strType);
226
221
 
227
222
    // if this is a primary query we add the restrictor, note this one is different
228
223
    // from the one used in the by-type method
229
 
    if ($primary)
230
 
    {
 
224
    if ($primary) {
231
225
      $q->addWhere(' EXISTS (
232
226
        SELECT s.id
233
227
          FROM agEntityAddressContact s
234
228
          WHERE s.entity_id = eac.entity_id
235
 
          HAVING MIN(s.priority) = eac.priority )') ;
 
229
          HAVING MIN(s.priority) = eac.priority )');
236
230
    }
237
231
    // build this as custom hydration to 'double tap' the data
238
 
    $rows = $q->execute(array(), Doctrine_Core::HYDRATE_NONE) ;
239
 
    foreach ($rows as $row)
240
 
    {
241
 
      $entityAddresses[$row[0]][]= array($row[4],$row[1], $row[2], $row[3]) ;
 
232
    $rows = $q->execute(array(), Doctrine_Core::HYDRATE_NONE);
 
233
    foreach ($rows as $row) {
 
234
      $entityAddresses[$row[0]][] = array($row[4], $row[1], $row[2], $row[3]);
242
235
 
243
236
      // here we build the mono-dimensional addressId array, excluding dupes as we go; only useful
244
237
      // if we're actually going to use the address helper
245
 
      if (! is_null($addressHelperMethod) && ! in_array($row[1], $addressHelperArgs[0]))
246
 
      {
247
 
        $addressHelperArgs[0][] = $row[1] ;
 
238
      if (!is_null($addressHelperMethod) && !in_array($row[1], $addressHelperArgs[0])) {
 
239
        $addressHelperArgs[0][] = $row[1];
248
240
      }
249
241
    }
250
242
 
251
243
    // if no address helper method was passed, assume that all we need are the address id's and
252
244
    // stop right here!
253
 
    if (is_null($addressHelperMethod))
254
 
    {
255
 
      return $entityAddresses ;
 
245
    if (is_null($addressHelperMethod)) {
 
246
      return $entityAddresses;
256
247
    }
257
248
 
258
249
    // otherwise... we keep going and lazily load our address helper, 'cause we'll need her
259
 
    $addressHelper = $this->getAgAddressHelper() ;
 
250
    $addressHelper = $this->getAgAddressHelper();
260
251
 
261
252
    // finish appending the rest of our address helper args
262
 
    foreach ($addressArgs as $arg)
263
 
    {
264
 
      $addressHelperArgs[] = $arg ;
 
253
    foreach ($addressArgs as $arg) {
 
254
      $addressHelperArgs[] = $arg;
265
255
    }
266
256
 
267
257
    // use the address helper to format the address results
268
 
    $userFunc = array($addressHelper,$addressHelperMethod) ;
269
 
    $formattedAddresses = call_user_func_array($userFunc,$addressHelperArgs) ;
 
258
    $userFunc = array($addressHelper, $addressHelperMethod);
 
259
    $formattedAddresses = call_user_func_array($userFunc, $addressHelperArgs);
270
260
 
271
261
    // now loop through our entities and attach their addresses
272
 
    foreach ($entityAddresses as $entityId => $addresses)
273
 
    {
 
262
    foreach ($entityAddresses as $entityId => $addresses) {
274
263
      // if we're only returning the primary, change the second dimension from an array to a value
275
264
      // NOTE: because of the restricted query, we can trust there is only one component per type
276
265
      // in our output and safely make this assumption
277
 
      if ($primary)
278
 
      {
 
266
      if ($primary) {
279
267
        // flatten for just one return
280
 
        $addresses = $addresses[0] ;
281
 
        $addresses[1] = $formattedAddresses[$addresses[1]] ;
 
268
        $addresses = $addresses[0];
 
269
        $addresses[1] = $formattedAddresses[$addresses[1]];
282
270
 
283
 
        $entityAddresses[$entityId] = $addresses ;
 
271
        $entityAddresses[$entityId] = $addresses;
284
272
      }
285
273
      // if not primary, we have one more loop in our return for another array nesting
286
 
      else
287
 
      {
288
 
        foreach ($addresses as $index => $address) 
289
 
        {
290
 
          $entityAddresses[$entityId][$index][1] = $formattedAddresses[$address[1]] ;
 
274
      else {
 
275
        foreach ($addresses as $index => $address) {
 
276
          $entityAddresses[$entityId][$index][1] = $formattedAddresses[$address[1]];
291
277
        }
292
278
      }
293
279
    }
294
 
   
295
 
    return $entityAddresses ;
 
280
 
 
281
    return $entityAddresses;
296
282
  }
297
283
 
298
284
  /**
303
289
   * <code>
304
290
   * array(
305
291
   *   $entityId => array(
306
 
   *     array($addressContactTypeId, array(array($elementId => $value, ...),
307
 
   *      $addressStandardId,
308
 
   *      array(array($latitude, $longitude), ...), $matchScoreId)
 
292
   *     array($addressContactTypeId,
 
293
   *            array(array($elementId => $value, ...),
 
294
   *                  $addressStandardId,
 
295
   *                  array(array( array($latitude, $longitude), ...),
 
296
   *                        $matchScoreId)
309
297
   *      )),
310
298
   *     ...
311
299
   *   ), ...
325
313
   * records, removed records, an a positional array of failed inserts.
326
314
   * @todo Hook up the addressGeo bits
327
315
   */
328
 
  public function setEntityAddress( $entityContacts,
329
 
                                    $addressGeo = array(), 
 
316
  public function setEntityAddress( array $entityContacts,
 
317
                                    $geoSourceId = NULL,
330
318
                                    $keepHistory = NULL,
331
319
                                    $enforceComplete = NULL,
332
320
                                    $throwOnError = NULL,
334
322
  {
335
323
    // some explicit declarations at the top
336
324
    $uniqContacts = array() ;
 
325
    $addressGeos = array();
337
326
    $err = NULL ;
338
327
    $errMsg = 'This is a generic ERROR for setEntityAddress. You should never receive this ERROR.
339
 
      If you have received this ERROR, there is an error with your ERROR handling code.' ;
 
328
      If you have received this ERROR, there is an error with your ERROR handling code.';
340
329
 
341
330
    // determine whether or not we'll explicitly throw exceptions on error
342
 
    if (is_null($throwOnError)) { $throwOnError = $this->throwOnError ; }
343
 
    
 
331
    if (is_null($throwOnError)) {
 
332
      $throwOnError = $this->throwOnError;
 
333
    }
 
334
 
344
335
    // loop through our contacts and pull our unique addresses from the fire
345
 
    foreach ($entityContacts as $entityId => $contacts)
 
336
    foreach ($entityContacts as $entityId => &$contacts)
346
337
    {
347
338
      foreach ($contacts as $index => $contact)
348
339
      {
 
340
        $geo = NULL;
 
341
 
349
342
        // Trim leading and trailing spaces from contact values.
350
 
        foreach($contact[1][0] as $elem => $val)
 
343
        foreach ($contact[1][0] as $elem => $val)
351
344
        {
352
345
          $contact[1][0][$elem] = trim($val);
353
346
        }
354
347
 
 
348
        if (array_key_exists(2, $contact[1]))
 
349
        {
 
350
          $geo = array_pop($contact[1]);
 
351
        }
 
352
 
355
353
        // find the position of the element or return false
356
 
        $pos = array_search($contact[1], $uniqContacts, TRUE) ;
 
354
        $pos = array_search($contact[1], $uniqContacts, TRUE);
357
355
 
358
356
        // need to be really strict here because we don't want any [0] positions throwing us
359
 
        if ($pos === FALSE)
360
 
        {
 
357
        if ($pos === FALSE) {
361
358
          // add it to our unique contacts array
362
 
          $uniqContacts[] = $contact[1] ;
 
359
          $uniqContacts[] = $contact[1];
363
360
 
364
361
          // the the most recently inserted key
365
 
          $pos = max(array_keys($uniqContacts)) ;
 
362
          $pos = max(array_keys($uniqContacts));
 
363
        }
 
364
 
 
365
        // Set geo array to have the same index id as address unique array
 
366
        if (!empty($geo))
 
367
        {
 
368
          $addressGeos[$pos] = $geo;
366
369
        }
367
370
 
368
371
        // either way we'll have to point the entities back to their addresses
369
 
        $entityContacts[$entityId][$index][1] = $pos ;
 
372
        $contacts[$index][1] = $pos;
370
373
      }
371
374
    }
 
375
    unset($contacts);
372
376
 
373
377
    // whelp, if we haven't loaded it already, let's get our address helper
374
 
    $addressHelper = $this->getAgAddressHelper() ;
 
378
    $addressHelper = $this->getAgAddressHelper();
375
379
 
376
380
    // here we check our current transaction scope and create a transaction or savepoint
377
 
    if (is_null($conn)) { $conn = Doctrine_Manager::connection() ; }
378
 
    $useSavepoint = ($conn->getTransactionLevel() > 0) ? TRUE : FALSE ;
379
 
    if ($useSavepoint)
380
 
    {
381
 
      $conn->beginTransaction(__FUNCTION__) ;
 
381
    if (is_null($conn)) {
 
382
      $conn = Doctrine_Manager::connection();
382
383
    }
383
 
    else
384
 
    {
385
 
      $conn->beginTransaction() ;
 
384
    $useSavepoint = ($conn->getTransactionLevel() > 0) ? TRUE : FALSE;
 
385
    if ($useSavepoint) {
 
386
      $conn->beginTransaction(__FUNCTION__);
 
387
    } else {
 
388
      $conn->beginTransaction();
386
389
    }
387
390
 
388
 
    try
389
 
    {
 
391
    try {
390
392
      // process addresses, setting or returning, whichever is better with our s/getter
391
 
      $uniqContacts = $addressHelper->setAddresses($uniqContacts, $addressGeo,
 
393
      $uniqContacts = $addressHelper->setAddresses($uniqContacts, $addressGeos, $geoSourceId,
392
394
        $enforceComplete, $throwOnError, $conn) ;
393
395
    }
394
396
    catch(Exception $e)
395
397
    {
396
398
      // log our error
397
 
      $errMsg = sprintf('Could not set addresses %s. Rolling back!', json_encode($uniqContacts)) ;
 
399
      $errMsg = sprintf('Could not set addresses %s. Rolling back!', json_encode($uniqContacts));
398
400
 
399
401
      // hold onto this exception for later
400
 
      $err = $e ;
 
402
      $err = $e;
401
403
    }
402
404
 
403
 
    if (is_null($err))
404
 
    {
 
405
    if (is_null($err)) {
405
406
      // now loop through the contacts again and give them their real values
406
 
      foreach ($entityContacts as $entityId => $contacts)
407
 
      {
408
 
        foreach ($contacts as $index => $contact)
409
 
        {
 
407
      foreach ($entityContacts as $entityId => $contacts) {
 
408
        foreach ($contacts as $index => $contact) {
410
409
          // check to see if this index found in our 'unsettable' return from setAddresses
411
 
          if (array_key_exists($contact[1], $uniqContacts[1]))
412
 
          {
 
410
          if (array_key_exists($contact[1], $uniqContacts[1])) {
413
411
            // purge this address
414
 
            unset($entityContacts[$entityId][$index]) ;
415
 
          }
416
 
          else
417
 
          {
 
412
            unset($entityContacts[$entityId][$index]);
 
413
          } else {
418
414
            // otherwise, get our real addressId
419
 
            $entityContacts[$entityId][$index][1] = $uniqContacts[0][$contact[1]] ;
 
415
            $entityContacts[$entityId][$index][1] = $uniqContacts[0][$contact[1]];
420
416
          }
421
417
        }
422
418
      }
423
419
 
424
420
      // we're done with uniqContacts now
425
 
      unset($uniqContacts) ;
 
421
      unset($uniqContacts);
426
422
 
427
 
      try
428
 
      {
 
423
      try {
429
424
        // just submit the entity addresses for setting
430
425
        $results = $this->setEntityContactById($entityContacts, $keepHistory, $throwOnError, $conn);
 
426
        // most excellent! no errors at all, so we commit... finally!
 
427
        if ($useSavepoint) { $conn->commit(__FUNCTION__) ; } else { $conn->commit() ; }
431
428
      }
432
429
      catch(Exception $e)
433
430
      {
434
431
        // log our error
435
432
        $errMsg = sprintf('Could not set entity addresses %s. Rolling Back!',
436
 
          json_encode($entityContacts)) ;
 
433
                json_encode($entityContacts));
437
434
 
438
435
        // hold onto this exception for later
439
 
        $err = $e ;
 
436
        $err = $e;
440
437
      }
441
438
    }
442
439
 
443
440
    // check to see if we had any errors along the way
444
 
    if (! is_null($err))
445
 
    {
 
441
    if (!is_null($err)) {
446
442
      // log our error
447
 
      sfContext::getInstance()->getLogger()->err($errMsg) ;
 
443
      sfContext::getInstance()->getLogger()->err($errMsg);
448
444
 
449
445
      // rollback
450
 
      if ($useSavepoint) { $conn->rollback(__FUNCTION__) ; } else { $conn->rollback() ; }
 
446
      if ($useSavepoint) {
 
447
        $conn->rollback(__FUNCTION__);
 
448
      } else {
 
449
        $conn->rollback();
 
450
      }
451
451
 
452
452
      // ALWAYS throw an error, it's like stepping on a crack if you don't
453
 
      if ($throwOnError) { throw $err ; }
 
453
      if ($throwOnError) {
 
454
        throw $err;
 
455
      }
454
456
    }
455
457
 
456
 
    // most excellent! no errors at all, so we commit... finally!
457
 
    if ($useSavepoint) { $conn->commit(__FUNCTION__) ; } else { $conn->commit() ; }
458
 
 
459
458
    return $results ;
460
459
  }
 
460
 
461
461
}
 
 
b'\\ No newline at end of file'