-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '1.7-wip' into la-milestone-3
- Loading branch information
Showing
70 changed files
with
4,511 additions
and
3,616 deletions.
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
com.civicrm.hrjobroles/CRM/Hrjobroles/API/Query/ContactHrJobRolesSelect.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
<?php | ||
|
||
use CRM_Hrjobroles_API_Query_VirtualEntitySelectQuery as VirtualEntitySelectQuery; | ||
use CRM_Hrjobroles_BAO_HrJobRoles as HRJobRoles; | ||
use CRM_Hrjobcontract_BAO_HRJobContract as HRJobContract; | ||
|
||
/** | ||
* This is a special class created mainly to support the ContactHrJobRoles.get | ||
* API. Its main objective is to return a list of Job Roles, but with a reduced | ||
* set of properties, and also include the id of the contact the role belongs to, | ||
* which is an information that is not stored together with the Job Role. It does | ||
* this by creating a query that joins the Job Roles table with the Contract | ||
* table, where the contact ID exists. | ||
* | ||
* Internally it uses a child class of the Api3SelectQuery class, which means | ||
* it can support everything that a normal .get query can like: | ||
* - Different operators (IN, LIKE, <>, etc) | ||
* - Limit and Offset operations | ||
* - Sorting | ||
*/ | ||
class CRM_Hrjobroles_API_Query_ContactHrJobRolesSelect { | ||
|
||
/** | ||
* @var array | ||
* An array of params passed to an API endpoint | ||
*/ | ||
private $params; | ||
|
||
/** | ||
* @var \CRM_HRLeaveAndAbsences_API_Query_Select | ||
* The SelectQuery instance wrapped by this class | ||
*/ | ||
private $query; | ||
|
||
/** | ||
* @var array | ||
* A list of fields that are supported by the entity + their names as they | ||
* should be added to the SELECT query. Usually the internal classes can | ||
* build this by themselves, but here we need to do it manually because not | ||
* all the fields are from the same database table | ||
*/ | ||
private $selectableFields = [ | ||
'id' => 'a.id', | ||
'title' => 'a.title', | ||
'description' => 'a.description', | ||
'region' => 'a.region', | ||
'department' => 'a.department', | ||
'level_type' => 'a.level_type', | ||
'functional_area' => 'a.functional_area', | ||
'location' => 'a.location', | ||
'contact_id' => 'jc.contact_id' | ||
]; | ||
|
||
public function __construct($params) { | ||
$this->params = $params; | ||
$this->buildCustomQuery(); | ||
} | ||
|
||
/** | ||
* Build the custom query. | ||
* | ||
* Here is basically where we get the given $params and build the entire query, | ||
* including the JOIN with the Contracts table | ||
*/ | ||
private function buildCustomQuery() { | ||
$customQuery = CRM_Utils_SQL_Select::from(HRJobRoles::getTableName() . ' as a'); | ||
|
||
$this->addJoins($customQuery); | ||
|
||
$this->query = $this->buildSelectQuery('ContactHrJobRoles'); | ||
$this->query->merge($customQuery); | ||
} | ||
|
||
/** | ||
* This method parses the $params array passed to the API and build an instance | ||
* of VirtualEntitySelectQuery, which is a child class of Api3SelectQuery and | ||
* it's the class that will actually build the SQL query. | ||
* | ||
* @param string $entity | ||
* | ||
* @return \CRM_Hrjobroles_API_Query_VirtualEntitySelectQuery | ||
*/ | ||
private function buildSelectQuery($entity) { | ||
$checkPermissions = !empty($this->params['check_permissions']); | ||
$query = new VirtualEntitySelectQuery($entity, $this->selectableFields, $checkPermissions); | ||
|
||
$query->where = $this->params; | ||
|
||
$options = _civicrm_api3_get_options_from_params($this->params); | ||
|
||
if ($options['is_count']) { | ||
$query->select = ['count_rows']; | ||
} | ||
else { | ||
$query->select = array_keys(array_filter($options['return'])); | ||
$query->orderBy = $options['sort']; | ||
} | ||
|
||
$query->limit = $options['limit']; | ||
$query->offset = $options['offset']; | ||
|
||
return $query; | ||
} | ||
|
||
/** | ||
* Add the clauses to JOIN the Job Roles table with other tables | ||
* | ||
* @param \CRM_Utils_SQL_Select $query | ||
*/ | ||
private function addJoins(CRM_Utils_SQL_Select $query) { | ||
$joins[] = 'INNER JOIN ' . HRJobContract::getTableName() . ' jc ON jc.id = a.job_contract_id'; | ||
|
||
$query->join(null, $joins); | ||
} | ||
|
||
/** | ||
* Executes the query | ||
* | ||
* @return array|int | ||
*/ | ||
public function run() { | ||
return $this->query->run(); | ||
} | ||
} | ||
|
61 changes: 61 additions & 0 deletions
61
com.civicrm.hrjobroles/CRM/Hrjobroles/API/Query/VirtualEntitySelectQuery.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
use Civi\API\Api3SelectQuery; | ||
|
||
/** | ||
* This is a specialization of the Api3SelectQuery, created to allow an entity | ||
* to return fields that are not part of an entity's table. | ||
* | ||
* The original implementation of the buildSelectFields() on the Api3SelectQuery | ||
* class makes sure that only fields of the entity's table will be returned by | ||
* the query. That means that, even if this is a query with multiple joins, it | ||
* won't be possible to return fields from any of the joined tables. This class | ||
* works around this by overriding that method and making it filter out fields | ||
* based on a list of "allowed" fields passed to the constructor. | ||
*/ | ||
class CRM_Hrjobroles_API_Query_VirtualEntitySelectQuery extends Api3SelectQuery { | ||
|
||
/** | ||
* @var array|bool | ||
* The list of fields that can be selected/returned by the query | ||
* Format: 'field name' => 'field name on the select clause (e.g. contract.contact_id)' | ||
*/ | ||
protected $virtualEntityFields = []; | ||
|
||
/** | ||
* CRM_Hrjobroles_API_Query_VirtualEntitySelectQuery constructor. | ||
* | ||
* @param string $entity | ||
* @param array $virtualEntityFields | ||
* The list of fields that can be selected/returned | ||
* @param bool $checkPermissions | ||
*/ | ||
public function __construct($entity, $virtualEntityFields, $checkPermissions) { | ||
parent::__construct($entity, $checkPermissions); | ||
$this->virtualEntityFields = $virtualEntityFields; | ||
} | ||
|
||
/** | ||
* Builds the list of fields that can be selected by the query, based on the | ||
* list of fields passed to the constructor | ||
*/ | ||
protected function buildSelectFields() { | ||
$returnAllFields = (empty($this->select) || !is_array($this->select)); | ||
$return = $returnAllFields ? $this->entityFieldNames : $this->select; | ||
if ($returnAllFields) { | ||
foreach (array_keys($this->apiFieldSpec) as $fieldName) { | ||
$return[] = $fieldName; | ||
} | ||
} | ||
|
||
// Always select the ID to keep some consistency with the API3 behavior | ||
$this->selectFields[self::MAIN_TABLE_ALIAS . '.id'] = 'id'; | ||
|
||
foreach ($return as $fieldName) { | ||
$field = $this->getField($fieldName); | ||
if ($field && in_array($field['name'], $this->entityFieldNames)) { | ||
$this->selectFields[$this->virtualEntityFields[$fieldName]] = $field['name']; | ||
} | ||
} | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
com.civicrm.hrjobroles/CRM/Hrjobroles/BAO/ContactHrJobRoles.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<?php | ||
|
||
use CRM_Hrjobroles_DAO_HrJobRoles as HrJobRoles; | ||
|
||
/** | ||
* This is a virtual entity. Its main objective is to serve as the underlying | ||
* entity for the ContactJobRole API. | ||
* | ||
* Originally, there's no direct connection between a Job Role and a Contact. | ||
* A Job Role is linked to a Contract, which finally is the entity connect to | ||
* a Contact. This means that, if we want to know which contacts work in the | ||
* IT department, we need to: | ||
* 1. Fetch all the Job Roles where the department == IT | ||
* 2. Fetch all the Contracts linked to these Job Roles | ||
* 3. Fetch all the Contacts linked to these Contracts | ||
* | ||
* The idea of this virtual entity is to expose both the Contact and Job Role | ||
* information under a single place and reduce the number of API calls to get | ||
* the data as exemplified above. The ContactJobRole.get custom API was created | ||
* to create the query necessary for this. This virtual BAO is necessary to | ||
* exposed which field will be available on the API. | ||
* | ||
* @see civicrm_api3_contact_job_role_get() | ||
* @see CRM_Hrjobroles_API_Query_ContactHrJobRolesSelect | ||
*/ | ||
class CRM_Hrjobroles_BAO_ContactHrJobRoles extends HrJobRoles { | ||
|
||
/** | ||
* @var array | ||
* To avoid exposing confidential information via de API, this entity exposes | ||
* just small set of all the HrJobRoles fields. Should a user have access to | ||
* all the fields, the HrJobRoles.get API should be used instead. | ||
* This is the list of fields exposed by the ContactJobRole.API | ||
*/ | ||
private static $allowedFields = [ | ||
'id', | ||
'title', | ||
'region', | ||
'department', | ||
'level_type', | ||
'location' | ||
]; | ||
|
||
/** | ||
* Returns the same information as HrJobRoles::fields(), but only for the | ||
* fields listed on $allowedFields. Additionally, it returns a "fake" | ||
* contact_id, which will actually come from the Job Contract. | ||
* | ||
* @return array | ||
*/ | ||
public static function &fields() { | ||
$fields = []; | ||
foreach(HrJobRoles::fields() as $key => $field) { | ||
if(!empty($field['name']) && in_array($field['name'], self::$allowedFields)) { | ||
$fields[$key] = $field; | ||
} | ||
} | ||
|
||
$fields['contact_id'] = [ | ||
'name' => 'contact_id', | ||
'type' => CRM_Utils_Type::T_INT, | ||
'title' => ts('Contact ID'), | ||
]; | ||
|
||
return $fields; | ||
} | ||
|
||
} |
27 changes: 27 additions & 0 deletions
27
com.civicrm.hrjobroles/CRM/Hrjobroles/Test/Fabricator/HrJobRoles.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?php | ||
|
||
class CRM_Hrjobroles_Test_Fabricator_HrJobRoles { | ||
|
||
protected static $defaultParams = [ | ||
'sequential' => 1 | ||
]; | ||
|
||
/** | ||
* @param array $params | ||
* An array of params that will be passed to the civicrm API | ||
* | ||
* @return array | ||
* The entity values as they are returned by the API call | ||
* | ||
* @throws \Exception | ||
*/ | ||
public static function fabricate($params) { | ||
$result = civicrm_api3( | ||
'HrJobRoles', | ||
'create', | ||
array_merge(self::$defaultParams, $params) | ||
); | ||
|
||
return array_shift($result['values']); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<?php | ||
|
||
/** | ||
* ContactJobRole.get API | ||
* | ||
* @param array $params | ||
* | ||
* @return array API result descriptor | ||
* | ||
* @throws API_Exception | ||
*/ | ||
function civicrm_api3_contact_hr_job_roles_get($params) { | ||
$query = new CRM_Hrjobroles_API_Query_ContactHrJobRolesSelect($params); | ||
|
||
return civicrm_api3_create_success($query->run(), $params, 'ContactHrJobRoles', 'get'); | ||
} | ||
|
||
/** | ||
* This function is used internally, to respond to a call to | ||
* ContactHrJobRoles.getFields. The CiviCRM will try to call a function with | ||
* this name to get the DAO for this entity. | ||
* | ||
* This is necessary because there is no DAO for ContactHrJobRoles. | ||
* | ||
* @return string | ||
*/ | ||
function _civicrm_api3_contact_hr_job_roles_DAO() { | ||
return CRM_Hrjobroles_BAO_ContactHrJobRoles::class; | ||
} |
Oops, something went wrong.