petitionemail.php 45.5 KB
Newer Older
1 2 3 4
<?php

require_once 'petitionemail.civix.php';

5 6 7 8 9
// You can define multiple pairs of target groups to
// matching field. This constant defines how many are 
// presented in the user interface.
define('PETITIONEMAIL_ALLOWED_GROUP_FIELD_COMBINATIONS_COUNT', 3);

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
/**
 * Implementation of hook_civicrm_config
 */
function petitionemail_civicrm_config(&$config) {
  _petitionemail_civix_civicrm_config($config);
}

/**
 * Implementation of hook_civicrm_xmlMenu
 *
 * @param $files array(string)
 */
function petitionemail_civicrm_xmlMenu(&$files) {
  _petitionemail_civix_civicrm_xmlMenu($files);
}

/**
 * Implementation of hook_civicrm_install
 */
function petitionemail_civicrm_install() {
  return _petitionemail_civix_civicrm_install();
}

/**
 * Implementation of hook_civicrm_uninstall
 */
function petitionemail_civicrm_uninstall() {
37
  // Clear out our variables.
38
  petitionemail_remove_profiles();
39
  petitionemail_remove_variables();
40 41 42 43 44 45 46
  return _petitionemail_civix_civicrm_uninstall();
}

/**
 * Implementation of hook_civicrm_enable
 */
function petitionemail_civicrm_enable() {
47
  // Ensure the profile id is created.
48
  petitionemail_get_matching_fields_profile_id();
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
  return _petitionemail_civix_civicrm_enable();
}

/**
 * Implementation of hook_civicrm_disable
 */
function petitionemail_civicrm_disable() {
  return _petitionemail_civix_civicrm_disable();
}

/**
 * Implementation of 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
 */
function petitionemail_civicrm_upgrade($op, CRM_Queue_Queue $queue = NULL) {
  return _petitionemail_civix_civicrm_upgrade($op, $queue);
}

/**
 * Implementation of hook_civicrm_managed
 *
 * Generate a list of entities to create/deactivate/delete when this module
 * is installed, disabled, uninstalled.
 */
function petitionemail_civicrm_managed(&$entities) {
  return _petitionemail_civix_civicrm_managed($entities);
}
81

Jamie McClelland's avatar
Jamie McClelland committed
82 83 84
/**
 * Implemention of hook_civicrm_buildForm
 */
85 86 87 88
function petitionemail_civicrm_buildForm( $formName, &$form ) {
  if ($formName == 'CRM_Campaign_Form_Petition_Signature') {  
    $survey_id = $form->getVar('_surveyId');
    if ($survey_id) {
Jamie McClelland's avatar
Jamie McClelland committed
89 90
      $sql = "SELECT petition_id, 
                  default_message, 
91
                  subject, 
Jamie McClelland's avatar
Jamie McClelland committed
92
                  message_field, 
93
                  subject_field,
Jamie McClelland's avatar
Jamie McClelland committed
94 95 96 97 98
                  subject 
             FROM civicrm_petition_email 
             WHERE petition_id = %1";
      $params = array( 1 => array( $survey_id, 'Integer' ) );
      $dao = CRM_Core_DAO::executeQuery( $sql, $params );
99 100
      $defaults = array();
      $dao->fetch();
101 102 103 104
      if($dao->N == 0) {
        // Not a email enabled petition
        return;
      }
105
      $message_field = $dao->message_field;
106
      $subject_field = $dao->subject_field;
107
      $defaults[$message_field] = $dao->default_message;
108
      $defaults[$subject_field] = $dao->subject;
109
      $form->setDefaults($defaults);
110 111 112
    }
  }

113
  if ($formName == 'CRM_Campaign_Form_Petition') {
114
    CRM_Core_Resources::singleton()->addScriptFile('cc.tadpole.petitionemail', 'petitionemail.js');
115 116
    $survey_id = $form->getVar('_surveyId');
    if ($survey_id) {
117
      // Set default values for saved petitions.
118 119 120
      $sql = "SELECT petition_id, 
                default_message, 
                message_field, 
121
                subject_field,
122 123
                subject,
                recipients,
124
                location_type_id
125 126 127 128
              FROM civicrm_petition_email 
              WHERE petition_id = %1";
      $params = array( 1 => array( $survey_id, 'Integer' ) );
      $dao = CRM_Core_DAO::executeQuery( $sql, $params );
129
      $dao->fetch();
130 131 132 133 134
      if($dao->N > 0) {
        // Base table values.
        $defaults['email_petition'] = 1;
        $defaults['recipients'] = $dao->recipients;
        $defaults['default_message'] = $dao->default_message;
135
        $defaults['message_field'] = $dao->message_field;
136
        $defaults['subject_field'] = $dao->subject_field;
137 138 139 140
        $defaults['subject'] = $dao->subject;
        $defaults['location_type_id'] = $dao->location_type_id;
        
        // Now get matching fields.
141 142
        $sql = "SELECT matching_field, matching_group_id FROM
          civicrm_petition_email_matching_field WHERE petition_id = %1";
143 144
        $dao = CRM_Core_DAO::executeQuery($sql, $params);
        $matching_fields = array();
145
        $i = 1;
146
        while($dao->fetch()) {
147 148 149
          $defaults['matching_field' . $i] = $dao->matching_field;
          $defaults['matching_group_id' . $i] = $dao->matching_group_id;
          $i++;
150
        }
151 152
        // We have to build this URL by hand to avoid having the curly 
        // braces get escaped.
153 154
        $base_url = preg_match('#/$#', CIVICRM_UF_BASEURL) ? CIVICRM_UF_BASEURL : CIVICRM_UF_BASEURL . '/';
        $base_url = $base_url . "civicrm/petition/sign?sid=$survey_id&reset=1";
155
        $personal_url = $base_url . '&{contact.checksum}&cid={contact.contact_id}';
156
        $defaults['links'] = ts("Personal link (use this link if you are sending it via CiviMail, it will auto fill with the user's address): ") . "\n" . 
157
          $personal_url . "\n\n" .  ts("General link: ") . $base_url;
158
        $form->setDefaults($defaults);
159
      }
160
    }
161 162 163 164 165 166 167
    else {
      $form->setDefaults(
        array(
          'links' => ts("Please save the petition first, then you can copy and paste the link to sign the petition.")
        )
      );
    }
168
    // Now add our extra fields to the form.
169
    $form->add('checkbox', 'email_petition', ts('Send an email to a target'));
170

171 172 173
    // Get the Profiles in use by this petition so we can find out
    // if there are any potential fields for an extra message to the
    // petition target.
Jamie McClelland's avatar
Jamie McClelland committed
174
    $params = array('module' => 'CiviCampaign', 
175
                    'entity_table' => 'civicrm_survey', 
Jamie McClelland's avatar
Jamie McClelland committed
176
                    'entity_id' => $survey_id,
177
                    'rowCount' => 0);
Jamie McClelland's avatar
Jamie McClelland committed
178
    $join_results = civicrm_api3('UFJoin','get', $params);
179
    $custom_fields = array();
180
    $profile_ids = array();
181 182
    if ($join_results['is_error'] == 0) {
      foreach ($join_results['values'] as $join_value) {
183
        $profile_ids[] = $join_value['uf_group_id'];
184 185
      }
    }
186
    $custom_fields = petitionemail_get_text_fields($profile_ids);
187
    
188
    $custom_field_options = array();
189
    if(count($custom_fields) == 0) {
190
      $custom_field_options = array(
Jamie McClelland's avatar
Jamie McClelland committed
191 192
        '' => t('- No Text or TextArea fields defined in your profiles -')
      );
193 194
    }
    else {
195 196
      $custom_field_options = array('' => t('- Select -'));
      $custom_field_options = $custom_field_options + $custom_fields;
197 198 199
    }
    $choose_one = array('0' => ts('--choose one--'));
    $group_options = $choose_one + CRM_Core_PseudoConstant::group('Mailing');
Jamie McClelland's avatar
Jamie McClelland committed
200 201
    $location_options = $choose_one + 
      CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
202

203
    $field_options = petitionemail_get_matching_field_options();
204
    $field_options_count = count($field_options);
205 206 207 208 209 210 211
    if($field_options_count == 0) {
      // No matching fields!
      $field_options[''] = ts("No fields are configured");
    }
    else {
      array_unshift($field_options, ts("--Choose one--"));
    }
212 213
    $form->assign('petitionemail_matching_fields_count', $field_options_count);
    $url_params = array(
214
      'gid' => petitionemail_get_matching_fields_profile_id(),
215 216 217 218
      'action' => 'browse'
    );
    $url = CRM_Utils_System::url("civicrm/admin/uf/group/field", $url_params);
    $form->assign('petitionemail_profile_edit_link', $url);
219 220 221 222 223 224 225

    $i = 1;
    while($i <= PETITIONEMAIL_ALLOWED_GROUP_FIELD_COMBINATIONS_COUNT) {
      $form->add('select', 'matching_group_id' . $i, ts('Matching Target Group'), $group_options);
      $form->add('select', 'matching_field' . $i, ts('Matching field(s)'), $field_options); 
      $i++;
    }
226
    $form->add('select', 'location_type_id', ts('Email'), $location_options);
227
    $form->add('textarea', 'recipients', ts("Send petitions to"), 'rows=20 cols=100');
228
    $form->add('select', 'message_field', ts('Custom Message Field'),
229 230 231
      $custom_field_options);
    $form->add('select', 'subject_field', ts('Custom Subject Field'),
      $custom_field_options);
232
    $form->add('textarea', 'default_message', ts('Default Message'), 'rows=20 cols=100');
233
    $form->add('text', 'subject', ts('Default Email Subject Line'), array('size' => 70));
234
    $form->add('textarea', 'links', ts('Links to sign the petition'), 'rows=5')->freeze();
235 236
    
 
237 238 239
  }
}

