Commit a33eee32 authored by Johan Vervloet's avatar Johan Vervloet Committed by GitHub
Browse files

Merge pull request #9 from johanv/9-more_oo_fun

I guess I will just merge this into master. We are using this for about a month now, it does not seem to cause any troubles.
parents 194161c7 37222fe3
......@@ -8,14 +8,59 @@
*/
abstract class CRM_Civiconfig_Entity {
protected $entity;
/**
* CRM_Civiconfig_Entity constructor.
*
* @param string $entity The type of entity you want to configure,
* e.g. ContactType, RelationshipType, Group.
*/
public function __construct($entity) {
// TODO: validate whether $entity is a CiviCRM entity.
$this->entity = $entity;
}
/**
* Function to find an existing entity based on the entity's parameters.
*
* If no existing entity is found, an empty array is returned.
* This default implementation searches on the name, but you can override it.
*
* @param array $params
* @return array
* @access public
* @static
*/
public function getExisting(array $params) {
try {
return civicrm_api3($this->entity, 'Getsingle', array('name'=> $params['name']));
} catch (\CiviCRM_API3_Exception $ex) {
return [];
}
}
/**
* Method to create or update any entity
*
* @param array $params Parameters
* @return mixed
* @throws Exception when error from API RelationshipType Create
* @return int id of created/updated entity
* @throws Exception when error from API Entity Create
*/
public abstract function create(array $params);
public function create(array $params) {
$existingEntity = $this->getExisting($params);
// First prepare, then validate, because for e.g. event types, the
// option_group_id (which should be set) is set by the prepare function.
$this->prepareParams($params, $existingEntity);
$this->validateCreateParams($params);
try {
$result = civicrm_api3($this->entity, 'Create', $params);
} catch (\CiviCRM_API3_Exception $ex) {
throw new \CRM_Civiconfig_EntityException("Could not create or update {$this->entity} type with name "
.$params['name'].". Error from API {$this->entity}.Create: " . $ex->getMessage() . '.');
}
return $result['id'];
}
/**
* Creates/updates all objects at once.
......@@ -29,4 +74,38 @@ abstract class CRM_Civiconfig_Entity {
}
}
/**
* Method to validate params for create.
*
* Override this method if you want custom validation for the entity params.
*
* @param array $params
* @throws Exception when mandatory param not found
*/
public function validateCreateParams($params) {
if (empty($params['name'])) {
throw new \CRM_Civiconfig_EntityException("Missing mandatory parameter 'name' in class " . get_class() . ".");
}
// TODO: use API spec to check for other mandatory fields.
}
/**
* Override this method if you want to manipulate your params before creation.
*
* But don't forget to call the base one, to get $params['id'] right.
*
* @param array $params params that will be used for entity creation
* @param array $existing existing entity (if available)
*/
protected function prepareParams(array &$params, array $existing = []) {
if (isset($existing['id'])) {
$params['id'] = $existing['id'];
}
if (!isset($params['is_active'])) {
// if is_active is not explicitly given, assume that the entity is active.
// the entities 'setting' and 'tag' don't have an 'is_active' field, but I don't think
// it hurts that the param is set.
$params['is_active'] = 1;
}
}
}
......@@ -8,21 +8,29 @@
*/
class CRM_Civiconfig_Entity_ActivityType extends CRM_Civiconfig_Entity_OptionValue {
/**
* Overridden parent method to validate params for create
* Manipulate $params before entity creation.
*
* @param $params
* @throws Exception when missing mandatory params
* @param array $params params that will be used for entity creation
* @param array $existing existing entity (if available)
*/
protected function validateCreateParams($params) {
if (!isset($params['name']) || empty($params['name'])) {
throw new \CRM_Civiconfig_EntityException("Missing mandatory parameter 'name' in class " . get_class() . ".");
}
$this->_apiParams = $params;
try {
$this->_apiParams['option_group_id'] = $this->getOptionGroupId();
} catch (\CiviCRM_API3_Exception $ex) {
throw new \CRM_Civiconfig_EntityException("Unable to find option group for activity_type in " . get_class() . ", contact your system administrator.");
}
protected function prepareParams(array &$params, array $existing = []) {
$params['option_group_id'] = $this->getOptionGroupId();
parent::prepareParams($params, $existing);
}
/**
* Function to find an existing entity based on the entity's parameters.
*
* This default implementation searches on the name, but you can override it.
*
* @param array $params
* @return array|bool
* @access public
* @static
*/
public function getExisting(array $params) {
$params['option_group_id'] = $this->getOptionGroupId();
return parent::getExisting($params); // TODO: Change the autogenerated stub
}
/**
......
......@@ -6,65 +6,10 @@
* @license AGPL-3.0
*/
class CRM_Civiconfig_Entity_CaseType extends CRM_Civiconfig_Entity {
protected $_apiParams = array();
/**
* CRM_Civiconfig_Entity_CaseType constructor.
*/
public function __construct() {
$this->_apiParams = array();
}
/**
* Method to validate params passed to create
*
* @param $params
* @throws Exception when required param not found
*/
private function validateCreateParams($params) {
if (!isset($params['name']) || empty($params['name'])) {
throw new \CRM_Civiconfig_EntityException("Missing mandatory parameter 'name' in class " . get_class() . ".");
}
// The line below is in a strange place in the code. But I'll keep it
// there, because it is there as well for every other entity type.
$this->_apiParams = $params;
}
/**
* Method to create or update a case type
*
* @param array $params
* @return mixed
* @throws Exception if an API error occurs
*/
public function create(array $params) {
$this->validateCreateParams($params);
$existing = $this->getWithName($this->_apiParams['name']);
if (isset($existing['id'])) {
$this->_apiParams['id'] = $existing['id'];
}
try {
civicrm_api3('FinancialType', 'Create', $this->_apiParams);
} catch (\CiviCRM_API3_Exception $ex) {
throw new \CRM_Civiconfig_EntityException('Could not create or update financial type with name '.$this->_apiParams['name'] . '. Error from API CaseType.Create: '.$ex->getMessage() . '.');
}
}
/**
* Function to get the case type by name
*
* @param string $name
* @return array|bool
* @access public
* @static
*/
public function getWithName($name) {
try {
return civicrm_api3('CaseType', 'Getsingle',
array('name' => $name));
} catch (\CiviCRM_API3_Exception $ex) {
return FALSE;
}
parent::__construct('CaseType');
}
}
\ No newline at end of file
......@@ -8,14 +8,11 @@
* @license AGPL-3.0
*/
class CRM_Civiconfig_Entity_CivicrmSetting extends CRM_Civiconfig_Entity {
protected $_apiParams = [];
/**
* CRM_Civiconfig_Entity_CivicrmSetting constructor.
* CRM_Civiconfig_CivicrmSetting constructor.
*/
public function __construct() {
$this->_apiParams = [];
parent::__construct('Setting');
}
/**
......@@ -31,10 +28,9 @@ class CRM_Civiconfig_Entity_CivicrmSetting extends CRM_Civiconfig_Entity {
if (!is_array($paramsArray) || count($paramsArray) == 0) {
return FALSE;
}
$this->_apiParams = $paramsArray;
try {
civicrm_api3('Setting', 'create', $this->_apiParams);
civicrm_api3('Setting', 'create', $paramsArray);
} catch (\CiviCRM_API3_Exception $ex) {
throw new \CRM_Civiconfig_EntityException('Could not create or update CiviCRM settings. Error from API Setting.Create: ' . $ex->getMessage() . '.');
}
......
......@@ -7,61 +7,54 @@
* @license AGPL-3.0
*/
class CRM_Civiconfig_Entity_ContactType extends CRM_Civiconfig_Entity {
protected $_apiParams = array();
/**
* CRM_Civiconfig_ContactType constructor.
*/
public function __construct() {
parent::__construct('ContactType');
}
/**
* Method to validate params for create
* Manipulate $params before entity creation.
*
* @param $params
* @throws Exception when missing mandatory params
* @param array $params params that will be used for entity creation
* @param array $existing existing entity (if available)
*/
protected function validateCreateParams($params) {
if (!isset($params['name']) || empty($params['name'])) {
throw new \CRM_Civiconfig_EntityException("Missing mandatory parameter 'name' in class " . get_class() . ".");
protected function prepareParams(array &$params, array $existing = []) {
if (empty($params['label'])) {
$params['label'] = CRM_Civiconfig_Utils::buildLabelFromName($params['name']);
}
$this->_apiParams = $params;
parent::prepareParams($params, $existing);
}
/**
* Method to create contact type
* Method to create contact type.
*
* @param array $params
* @return mixed
* @return int $id ID of created contact type
* @throws Exception when error from API ContactType Create
*/
public function create(array $params) {
$this->validateCreateParams($params);
$existing = $this->getWithName($this->_apiParams['name']);
if (isset($existing['id'])) {
$this->_apiParams['id'] = $existing['id'];
}
if (!isset($this->_apiParams['label']) || empty($this->_apiParams['label'])) {
$this->_apiParams['label'] = CRM_Civiconfig_Utils::buildLabelFromName($this->_apiParams['name']);
}
try {
civicrm_api3('ContactType', 'Create', $this->_apiParams);
$this->updateNavigationMenuUrl();
} catch (\CiviCRM_API3_Exception $ex) {
throw new \CRM_Civiconfig_EntityException('Could not create or update contact type with name '.$this->_apiParams['name']
.'. Error from API ContactType.Create: '.$ex->getMessage().'.');
}
$id = parent::create($params);
$this->updateNavigationMenuUrl($params);
return $id;
}
/**
* Method to check if there is a navigation menu option for the contact type
* and if so, update name and url
*
* @param array $params
* @access private
*/
private function updateNavigationMenuUrl() {
private function updateNavigationMenuUrl($params) {
// check if there is a "New <label>" entry in the navigation table
$query = "SELECT * FROM civicrm_navigation WHERE label = %1";
$label = "New ".$this->_apiParams['label'];
$label = "New ".$params['label'];
$dao = CRM_Core_DAO::executeQuery($query, array(1 => array($label, 'String')));
$validParent = array("New Organization", "New Individual", "New Household");
$newUrl = 'civicrm/contact/add&ct=Organization&cst='.$this->_apiParams['name'].'&reset=1';
$newName = "New ".$this->_apiParams['name'];
$newUrl = 'civicrm/contact/add&ct=Organization&cst='.$params['name'].'&reset=1';
$newName = "New ".$params['name'];
while ($dao->fetch()) {
// parent should be either New Organization, New Individual or New Household
if (isset($dao->parent_id)) {
......@@ -79,21 +72,4 @@ class CRM_Civiconfig_Entity_ContactType extends CRM_Civiconfig_Entity {
}
}
}
/**
* Method to get contact sub type with name
*
* @param string $contactTypeName
* @return array|bool
* @access public
* @static
*/
public function getWithName($contactTypeName) {
try {
return civicrm_api3('ContactType', 'Getsingle', array('name' => $contactTypeName));
} catch (\CiviCRM_API3_Exception $ex) {
return FALSE;
}
}
}
\ No newline at end of file
......@@ -7,14 +7,11 @@
* @license AGPL-3.0
*/
class CRM_Civiconfig_Entity_CustomField extends CRM_Civiconfig_Entity {
protected $_apiParams = array();
/**
* CRM_Civiconfig_CustomField constructor.
*/
public function __construct() {
$this->_apiParams = array();
parent::__construct('CustomField');
}
/**
......@@ -23,64 +20,66 @@ class CRM_Civiconfig_Entity_CustomField extends CRM_Civiconfig_Entity {
* @param array $params
* @throws Exception when missing mandatory params
*/
private function validateCreateParams($params) {
if (!isset($params['name']) || empty($params['name']) || !isset($params['custom_group_id'])
|| empty($params['custom_group_id'])) {
public function validateCreateParams($params) {
parent::validateCreateParams($params);
if (empty($params['custom_group_id'])) {
throw new \CRM_Civiconfig_EntityException("Missing mandatory parameters 'name' and/or 'custom_group_id' in class " . get_class() . ".");
}
$this->_apiParams = $params;
if (isset($this->_apiParams['option_group'])) {
$this->_apiParams['option_type'] = 0;
}
/**
* Manipulate $params before entity creation.
*
* @param array $params params that will be used for entity creation
* @param array $existing existing entity (if available)
*/
protected function prepareParams(array &$params, array $existing = []) {
if (isset($params['option_group'])) {
$params['option_type'] = 0;
$optionGroup = new CRM_Civiconfig_Entity_OptionGroup();
$found = $optionGroup->getWithName($this->_apiParams['option_group']);
$found = $optionGroup->getExisting(['name' => $params['option_group']]);
if (!empty($found)) {
$this->_apiParams['option_group_id'] = $found['id'];
$params['option_group_id'] = $found['id'];
} else {
$created = $optionGroup->create(array('name' => $this->_apiParams['option_group']));
$this->_apiParams['option_group_id'] = $created['id'];
$id = $optionGroup->create(array('name' => $params['option_group']));
$params['option_group_id'] = $id;
}
unset($this->_apiParams['option_group']);
unset($params['option_group']);
}
if (empty($params['label'])) {
$params['label'] = CRM_Civiconfig_Utils::buildLabelFromName($params['name']);
}
parent::prepareParams($params, $existing);
}
/**
* Method to create or update custom field
*
* @param array $params
* @return int $id ID of created custom field.
*
* @throws Exception when error from API CustomField Create
*/
public function create(array $params) {
$this->validateCreateParams($params);
$existing = $this->getWithNameCustomGroupId($this->_apiParams['name'], $this->_apiParams['custom_group_id']);
if (isset($existing['id'])) {
$this->_apiParams['id'] = $existing['id'];
}
if (!isset($this->_apiParams['label']) || empty($this->_apiParams['label'])) {
$this->_apiParams['label'] = CRM_Civiconfig_Utils::buildLabelFromName($this->_apiParams['name']);
}
try {
$customField = civicrm_api3('CustomField', 'Create', $this->_apiParams);
if (isset($params['option_group'])) {
$this->fixOptionGroups($customField['values'], $params['option_group']);
}
} catch (\CiviCRM_API3_Exception $ex) {
throw new \CRM_Civiconfig_EntityException('Could not create or update custom field with name '.$this->_apiParams['name']
.' in custom group '.$this->_apiParams['custom_group_id'].'. Error from API CustomField.Create: '.$ex->getMessage() . '.');
$id = parent::create($params);
if (isset($params['option_group'])) {
$this->fixOptionGroups($id, $params['option_group']);
}
return $id;
}
/**
* Method to get custom field with name and custom group id
* Method to get the existing custom field
* If no existing entity is found, an empty array is returned.
*
* @param string $name
* @param integer $customGroupId
* @return array|bool
* @param array $params
* @return array
*/
public function getWithNameCustomGroupId($name, $customGroupId) {
public function getExisting(array $params) {
try {
return civicrm_api3('CustomField', 'Getsingle', array('name' => $name, 'custom_group_id' => $customGroupId));
return civicrm_api3('CustomField', 'Getsingle', array('name' => $params['name'], 'custom_group_id' => $params['custom_group_id']));
} catch (\CiviCRM_API3_Exception $ex) {
return FALSE;
return [];
}
}
......@@ -88,22 +87,23 @@ class CRM_Civiconfig_Entity_CustomField extends CRM_Civiconfig_Entity {
* Method to fix option group in custom field because API always creates an option group whatever you do
* so change option group to the one we created and then remove the one api created
*
* @param array $customField
* @param int $id custom field ID
* @param string $optionGroupName
* @throws CiviCRM_API3_Exception
*/
protected function fixOptionGroups($customField, $optionGroupName) {
$optionGroup = new CRM_Civiconfig_Entity_OptionGroup();
$found = $optionGroup->getWithName($optionGroupName);
protected function fixOptionGroups($id, $optionGroupName) {
$customField = civicrm_api3('CustomField', 'getsingle', ['id' => $id]);
$optionGroupConfig = new CRM_Civiconfig_Entity_OptionGroup();
$found = $optionGroupConfig->getExisting(['name' => $optionGroupName]);
// only if found is not equal to created custom field value
if ($found['id'] != $customField[key($customField)]['option_group_id']) {
if ($found['id'] != $customField['option_group_id']) {
$qry = 'UPDATE civicrm_custom_field SET option_group_id = %1 WHERE id = %2';
$params = array(
1 => array($found['id'], 'Integer'),
2 => array(key($customField), 'Integer')
2 => array($id, 'Integer')
);
CRM_Core_DAO::executeQuery($qry, $params);
civicrm_api3('OptionGroup', 'Delete', array('id' => $customField[key($customField)]['option_group_id']));
civicrm_api3('OptionGroup', 'Delete', array('id' => $customField['option_group_id']));
}
}
......
......@@ -9,28 +9,11 @@
* @license AGPL-3.0
*/
class CRM_Civiconfig_Entity_CustomGroup extends CRM_Civiconfig_Entity {
protected $_apiParams = array();
/**
* CRM_Civiconfig_CustomGroup constructor.
*/
public function __construct() {
$this->_apiParams = array();
}
/**
* Method to validate params for create
*
* @param $params
* @throws Exception
*/
private function validateCreateParams($params) {
if (!isset($params['name']) || empty($params['name']) || !isset($params['extends']) ||
empty($params['extends'])) {
throw new \CRM_Civiconfig_EntityException("Missing mandatory parameter 'name' and/or 'extends' in class " . get_class() . ".");
}
$this->buildApiParams($params);
parent::__construct('CustomGroup');
}
/**
......@@ -42,139 +25,112 @@ class CRM_Civiconfig_Entity_CustomGroup extends CRM_Civiconfig_Entity {
*/
public function create(array $params) {
$fieldParamsArray = $params['fields'];
$id = parent::create($params);
$this->validateCreateParams($params);
$existing = $this->getWithName($this->_apiParams['name']);
if (isset($existing['id'])) {
$this->_apiParams['id'] = $existing['id'];
}
if (!isset($this->_apiParams['title']) || empty($this->_apiParams['title'])) {
$this->_apiParams['title'] = CRM_Civiconfig_Utils::buildLabelFromName($this->_apiParams['name']);
}
try {
$customGroup = civicrm_api3('CustomGroup', 'Create', $this->_apiParams);
} catch (\CiviCRM_API3_Exception $ex) {
throw new \CRM_Civiconfig_EntityException('Could not create or update custom group with name ' . $this->_apiParams['name']
. ' to extend ' . $this->_apiParams['extends'] . '. Error from API CustomGroup.Create: ' .
$ex->getMessage() . ", parameters : " . implode(";", $this->_apiParams) . '.');
}
$created = $customGroup['values'][$customGroup['id']];
$customFieldCreator = new CRM_Civiconfig_Entity_CustomField();
foreach ($fieldParamsArray as $customFieldData) {
$customFieldData['custom_group_id'] = $created['id'];
$customField = new CRM_Civiconfig_Entity_CustomField();
$customField->create($customFieldData);
$customFieldData['custom_group_id'] = $id;
$customFieldCreator->create($customFieldData);
}
// remove custom fields that are still on install but no longer in config
CRM_Civiconfig_Entity_CustomField::removeUnwantedCustomFields($created['id'], $params);
CRM_Civiconfig_Entity_CustomField::removeUnwantedCustomFields($id, $params);
return $created;
return $id;
}
/**
* Method to get custom group with name
* Manipulate $params before entity creation.
*
* @param string $name
* @return array|bool
*/
public function getWithName($name) {
try {
return civicrm_api3('CustomGroup', 'Getsingle', array('name' => $name));
} catch (\CiviCRM_API3_Exception $ex) {
return FALSE;
}
}
/**
* Method to build api param list
* TODO: This function is too complex and can probably be refactored.
*
* @param array $params
* @param array $params params that will be used for entity creation
* @param array $existing existing entity (if available)
*/
protected function buildApiParams($params) {
// This can probably be refactored as well.
$this->_apiParams = array();
foreach ($params as $name => $value) {
if ($name != 'fields') {
$this->_apiParams[$name] = $value;
}
protected function prepareParams(array &$params, array $existing = []) {
if (empty($params['title'])) {
$params['title'] = CRM_Civiconfig_Utils::buildLabelFromName($params['name']);
}
switch ($this->_apiParams['extends']) {
parent::prepareParams($params, $existing);