/**
  * Get a list of Projects matching the params.
  *
  * This function is invoked from within the web form layer and also from the
  * API layer. Special params include:
  * <ol>
  *   <li>project_contacts (@see CRM_Volunteer_BAO_Project::create() and
  *     CRM_Volunteer_BAO_Project::buildContactWhere)</li>
  *   <li>proximity (@see CRM_Volunteer_BAO_Project::buildProximityWhere)</li>
  * </ol>
  *
  * NOTE: This method does not return data related to the special params
  * outlined above; however, these parameters can be used to filter the list
  * of Projects that is returned.
  *
  * @param array $params
  * @return array of CRM_Volunteer_BAO_Project objects
  */
 public static function retrieve(array $params)
 {
     $result = array();
     $query = CRM_Utils_SQL_Select::from('`civicrm_volunteer_project` vp')->select('DISTINCT vp.*');
     if (!empty($params['project_contacts'])) {
         $contactJoin = self::buildContactJoin($params['project_contacts']);
         if ($contactJoin) {
             $query->join('vpc', $contactJoin);
         }
     }
     if (!empty($params['proximity'])) {
         $query->join('loc', 'INNER JOIN `civicrm_loc_block` loc ON loc.id = vp.loc_block_id')->join('civicrm_address', 'INNER JOIN `civicrm_address` ON civicrm_address.id = loc.address_id')->where(self::buildProximityWhere($params['proximity']));
     }
     // This step is here to support both naming conventions for specifying params
     // (e.g., volunteer_project_id and id) while normalizing how we access them
     // (e.g., $project->id)
     $project = new CRM_Volunteer_BAO_Project();
     $project->copyValues($params);
     foreach ($project->fields() as $field) {
         $fieldName = $field['name'];
         if (!empty($project->{$fieldName})) {
             $query->where('!column = @value', array('column' => $fieldName, 'value' => $project->{$fieldName}));
         }
     }
     $dao = self::executeQuery($query->toSQL());
     while ($dao->fetch()) {
         $fetchedProject = new CRM_Volunteer_BAO_Project();
         $fetchedProject->copyValues(clone $dao);
         $result[(int) $dao->id] = $fetchedProject;
     }
     $dao->free();
     return $result;
 }