240 241 242 243 244
/**
 * Get fields from the special petition email profile.
 *
 * Filter out un-supported fields.
 */
245
function petitionemail_get_matching_field_options() {
246 247
  $session = CRM_Core_Session::singleton();
  $ret = array();
248
  $uf_group_id = petitionemail_get_matching_fields_profile_id();
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
  $fields = CRM_Core_BAO_UFGroup::getFields($uf_group_id); 
  $allowed = petitionemail_get_allowed_matching_fields();
  if(is_array($fields)) {
    reset($fields);
    while(list($id, $value) = each($fields)) {
      $include = FALSE;
      // Check to see if it's a custom field
      if(preg_match('/^custom_/', $id)) {
        $ret[$id] = $value['title'];
        continue;
      }
      else {
        // Check to see if it's an address field
        $field_pieces = petitionemail_split_address_field($id);
        if($field_pieces) {
          if($field_pieces['location_name'] != 'Primary') {
            $session->setStatus(ts("Only primary address fields are support at this time."));
            continue;
          }
          if(array_key_exists($field_pieces['field_name'], $allowed)) {
            $ret[$id] = $value['title'];
            continue;
          }
        }
      }
      // Warn the user about a field that is not allowed
      $session->setStatus(ts("The field $id is not supported as a matching field at this time."));
    }
  }
278
  
279 280 281
  return $ret;
}

282 283 284 285 286 287
/**
 * Validate the petition form
 *
 * Ensure our values are consistent to avoid broken petitions.
 */
