예제 #1
0
 /**
  * Handling for is_primary.
  * $params is_primary could be
  *  #  1 - find other entries with is_primary = 1 &  reset them to 0
  *  #  0 - make sure at least one entry is set to 1
  *            - if no other entry is 1 change to 1
  *            - if one other entry exists change that to 1
  *            - if more than one other entry exists change first one to 1
  *              @fixme - perhaps should choose by location_type
  *  #  empty - same as 0 as once we have checked first step
  *             we know if it should be 1 or 0
  *
  *  if $params['id'] is set $params['contact_id'] may need to be retrieved
  *
  *  @param array $params
  * @static
  */
 public static function handlePrimary(&$params, $class)
 {
     $table = CRM_Core_DAO_AllCoreTables::getTableForClass($class);
     if (!$table) {
         throw new API_Exception("Failed to locate table for class [{$class}]");
     }
     // contact_id in params might be empty or the string 'null' so cast to integer
     $contactId = (int) CRM_Utils_Array::value('contact_id', $params);
     // If id is set & we haven't been passed a contact_id, retrieve it
     if (!empty($params['id']) && !isset($params['contact_id'])) {
         $entity = new $class();
         $entity->id = $params['id'];
         $entity->find(TRUE);
         $contactId = $entity->contact_id;
     }
     // If entity is not associated with contact, concept of is_primary not relevant
     if (!$contactId) {
         return;
     }
     // if params is_primary then set all others to not be primary & exit out
     if (!empty($params['is_primary'])) {
         $sql = "UPDATE {$table} SET is_primary = 0 WHERE contact_id = %1";
         $sqlParams = array(1 => array($contactId, 'Integer'));
         // we don't want to create unecessary entries in the log_ tables so exclude the one we are working on
         if (!empty($params['id'])) {
             $sql .= " AND id <> %2";
             $sqlParams[2] = array($params['id'], 'Integer');
         }
         CRM_Core_DAO::executeQuery($sql, $sqlParams);
         return;
     }
     //Check what other emails exist for the contact
     $existingEntities = new $class();
     $existingEntities->contact_id = $contactId;
     $existingEntities->orderBy('is_primary DESC');
     if (!$existingEntities->find(TRUE) || !empty($params['id']) && $existingEntities->id == $params['id']) {
         // ie. if  no others is set to be primary then this has to be primary set to 1 so change
         $params['is_primary'] = 1;
         return;
     } else {
         /*
          * If the only existing email is the one we are editing then we must set
          * is_primary to 1
          * CRM-10451
          */
         if ($existingEntities->N == 1 && $existingEntities->id == CRM_Utils_Array::value('id', $params)) {
             $params['is_primary'] = 1;
             return;
         }
         if ($existingEntities->is_primary == 1) {
             return;
         }
         // so at this point we are only dealing with ones explicity setting is_primary to 0
         // since we have reverse sorted by email we can either set the first one to
         // primary or return if is already is
         $existingEntities->is_primary = 1;
         $existingEntities->save();
     }
 }
예제 #2
0
 public function testGetTableForClass()
 {
     $this->assertEquals('civicrm_email', CRM_Core_DAO_AllCoreTables::getTableForClass('CRM_Core_DAO_Email'));
     $this->assertEquals('civicrm_email', CRM_Core_DAO_AllCoreTables::getTableForClass('CRM_Core_BAO_Email'));
 }
예제 #3
0
 /**
  * Joins onto an fk field
  *
  * Adds one or more joins to the query to make this field available for use in a clause.
  *
  * Enforces permissions at the api level and by appending the acl clause for that entity to the join.
  *
  * @param $fkFieldName
  * @return array|null
  *   Returns the table and field name for adding this field to a SELECT or WHERE clause
  * @throws \API_Exception
  * @throws \Civi\API\Exception\UnauthorizedException
  */
 private function addFkField($fkFieldName)
 {
     $stack = explode('.', $fkFieldName);
     if (count($stack) < 2) {
         return NULL;
     }
     $prev = 'a';
     foreach ($stack as $depth => $fieldName) {
         // Setup variables then skip the first level
         if (!$depth) {
             $fk = $fieldName;
             // We only join on core fields
             // @TODO: Custom contact ref fields could be supported too
             if (!in_array($fk, $this->entityFieldNames)) {
                 return NULL;
             }
             $fkField =& $this->apiFieldSpec[$fk];
             continue;
         }
         // More than 4 joins deep seems excessive - DOS attack?
         if ($depth > self::MAX_JOINS) {
             throw new UnauthorizedException("Maximum number of joins exceeded for api.{$this->entity}.get in parameter {$fkFieldName}");
         }
         if (!isset($fkField['FKApiName']) && !isset($fkField['FKClassName'])) {
             // Join doesn't exist - might be another param with a dot in it for some reason, we'll just ignore it.
             return NULL;
         }
         // Ensure we have permission to access the other api
         if (!$this->checkPermissionToJoin($fkField['FKApiName'], array_slice($stack, 0, $depth))) {
             throw new UnauthorizedException("Authorization failed to join onto {$fkField['FKApiName']} api in parameter {$fkFieldName}");
         }
         if (!isset($fkField['FKApiSpec'])) {
             $fkField['FKApiSpec'] = \_civicrm_api_get_fields($fkField['FKApiName']);
         }
         $fieldInfo = \CRM_Utils_Array::value($fieldName, $fkField['FKApiSpec']);
         // FIXME: What if the foreign key is not the "id" column?
         if (!$fieldInfo || !isset($fkField['FKApiSpec']['id'])) {
             // Join doesn't exist - might be another param with a dot in it for some reason, we'll just ignore it.
             return NULL;
         }
         $fkTable = \CRM_Core_DAO_AllCoreTables::getTableForClass($fkField['FKClassName']);
         $tableAlias = implode('_to_', array_slice($stack, 0, $depth)) . "_to_{$fkTable}";
         $joinClause = "LEFT JOIN {$fkTable} {$tableAlias} ON {$prev}.{$fk} = {$tableAlias}.id";
         // Add acl condition
         $joinCondition = $this->getAclClause($tableAlias, $fkField['FKClassName']);
         if ($joinCondition !== NULL) {
             $joinClause .= " AND {$joinCondition}";
         }
         $this->query->join($tableAlias, $joinClause);
         if (strpos($fieldName, 'custom_') === 0) {
             list($tableAlias, $fieldName) = $this->addCustomField($fieldInfo, $tableAlias);
         }
         // Get ready to recurse to the next level
         $fk = $fieldName;
         $fkField =& $fkField['FKApiSpec'][$fieldName];
         $prev = $tableAlias;
     }
     return array($tableAlias, $fieldName);
 }
예제 #4
0
 /**
  * @param $testEntityClass
  * @param $createParams
  * @param $updateParams
  * @param $expectedError
  * @dataProvider badUpdateProvider
  */
 public function testCreateWithBadUpdate($testEntityClass, $createParams, $updateParams, $expectedError)
 {
     $entity = CRM_Core_DAO::createTestObject($testEntityClass);
     $entity_table = CRM_Core_DAO_AllCoreTables::getTableForClass($testEntityClass);
     $this->assertTrue(is_numeric($entity->id));
     $createResult = $this->callAPISuccess('Attachment', 'create', $createParams + array('entity_table' => $entity_table, 'entity_id' => $entity->id));
     $fileId = $createResult['id'];
     $this->assertTrue(is_numeric($fileId));
     $updateResult = $this->callAPIFailure('Attachment', 'create', $updateParams + array('id' => $fileId));
     $this->assertRegExp($expectedError, $updateResult['error_message']);
 }