function petitionemail_civicrm_validateForm($formName, &$fields, &$files, &$form, &$errors) {
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
  if ($formName == 'CRM_Campaign_Form_Petition_Signature') {  
    // Do some basic sanity checking to prevent spammers
    if(empty($form->_surveyId)) {
      // Can't do much without the survey_id
      return;
    }
    $survey_id = $form->_surveyId;

    // Check to see if it's an email petition
    $sql = "SELECT message_field FROM civicrm_petition_email WHERE
      petition_id = %0";
    $dao = CRM_Core_DAO::executeQuery($sql, array(0 => array($survey_id, 'Integer')));
    $dao->fetch();
    if($dao->N == 0) {
      // Nothing to do
      return;
    }

    if(!empty($dao->message_field)) {
      $field_name = 'custom_' . $dao->message_field;
      // If we are allowing a user-supplied message field, ensure it doesn't
      // have any URLs or HTML in it.
      if(array_key_exists($field_name, $fields)) {
        if(preg_match('#https?://#i', $fields[$field_name])) {
          $errors[$field_name] = ts("To avoid spammers, you are not allowed to put web addresses in your message. Please revise your message and try again.");
        }
        // Now ensure we have no html tag
        if (preg_match('/([\<])([^\>]{1,})*([\>])/i', $fields[$field_name] )) {
          $errors[$field_name] = ts("To avoid spammers, you are not allowed to put HTML code in your message. Please revise your message and try again.");
        }
      }
    }
  }

322 323
  if($formName == 'CRM_Campaign_Form_Petition') {
    if(CRM_Utils_Array::value('email_petition', $fields)) {
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
      // Make sure we have a subject field and a default message.
      if(!CRM_Utils_Array::value('subject', $fields)) {
        $msg = ts("You must enter an email subject line.");
        $errors['subject'] = $msg;
      }
      if(!CRM_Utils_Array::value('default_message', $fields)) {
        $msg = ts("You must enter a default message.");
        $errors['default_message'] = $msg;
      }
      // For each matching_group_id, make sure we have a corresponding
      // matching field. 
      $i = 1;
      $using_dynamic_method = FALSE;
      while($i <= PETITIONEMAIL_ALLOWED_GROUP_FIELD_COMBINATIONS_COUNT) {
        $matching_group_id = CRM_Utils_Array::value('matching_group_id' . $i, $fields);
        $matching_field = CRM_Utils_Array::value('matching_field' . $i, $fields);

        if(!empty($matching_group_id) && empty($matching_field)) {
342
          $msg = ts("If you select a matching target group you must select
343 344 345 346 347 348 349 350 351 352 353 354
            a corresponding matching field.");
          $errors['matching_field' . $i] = $msg; 
        }
        if(empty($matching_group_id) && !empty($matching_field)) {
          $msg = ts("If you select a matching field you must select a 
            corresponding matching target group.");
          $errors['matching_group_id' . $i] = $msg; 
        }

        // Keep track to see if there are using the dynamic method
        if(!empty($matching_group_id)) {
          $using_dynamic_method = TRUE;
355
        }
356
        $i++;
357
      }
358

359 360 361 362 363 364 365 366 367 368 369 370
      // If additional email targets have been provided, make sure they are
      // all syntactically correct.
      $recipients = CRM_Utils_Array::value('recipients', $fields);
      if(!empty($recipients)) {
        $recipient_array = explode("\n", $recipients);
        while(list(,$line) = each($recipient_array)) {
          if(FALSE === petitionemail_parse_email_line($line)) {
            $errors['recipients'] = ts("Invalid email address listed: %1.", array(1 => $line));
          }
        }
      }

371 372
      if(!$using_dynamic_method && empty($recipients)) {
        $msg = ts("You must select either one target matching group/field or list
373 374 375 376 377 378 379
          at least one address to send all petitions to.");
        $errors['recipients'] = $msg;
      }
    }
  }
}

380 381 382
/**
 * Given an array of profile ids, list all text area fields
 */
383
function petitionemail_get_text_fields($profile_ids) {
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
  // Now get all fields in this profile
  $custom_fields = array();
  while(list(,$uf_group_id) = each($profile_ids)) {
    $params = array('uf_group_id' => $uf_group_id, 'rowCount' => 0);
    $field_results = civicrm_api3('UFField', 'get', $params);
    if ($field_results['is_error'] == 0) {
      foreach ($field_results['values'] as $field_value) {
        $field_name = $field_value['field_name'];
        if(!preg_match('/^custom_[0-9]+/', $field_name)) {
          // We only know how to lookup field types for custom
          // fields. Skip core fields.
          continue;
        }

        $id = substr(strrchr($field_name, '_'), 1);
        // Finally, see if this is a text or textarea field.
        $params = array('id' => $id);
        $custom_results = civicrm_api3('CustomField', 'get', $params);
        if ($custom_results['is_error'] == 0) {
          $field_value = array_pop($custom_results['values']);
          $html_type = $field_value['html_type'];
          $label = $field_value['label'];
          $id = $field_value['id'];
          if($html_type == 'Text' || $html_type == 'TextArea') {
408
            $custom_fields['custom_' . $id] = $label;
409 410 411 412 413 414 415 416 417
          }
        }
      }
    }
  }
  return $custom_fields;
}


418
function petitionemail_civicrm_postProcess( $formName, &$form ) {
419 420 421
  if ($formName != 'CRM_Campaign_Form_Petition') { 
    return; 
  }
422 423
  $email_petition = CRM_Utils_Array::value('email_petition', $form->_submitValues);
  if($email_petition && $email_petition  == 1 ) {
424 425 426
    $survey_id = $form->getVar('_surveyId');
    $lastmoddate = 0;
    if (!$survey_id) {  // Ugly hack because the form doesn't return the id
Jamie McClelland's avatar
Jamie McClelland committed
427 428
      $params = array('title' =>$form->_submitValues['title']);
      $surveys = civicrm_api3("Survey", "get", $params);
429 430
      if (is_array($surveys['values'])) {
        foreach($surveys['values'] as $survey) {
431 432 433
          if ($lastmoddate > strtotime($survey['last_modified_date'])) { 
            continue; 
          }
434 435 436 437 438 439
          $lastmoddate = strtotime($survey['last_modified_date']);
          $survey_id = $survey['id'];
        }
      }
    }
    if (!$survey_id) {
Jamie McClelland's avatar
Jamie McClelland committed
440 441
      $msg = ts('Cannot find the petition for saving email delivery fields.');
      CRM_Core_Session::setStatus($msg);
442 443 444 445
      return;
    }

    $default_message =  $form->_submitValues['default_message'];
446
    $message_field = $form->_submitValues['message_field'];
447
    $subject_field = $form->_submitValues['subject_field'];
448 449 450
    $subject = $form->_submitValues['subject'];
    $recipients = $form->_submitValues['recipients'];
    $location_type_id = $form->_submitValues['location_type_id'];
451

452
    $sql = "REPLACE INTO civicrm_petition_email (
Jamie McClelland's avatar
Jamie McClelland committed
453 454 455
             petition_id,
             default_message, 
             message_field, 
456
             subject_field, 
Jamie McClelland's avatar
Jamie McClelland committed
457 458 459 460 461 462 463 464 465
             subject,
             recipients,
             location_type_id
           ) VALUES ( 
             %1, 
             %2, 
             %3, 
             %4,
             %5,
466 467
             %6,
             %7
Jamie McClelland's avatar
Jamie McClelland committed
468
    )";
469 470 471
    $params = array( 
      1 => array( $survey_id, 'Integer' ),
      2 => array( $default_message, 'String' ),
472
      3 => array( $message_field, 'String' ),
473 474 475 476
      4 => array( $subject_field, 'String' ),
      5 => array( $subject, 'String' ),
      6 => array( $recipients, 'String' ),
      7 => array( $location_type_id, 'Integer' ),
477 478
    );
    $petitionemail = CRM_Core_DAO::executeQuery( $sql, $params );
479
    
480
    // delete any existing ones
Jamie McClelland's avatar
Jamie McClelland committed
481 482
    $sql = "DELETE FROM civicrm_petition_email_matching_field WHERE
      petition_id = %0";
483 484
    $params = array(0 => array($survey_id, 'Integer'));
    CRM_Core_DAO::executeQuery($sql, $params);
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500

    $i = 1;
    while($i <= PETITIONEMAIL_ALLOWED_GROUP_FIELD_COMBINATIONS_COUNT) {
      $matching_group_id = CRM_Utils_Array::value('matching_group_id' . $i, $form->_submitValues);
      $matching_field = CRM_Utils_Array::value('matching_field' . $i, $form->_submitValues);
      if(!empty($matching_group_id) && !empty($matching_field)) {
        $sql = "INSERT INTO civicrm_petition_email_matching_field SET
          petition_id = %0, matching_field = %1, matching_group_id = %2";
        $params = array(
          0 => array($survey_id, 'Integer'),
          1 => array($matching_field, 'String'),
          2 => array($matching_group_id, 'Integer')
        );
        CRM_Core_DAO::executeQuery($sql, $params);
      }
      $i++;
501
    }
502 503 504
  }
}

505 506 507 508
/**
 * Implementation of hook_civicrm_post
 *
 * Run everytime a post is made to see if it's a new profile/activity
509 510
 * that should trigger a petition email to be sent. Also clean up 
 * our tables if a petition is deleted.
511
 */
512
function petitionemail_civicrm_post( $op, $objectName, $objectId, &$objectRef ) {
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
  static $profile_fields = NULL;
  if($objectName == 'Profile' && is_array($objectRef)) {
    // This is hacky but seems to be unavoidable. We really want to run 
    // on the activity post create hook. However, the activity post create
    // hook is called *before* the custom fields are saved for the activity
    // record. That means that none of the custom fields are available when
    // it is called, so we can't provide a custom subject or custom message
    // field to the petitionemail_process_signature function.
    //
    // However, the profile post hook is called before the activity post
    // hook is called. So, we set a static variable when the profile post
    // hook is called to save all the fields being submitted and then make
    // that available when the activity post hook is called.
    $profile_fields = $objectRef;
  }
528 529 530
  if ($objectName == 'Activity') {
    $activity_id = $objectId;

531
    // Only run on creation. For petitions that require a confirmation,
532 533 534
    // after the petition has been created, see petitionemail_civicrm_pageRun().
    if($op == 'create') {
      if(petitionemail_is_actionable_activity($activity_id)) {
535
        petitionemail_process_signature($activity_id, $profile_fields);
536 537
      }
    }
538
  }
539
}
540

541 542 543 544 545 546 547 548 549 550 551 552 553 554
/**
 * Implementation of hook_civicrm_pageRun
 */
function petitionemail_civicrm_pageRun(&$page) {
  // This should be fired after most of the parent run()
  // code is done, which means the activity status should
  // be converted to "complete" if it has been properly
  // verified.
  $pageName = $page->getVar('_name');
  if ($pageName == 'CRM_Campaign_Page_Petition_Confirm') { 
    // Get the activity id from the URL
    $activity_id  = CRM_Utils_Request::retrieve('a', 'String', CRM_Core_DAO::$_nullObject);
    if(petitionemail_is_actionable_activity($activity_id)) {
      petitionemail_process_signature($activity_id);
555 556 557
    }
  }
}
558

559 560
function petitionemail_get_petition_details($petition_id) {
  $ret = array();
Jamie McClelland's avatar
Jamie McClelland committed
561
  $sql = "SELECT default_message, 
562
               message_field, 
563
               subject_field,
564 565 566 567 568
               subject,
               location_type_id,
               recipients
         FROM civicrm_petition_email
         WHERE petition_id = %1 GROUP BY petition_id";
569
  $params = array( 1 => array( $petition_id, 'Integer' ) );
570 571
  $petition_email = CRM_Core_DAO::executeQuery( $sql, $params );
  $petition_email->fetch();
Jamie McClelland's avatar
Jamie McClelland committed
572
  if($petition_email->N == 0) {
573
    // Must not be a petition with a target.
Jamie McClelland's avatar
Jamie McClelland committed
574
    return FALSE;;
575
  }
576

577
  // Store variables we need
578 579 580 581
  $ret['default_message'] = $petition_email->default_message;
  $ret['subject'] = $petition_email->subject;
  $ret['location_type_id'] = $petition_email->location_type_id;
  $ret['message_field'] = $petition_email->message_field;
582
  $ret['subject_field'] = $petition_email->subject_field;
583
  $ret['recipients'] = $petition_email->recipients;
584

585
  // Now retrieve the matching fields, if any
586 587
  $sql = "SELECT matching_field, matching_group_id FROM
    civicrm_petition_email_matching_field WHERE petition_id = %1";
588
  $params = array( 1 => array( $petition_id, 'Integer' ) );
589
  $dao = CRM_Core_DAO::executeQuery($sql, $params);
590
  $ret['matching'] = array();
591
  while($dao->fetch()) {
592
    $ret['matching'][$dao->matching_field] = $dao->matching_group_id;
593
  }
594 595 596
  return $ret;
}

597 598 599 600 601 602 603 604
/**
 * This function handles all petition signature processing.
 *
 * @activity_id integer The activity id of the signature activity
 * @profile_fields array An array of fields submitted by the user, which
 *   may include the custom subject and custom message values.
 */
function petitionemail_process_signature($activity_id, $profile_fields = NULL) {
605 606 607 608 609 610 611
  $petition_id = petitionemail_get_petition_id_for_activity($activity_id);
  if(empty($petition_id)) {
    $log = "Failed to find petition id for activity id: $activity_id";
    CRM_Core_Error::debug_log_message($log);
    return FALSE;
  }
  $petition_vars = petitionemail_get_petition_details($petition_id);
Jamie McClelland's avatar
Jamie McClelland committed
612 613 614 615
  if(!$petition_vars) {
    // Nothing to process, this isn't an email target enabled petition
    return;
  }
616
  $default_message = $petition_vars['default_message'];
617
  $default_subject = $petition_vars['subject'];
618
  $message_field = $petition_vars['message_field'];
619
  $subject_field = $petition_vars['subject_field'];
620

621 622
  // Figure out whether to use the user-supplied message/subject or the default
  // message/subject.
623
  $petition_message = NULL;
624
  $subject = NULL;
625 626
  // If the petition has specified a message field
  if(!empty($message_field)) {
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
    // Check for a custom message field value in the passed in profile fields.
    // This field will be populated if we are operating on a new activity via
    // the post hook.
    if(is_array($profile_fields) && !empty($profile_fields[$message_field])) {
      $petition_message = $profile_fields[$message_field];
    }
    else {
      // Retrieve the value of the field for this activity (this may happen
      // if we are operating on a confirmation click from pageRun hook).
      $params = array(
        'id' => $activity_id, 
        'return' => $message_field
      );
      $result = civicrm_api3('Activity', 'getsingle', $params);
      if(!empty($result[$message_field])) {
        $petition_message = $result[$message_field];
      }
644 645
    }
  } 
646 647 648 649
  if(is_null($petition_message)) {
    $petition_message = $default_message;
  }

650 651
  // If the petition has specified a subject field
  if(!empty($subject_field)) {
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
    // Check for a custom subject field value in the passed in profile fields.
    // This field will be populated if we are operating on a new activity via
    // the post hook.
    if(is_array($profile_fields) && !empty($profile_fields[$subject_field])) {
      $subject = $profile_fields[$subject_field];
    }
    else {
      // Retrieve the value of the field for this activity (this may happen
      // if we are operating on a confirmation click from pageRun hook).
      $params = array(
        'id' => $activity_id, 
        'return' => $subject_field
      );
      $result = civicrm_api3('Activity', 'getsingle', $params);
      if(!empty($result[$subject_field])) {
        $subject = $result[$subject_field];
      }
669 670 671
    }
  }
  // No user supplied message/subject, use the default
672
  
673 674 675 676
  if(is_null($subject)) {
    $subject = $default_subject;
  }

677 678
  $activity = civicrm_api3("Activity", "getsingle", array ('id' => $activity_id));
  $contact_id = $activity['source_contact_id'];
Jamie McClelland's avatar
Jamie McClelland committed
679
  $contact = civicrm_api3("Contact", "getsingle", array ('id' => $contact_id));
680

Jamie McClelland's avatar
Jamie McClelland committed
681
  $from = NULL;
682
  if (empty($contact['email'])) {
683 684 685
    $domain = civicrm_api3("Domain", "get", array ());
    if ($domain['is_error'] != 0 || !is_array($domain['values'])) { 
      // Can't send email without a from address.
686 687
      $msg = "petition_email: Failed to send petition email because from
        address not sent.";
688 689 690
      CRM_Core_Error::debug_log_message($msg);
      return; 
    }
691
    $contact['email'] = $domain['values']['from_email'];
692
  }
693
  $from = $contact['display_name'] . ' <' . $contact['email'] . '>';
694 695 696 697 698 699

  // Setup email message (except to address)
  $email_params = array( 
    'from'    => $from,
    'toName'  => NULL,
    'toEmail' => NULL,
Jamie McClelland's avatar
Jamie McClelland committed
700
    'subject' => $subject,
701
    'text'    => $petition_message, 
702
    'html'    => NULL, 
703 704 705
  );

  // Get array of recipients
706
  $recipients = petitionemail_get_recipients($contact_id, $petition_id);
707 708 709
  // Keep track of the targets we actually send the message to so we can 
  // email the petition signer to let them now.
  $message_sent_to = array();
710 711
  while(list(, $recipient) = each($recipients)) {
    if(!empty($recipient['email'])) {
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
      $log = "petition email: contact id ($contact_id) sending to email (" .
        $recipient['email'] . ")";
      CRM_Core_Error::debug_log_message($log);
      if(!empty($recipient['contact_id'])) {
        // Since we're sending to a recipient in the database, create this
        // as an email activity so we record it properly.

        $log = "petition email: recording email as activity against ".
          "target contact id: " . $recipient['contact_id'];
        CRM_Core_Error::debug_log_message($log);

        $contactDetails = array(0 => $recipient);
        // We are sending a text message, so ensure it's the preferred one
        $contactDetails[0]['preferred_mail_format'] = 'Text';
        $subject = $email_params['subject'];
        $text = $email_params['text'];
        $html = $email_params['html'];
        $emailAddress = $recipient['email'];
        $userID = $contact_id;
        $from = NULL; // This will be pulled from $contact_id,
        $attachments = NULL;
        $cc = NULL;
        $bcc = NULL;
        $contactIds = array($recipient['contact_id']);

        // Create/Send away.
        $ret = CRM_Activity_BAO_Activity::sendEmail(
          $contactDetails, $subject, $text, $html, $emailAddress, $userID,
          $from, $attachments, $cc, $bcc, $contactIds
        );
742

743 744 745
        $activity_id = array_pop($ret);
        $status = array_pop($ret);
        if($status === TRUE) {
746 747
          $to = $recipient['name'] . ' <' . $emailAddress . '>';
          CRM_Core_Session::setStatus( ts('Message sent successfully to: ') . htmlentities($to), '', 'success' );
748 749
          $log = "petition email: email sent successfully";
          CRM_Core_Error::debug_log_message($log);
750
          $message_sent_to[] = $to;
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774

          // Update the activity with the petition id so we can properly
          // report on the email messages sent as a result of this petition.
          $params = array(
            'activity_id' => $activity_id,
            'source_record_id' => $petition_id
          );
          $result = civicrm_api3('Activity', 'update', $params);
          if($result['is_error'] != 0) {
            $log = "civicrm petition: failed to update activity with ".
              "source_record_id";
            CRM_Core_Error::debug_log_message($log);
          }
        }
        else {
          $log = "petition email: failed to send email as activity.";
          CRM_Core_Error::debug_log_message($log);
          CRM_Core_Error::debug_log_message(print_r($ret, TRUE));
        }
      }
      else {
        // Handle targets not in the database.
        $email_params['toName'] = $recipient['name'];
        $email_params['toEmail'] = $recipient['email'];
775
        $to = $email_params['toName'] . ' <' . $email_params['toEmail'] . '>';
776 777 778 779 780 781 782

        $log = "petition_email: sending petition to '$to' via mail function.";
        CRM_Core_Error::debug_log_message($log);

        $success = CRM_Utils_Mail::send($email_params);

        if($success == 1) {
783
          CRM_Core_Session::setStatus( ts('Message sent successfully to: ') . htmlentities($to), '', 'success' );
784
          $log = "petition_email: message sent.";
785
          $message_sent_to[] = $to;
786 787 788 789
        } else {
          $log = "petition_email: message was not sent.";
        }
        CRM_Core_Error::debug_log_message($log);
790 791 792
      }
    }
  }
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
  // Now send a copy to the petition signer, that tells them who it was
  // sent to.
  $prepend_msg = ts("Below is a copy of your message. It was sent to the following people.") . "\n\n" .
    implode("\n", $message_sent_to);

  // Modify our email_params to send to the petition signer.
  $email_params['toEmail'] = $contact['email'];
  $email_params['toName'] = $contact['display_name'];
  $email_params['text'] = $prepend_msg . "\n\n---------\n\n" . $email_params['text'];

  $success = CRM_Utils_Mail::send($email_params);

  if($success == 1) {
    $log = "petition_email: message sent to petition signer.";
  } else {
    $log = "petition_email: message not sent to petition signer.";
  }
  CRM_Core_Error::debug_log_message($log);
811 812
}
 
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
/**
 * Non custom data fields allowed to be a matching field.
 *
 * All custom fields can be used as matching fields, but only
 * a subset of non-custom fields (so we can be sure to build
 * a working query to retrieve them).
 */
function petitionemail_get_allowed_matching_fields() {
  $ret = array(
    'street_name' => 'civicrm_address',
    'street_number' => 'civicrm_address',
    'street_name' => 'civicrm_address',
    'city' => 'civicrm_address',
    'county_id' => 'civicrm_address',
    'state_province_id' => 'civicrm_address',
    'postal_code' => 'civicrm_address',
    'postal_code_suffix' => 'civicrm_address',
    'country_id' => 'civicrm_address',
  );
  return $ret;
}

835 836
function petitionemail_get_recipients($contact_id, $petition_id) {
  $petition_vars = petitionemail_get_petition_details($petition_id);
Jamie McClelland's avatar
Jamie McClelland committed
837 838 839 840
  if(!$petition_vars) {
    // Not an email target enabled petition
    return;
  }
841 842 843 844 845 846 847 848 849
  $ret = array();
  // First, parse the additional recipients, if any. These get the email
  // regarldess of who signs it.
  if(!empty($petition_vars['recipients'])) {
    $recipients = explode("\n", $petition_vars['recipients']);
    while(list(,$recipient) = each($recipients)) {
      $email_parts = petitionemail_parse_email_line($recipient); 
      if(FALSE !== $email_parts) {
        $ret[] = array(
850
          'contact_id' => NULL,
851 852 853 854 855 856
          'name' => $email_parts['name'],
          'email' => $email_parts['email']
        );
      }
    }
  }
857 858 859
  // If there are any matching criteria (for a dynamic lookup) we do a
  // complex query to figure out which members of the group should be
  // included as recipients.
Jamie McClelland's avatar
Jamie McClelland committed
860
  if(count($petition_vars['matching']) > 0) {
861 862 863 864
    // This comes as an array with the key being the matching field and
    // the value being the matching_group_id.
    $matching_fields = $petition_vars['matching'];

865 866 867
    // Get the values of the matching fields for the contact. These values
    // are used to match the contact who signed the petition with the 
    // contact or contacts in the target group.
868 869 870 871 872 873

    // Given the matching fields, we're going to do an API call against
    // the contact to get the values that we will be matching on.

    // Build a return_fields array that we will pass to the api call to 
    // specify the fields we want returned with this query.
874
    $field_names = array_keys($matching_fields);
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
    $return_fields = array();
    reset($field_names);
    while(list(, $field_name) = each($field_names)) {
      // If the field_name starts with custom_ we can add it straight 
      // away.
      if(preg_match('/^custom_/', $field_name)) {
        $return_fields[] = $field_name;
        continue;
      }

      // Look for field names with a - in them - that's an indication 
      // that it's an address field which will have the location part
      // stuck into the name.
      $field_pieces = petitionemail_split_address_field($field_name);
      if($field_pieces) {
        if($field_pieces['location_name'] == 'Primary') {
          // Primary will be included via the api call, so we just need
          // the field name. If it's not primary, we'll have to do a 
          // manual SQL call below to get the value.
          $return_fields[] = $field_pieces['field_name'];
          continue;
        }
      }
898
      // FIXME If we get here, this is an error
899 900
    }
    $contact_params = array('return' => $return_fields, 'id' => $contact_id);
901 902
    $contact = civicrm_api3('Contact', 'getsingle', $contact_params);
    while(list($matching_field) = each($matching_fields)) {
903 904 905 906 907 908 909 910
      // Check if the field was returned. If not, it's probably an address field
      if(array_key_exists($matching_field, $contact)) {
        $matching_fields[$matching_field] = $contact[$matching_field];
        continue;
      }
      // This means it's probably an address field.
      $field_pieces = petitionemail_split_address_field($matching_field);
      if(!$field_pieces) {
911
        // FIXME This is an error
912 913 914 915 916 917 918
        continue;
      }
      $location_name = $field_pieces['location_name'];
      $field_name = $field_pieces['field_name'];
      if($location_name == 'Primary' && array_key_exists($field_name, $contact)) {
        // We have to unset the field that was saved as fieldname-locatiname
        unset($matching_fields[$matching_field]);
919

920 921 922 923 924 925
        // And now set the proper key
        $matching_field = $field_name;
        $matching_fields[$matching_field] = $contact[$matching_field];
        continue;
      }
      else {
926
        // FIXME This is an error
927 928 929
        continue;
      }
    } 
930 931

    // Initialize variables to build the SQL statement
932
    $from = array();
933 934
    // The master $where clause will be put together using AND
    $where = array();
935
    $params = array();
936
    $added_tables = array();
937

938 939
    // Initialize the from clause
    $from[] = 'civicrm_contact c';
940

941 942 943 944 945
    // We build a sub where clause that limits results based on the 
    // matching group and matching field that will be put together using
    // OR since we match any any of the matching field => group
    // combinations.
    $sub_where = array();
946
    reset($matching_fields);
947
    $id = 0;
948
    while(list($matching_field, $value) = each($matching_fields)) {
949 950 951 952 953 954 955 956 957 958 959 960 961 962
      // The $where_fragment will be put together using AND because
      // you have to match both the group and the field.
      $where_fragment = array();

      // Gather information about the group that is paired with this
      // matching field.
      $group_id = $petition_vars['matching'][$matching_field];
      // Retrieve details (specifically, find out if it's a smart group)
      $results = civicrm_api3('Group', 'getsingle', array('id' => $group_id));
      if(!empty($results['id'])) {
        if(!empty($results['saved_search_id'])) {
          // Populate the cache
          CRM_Contact_BAO_GroupContactCache::check($group_id);
          if(!in_array('civicrm_group_contact_cache', $added_tables)) {
Jamie McClelland's avatar
Jamie McClelland committed
963
            $from[] = 'LEFT JOIN civicrm_group_contact_cache cc ON
964 965 966 967 968 969
              c.id = cc.contact_id';
            $added_tables[] = 'civicrm_group_contact_cache';
          }
          $where_fragment[] = 'cc.group_id = %' . $id;
          $params[$id] = array($group_id, 'Integer');
          $id++;
970 971
        }
        else {
972
          if(!in_array('civicrm_group_contact', $added_tables)) {
Jamie McClelland's avatar
Jamie McClelland committed
973
            $from[] = 'LEFT JOIN civicrm_group_contact gc ON
974 975 976 977 978 979 980
              c.id = gc.contact_id';
            $added_tables[] = 'civicrm_group_contact';
          }
          $where_fragment[] = 'gc.group_id = %' . $id;
          $where_fragment[] = 'gc.status = "Added"';
          $params[$id] = array($group_id, 'Integer');
          $id++;
981
        }
982 983 984 985 986
      
        // Now add in the matching field
        if(empty($value)) {
          // We should never match in this case
          $where_fragment[] = "(0)";
987 988
        }
        else {
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
          if(preg_match('/^custom_/', $matching_field)) {
            $sql = "SELECT column_name, table_name FROM civicrm_custom_group g 
              JOIN civicrm_custom_field f ON g.id = f.custom_group_id WHERE 
              f.id = %0";
            $custom_field_id = str_replace('custom_', '', $matching_field);
            $dao = CRM_Core_DAO::executeQuery($sql, array(0 => array($custom_field_id, 'Integer')));
            $dao->fetch();
            if(!in_array($dao->table_name, $added_tables)) {
              $from[] = "LEFT JOIN " . $dao->table_name . " ON " . $dao->table_name . ".entity_id = 
                c.id";
              $added_tables[] = $dao->table_name;
            }
            $where_fragment[] = $dao->column_name . ' = %' . $id;
            // Fixme - we should use the proper data type for each custom field
            $params[$id] = array($value, 'String');
            $id++;
          }
          else {
            // Handle non-custom fields (address fields)
            if(!in_array('civicrm_address', $added_tables)) {
              $from[] = "LEFT JOIN civicrm_address a ON a.contact_id = c.id";
              $added_tables[] = 'civicrm_address';
            }
            $field_where[] = '(' . $matching_field . ' = %' . $id . ')';
            $params[$id] = array($value, 'String');
            $id++;
          }
1016
        }
1017
        $sub_where[] = '(' . implode(' AND ', $where_fragment) . ')';
1018
      }
1019 1020 1021 1022 1023 1024 1025
      else {
        // This is an error
      }
    }

    if(count($sub_where) > 0) {
      $where[] = '(' . implode(' OR ', $sub_where) . ')';
1026 1027 1028
    }

    // put it all together
1029
    $sql = "SELECT DISTINCT c.id, c.display_name ";
1030 1031
    $sql .= "FROM " . implode("\n", $from) . " ";
    $sql .= "WHERE " . implode(" AND\n", $where);
1032
    $dao = CRM_Core_DAO::executeQuery($sql, $params);
1033
    $location_type_id = $petition_vars['location_type_id'];
1034
    while($dao->fetch()) {
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
      // Lookup the best email address. 
      // ORDER BY FIELD allows us to arbitrarily set the location type id
      // we want to be set the highest.
      $sql = "SELECT e.email FROM civicrm_email e WHERE contact_id = %0 ".
        "AND (location_type_id = %1 OR is_primary = 1) ".
        "ORDER BY FIELD(e.location_type_id, %2) DESC, e.is_primary LIMIT 1";
      
      $email_params = array(
        0 => array($dao->id, 'Integer'),
        1 => array($petition_vars['location_type_id'], 'Integer'),
        2 => array($petition_vars['location_type_id'], 'Integer')
      );
      
      $email_dao = CRM_Core_DAO::executeQuery($sql, $email_params);
      $email_dao->fetch();
1050
      $ret[] = array(
1051
        'contact_id' => $dao->id,
1052
        'name' => $dao->display_name,
1053
        'email' => $email_dao->email
1054 1055 1056 1057 1058 1059
      );
    }
  }
  return $ret; 
}

1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
/**
 * Split address field name
 * 
 * Field names in profiles are stored in the format
 * fieldname-locationame (e.g. postal_code-Primary).
 * This function breaks that string into the field name
 * and location name or returns FALSE if it's not a
 * location field.
 */
function petitionemail_split_address_field($field_name) {
  $ret = FALSE;
  if(preg_match('/([a-zA-Z0-9_]+)-([a-zA-Z0-9_]+)/', $field_name, $matches)) {
    if(!empty($matches[1]) && !empty($matches[2])) {
      $ret = array(
        'field_name' => $matches[1],
        'location_name' => $matches[2],
      );
    }
  }
  return $ret;
}

1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
/**
 * Convert name + email line into name and email parts
 *
 * Thanks: http://www.regular-expressions.info/email.html
 */
function petitionemail_parse_email_line($line) {
  $ret = array();
  $recipient = trim($line);
  // First attempt to extract a valid email address
  if(preg_match('/([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6})/i', $recipient, $matches)) {
    $email = $matches[1];
    // Now remove the matching email from the string, along with any <> characters
    $remainder = trim(str_replace(array($email, '>', '<'), '', $recipient)); 
    // Trim off any opening/closing quotes
    $name = trim($remainder, '"');
    $ret['name'] = $name;
    $ret['email'] = $email;
  }
  else {
    // Could not find an email address in there any where.
    $ret = FALSE;
  }
  return $ret;
}

1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
/**
 * Given an activity id, return the related petition id 
 *
 * Return FALSE if this is not an activity that is a petition
 * signature. 
 */
function petitionemail_get_petition_id_for_activity($activity_id) {
  // If there is a related civicrm_petition_email record, we are good to go.
  // NOTE: source_record_id stores the survey_id which is the same thing
  // as the petition_id for our purposes.
  $sql = "SELECT a.source_record_id FROM civicrm_activity a JOIN
    civicrm_petition_email pe ON a.source_record_id = pe.petition_id
    WHERE a.id = %0";
  $params = array(0 => array($activity_id, 'Integer'));
  $dao = CRM_Core_DAO::executeQuery($sql, $params);
  $dao->fetch();
  if($dao->N == 0) return FALSE;
  return $dao->source_record_id; 
}

/**
 * Ensure activity_id should generate an email 
 *
 * Should have a related petition_email record and should have
 * a status of complete and should have a date.
 */
function petitionemail_is_actionable_activity($activity_id) {
  if(!petitionemail_get_petition_id_for_activity($activity_id)) {
    return FALSE;
1136
  }
1137 1138 1139 1140 1141 1142 1143
  $completed = CRM_Core_OptionGroup::getValue('activity_status', 'Completed', 'name');
  $sql = "SELECT id FROM civicrm_activity WHERE id = %0 AND status_id = %1";
  $params = array(0 => array($activity_id, 'Integer'), 1 => array($completed, 'Integer'));
  $dao = CRM_Core_DAO::executeQuery($sql, $params);
  $dao->fetch();
  if($dao->N == 0) return FALSE;
  return TRUE;
1144
}
1145

1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
/**
 * Helper function to get or create required profile
 *
 * This profile controls which fields can be used to match a petition 
 * signer with a petition target. We use a profile to avoid having a
 * giant list of fields presented to the user.
 *
 * This function ensures that the profile is created and if not, it
 * creates it. 
 *
 * @return integer profile id 
 */
1158
function petitionemail_get_matching_fields_profile_id() {
1159
  $group = 'petitionemail';
1160
  $key = 'petitionemail_matching_fields';
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
  $ret = CRM_Core_BAO_Setting::getItem($group, $key);
  if(!empty($ret)) {
    // Ensure it exists
    $sql = "SELECT id FROM civicrm_uf_group WHERE id = %0";
    $dao = CRM_Core_DAO::executeQuery($sql, array(0 => array($ret, 'Integer')));
    $dao->fetch();
    if($dao->N == 1) {
      return $ret;
    }
    // Delete this variable - probably the user deleted the profile not knowing
    // what it was used for.
    $sql = "DELETE FROM civicrm_setting WHERE group_name = %0 AND name = %1";
    $params = array(
      0 => array($group, 'String'),
      1 => array($key, 'String')
    );
    CRM_Core_DAO::executeQuery($sql, $params);
  }

  // Create the profile
  // We have to manually set created_id if the current user is not set
  $session = CRM_Core_Session::singleton();
  $contact_id = $session->get('userID');
  if(empty($contact_id)) {
    // Maybe we are running via drush?
    // Try the contact associated with uid 1
    $contact_id = CRM_Core_BAO_UFMatch::getContactId(1);
    if(empty($contact_id)) {
      // Last ditch effort
      $sql = "SELECT MIN(id) FROM civicrm_contact WHERE is_active = 1 AND is_deleted = 0";
      $dao = CRM_Core_DAO::executeQuery($sql);
      $dao->fetch();
      $contact_id = $dao->id;
    }
  }

  $description = ts('This profile controls which fields are available as
    matching fields when using the petition email extension. Please do
    not delete this profile.');
  $params = array(
1201
    'name' => $key,
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
    'title' => ts('Petition Email Available Matching fields'),
    'description' => $description,
    'created_id' => $contact_id
  );
  $results = civicrm_api3('UFGroup', 'create', $params);
  if($results['is_error'] != 0) {
    $session->setStatus(ts("Error creating the petition email profile group."));
    return FALSE;
  }
  $value = array_pop($results['values']);
  $id = $value['id'];

  CRM_Core_BAO_Setting::setItem($id, $group, $key);
  return $id;
}

1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
/**
 * Remove any profiles we automatically created.
 */
function petitionemail_remove_profiles() {
  $profiles_to_remove = array('petitionemail_matching_fields');
  while(list(,$key) = each($profiles_to_remove)) {
    $group = 'petitionemail';
    $ret = CRM_Core_BAO_Setting::getItem($group, $key);
    if($ret) {
      // Get a list of existing profile fields and remove those 
      // first.
      $params = array(
        'uf_group_id' => $ret,
        'return' => array('id')
      );
      $results = civicrm_api3('UFField', 'get', $params);
      if(is_array($results['values'])) {
        while(list($id) = each($results['values'])) {
          $params = array('id' => $id);
          civicrm_api3('UFField', 'delete', $params);
        }
      }
      $params = array('id' => $ret);
      civicrm_api3('UFGroup', 'delete', $params);
    }
  }
}

1246 1247 1248 1249
/**
 * Helper to remove any extension created variables
 */
function petitionemail_remove_variables() {
1250
  $group = 'petitionemail';
1251 1252 1253 1254 1255 1256
  $sql = "DELETE FROM civicrm_setting WHERE group_name = %0";
  $params = array(
    0 => array($group, 'String')
  );
  CRM_Core_DAO::executeQuery($sql, $params);
}