diff --git a/CRM/FormProcessor/BAO/FormProcessor.php b/CRM/FormProcessor/BAO/FormProcessor.php index 99f65d07d0d28611aa65d8127f4723b63806088b..50f22a9c13e755158e7baca135bd9a43644958e6 100644 --- a/CRM/FormProcessor/BAO/FormProcessor.php +++ b/CRM/FormProcessor/BAO/FormProcessor.php @@ -27,7 +27,9 @@ $formProcessor->find(); while ($formProcessor->fetch()) { $row = array(); - self::storeValues($formProcessor, $row); + self::storeValues($formProcessor, $row); + $row['inputs'] = array_values(CRM_FormProcessor_BAO_FormProcessorInput::getValues(array('form_processor_id' => $formProcessor->id))); + $result[$row['id']] = $row; } return $result; @@ -95,6 +97,9 @@ CRM_Utils_Hook::pre('delete', 'FormProcessor', $id, CRM_Core_DAO::$_nullArray); + // First delete all inputs + CRM_FormProcessor_BAO_FormProcessorInput::deleteWithFormProcessorId($id); + $rule = new CRM_FormProcessor_BAO_FormProcessor(); $rule->id = $id; $rule->delete(); diff --git a/CRM/FormProcessor/BAO/FormProcessorInput.php b/CRM/FormProcessor/BAO/FormProcessorInput.php new file mode 100644 index 0000000000000000000000000000000000000000..a91312a18ceb017255349425dea70b3883c3b154 --- /dev/null +++ b/CRM/FormProcessor/BAO/FormProcessorInput.php @@ -0,0 +1,137 @@ +<?php + +use CRM_FormProcessor_ExtensionUtil as E; + +/** + * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org> + * @license http://www.gnu.org/licenses/agpl-3.0.html + */ +class CRM_FormProcessor_BAO_FormProcessorInput extends CRM_FormProcessor_DAO_FormProcessorInput { + + /** + * Function to get values + * + * @return array $result found rows with data + * @access public + * @static + */ + public static function getValues($params) { + $result = array(); + $input = new CRM_FormProcessor_BAO_FormProcessorInput(); + if (!empty($params)) { + $fields = self::fields(); + foreach ($params as $key => $value) { + if (isset($fields[$key])) { + $input->$key = $value; + } + } + } + $input->find(); + while ($input->fetch()) { + $row = array(); + self::storeValues($input, $row); + if (!empty($row['form_processor_id'])) { + $type = \Civi::service('form_processor_type_factory')->getTypeByName($row['type']); + if ($type) { + $row['type'] = $type->toArray(); + } + $result[$row['id']] = $row; + } else { + //invalid input because no there is no form processor + CRM_FormProcessor_BAO_FormProcessorInput::deleteWithId($row['id']); + } + } + return $result; + } + + /** + * Function to add or update form processor input + * + * @param array $params + * @return array $result + * @access public + * @throws Exception when params is empty + * @static + */ + public static function add($params) { + $result = array(); + if (empty($params)) { + throw new Exception('Params can not be empty when adding or updating a form processor input'); + } + + if (!empty($params['id'])) { + CRM_Utils_Hook::pre('edit', 'FormProcessorInput', $params['id'], $params); + } + else { + CRM_Utils_Hook::pre('create', 'FormProcessorInput', NULL, $params); + } + + $input = new CRM_FormProcessor_BAO_FormProcessorInput(); + $fields = self::fields(); + foreach ($params as $key => $value) { + if (isset($fields[$key])) { + $input->$key = $value; + } + } + $input->save(); + self::storeValues($input, $result); + + if (!empty($params['id'])) { + CRM_Utils_Hook::post('edit', 'FormProcessorInput', $input->id, $input); + } + else { + CRM_Utils_Hook::post('create', 'FormProcessorInput', $input->id, $input); + } + + return $result; + } + + /** + * Function to delete a form processor input with id + * + * @param int $id + * @throws Exception when $id is empty + * @access public + * @static + */ + public static function deleteWithId($id) { + if (empty($id)) { + throw new Exception('id can not be empty when attempting to delete a form processor input'); + } + + CRM_Utils_Hook::pre('delete', 'FormProcessorInput', $id, CRM_Core_DAO::$_nullArray); + + $input = new CRM_FormProcessor_BAO_FormProcessorInput(); + $input->id = $id; + if ($input->find(true)) { + $input->delete(); + } + + CRM_Utils_Hook::post('delete', 'FormProcessorInput', $id, CRM_Core_DAO::$_nullArray); + + return; + } + + /** + * Function to delete all inputs with a form processor id + * + * @param int $formProcessorId + * @access public + * @static + */ + public static function deleteWithFormProcessorId($formProcessorId) { + $input = new CRM_FormProcessor_BAO_FormProcessorInput(); + $input->form_processor_id = $formProcessorId; + $input->find(FALSE); + while ($input->fetch()) { + CRM_Utils_Hook::pre('delete', 'FormProcessorInput', $input->id, CRM_Core_DAO::$_nullArray); + + $input->id = $id; + $input->delete(); + + CRM_Utils_Hook::post('delete', 'FormProcessorInput', $input->id, CRM_Core_DAO::$_nullArray); + } + } + + +} \ No newline at end of file diff --git a/CRM/FormProcessor/DAO/FormProcessorInput.php b/CRM/FormProcessor/DAO/FormProcessorInput.php new file mode 100644 index 0000000000000000000000000000000000000000..88573225f7aff39451df924eb5bb15b5cbf33e65 --- /dev/null +++ b/CRM/FormProcessor/DAO/FormProcessorInput.php @@ -0,0 +1,120 @@ +<?php + +use CRM_FormProcessor_ExtensionUtil as E; + +/** + * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org> + * @license http://www.gnu.org/licenses/agpl-3.0.html + */ +class CRM_FormProcessor_DAO_FormProcessorInput extends CRM_Core_DAO { + /** + * static instance to hold the field values + * + * @var array + * @static + */ + static $_fields = null; + static $_export = null; + /** + * empty definition for virtual function + */ + static function getTableName() { + return 'civicrm_form_processor_input'; + } + /** + * returns all the column names of this table + * + * @access public + * @return array + */ + public static function &fields() { + if (!(self::$_fields)) { + self::$_fields = array( + 'id' => array( + 'name' => 'id', + 'title' => E::ts('ID'), + 'type' => CRM_Utils_Type::T_INT, + 'required' => true + ), + 'form_processor_id' => array( + 'name' => 'form_processor_id', + 'title' => E::ts('Form Processor ID'), + 'type' => CRM_Utils_Type::T_INT, + 'required' => true, + 'FKApiName' => 'FormProcessor', + ), + 'name' => array( + 'name' => 'name', + 'title' => E::ts('Name'), + 'type' => CRM_Utils_Type::T_STRING, + 'maxlength' => 80, + 'required' => true, + ) , + 'type' => array( + 'name' => 'type', + 'title' => E::ts('Type'), + 'type' => CRM_Utils_Type::T_STRING, + 'maxlength' => 80, + 'required' => true, + ), + 'is_required' => array( + 'name' => 'is_required', + 'title' => E::ts('Is required'), + 'type' => CRM_Utils_Type::T_INT, + ), + 'default_value' => array( + 'name' => 'default_value', + 'title' => E::ts('Default Value'), + 'type' => CRM_Utils_Type::T_STRING, + 'maxlength' => 256, + 'required' => true, + ), + ); + } + return self::$_fields; + } + /** + * Returns an array containing, for each field, the array key used for that + * field in self::$_fields. + * + * @access public + * @return array + */ + public static function &fieldKeys() { + if (!(self::$_fieldKeys)) { + self::$_fieldKeys = array( + 'id' => 'id', + 'form_processor_id' => 'form_processor_id', + 'name' => 'name', + 'type' => 'type', + 'is_required' => 'is_required', + 'default_value' => 'default_value', + ); + } + return self::$_fieldKeys; + } + /** + * returns the list of fields that can be exported + * + * @access public + * return array + * @static + */ + static function &export($prefix = false) + { + if (!(self::$_export)) { + self::$_export = array(); + $fields = self::fields(); + foreach($fields as $name => $field) { + if (CRM_Utils_Array::value('export', $field)) { + if ($prefix) { + self::$_export['activity'] = & $fields[$name]; + } else { + self::$_export[$name] = & $fields[$name]; + } + } + } + } + return self::$_export; + } +} \ No newline at end of file diff --git a/Civi/FormProcessor/API/Provider.php b/Civi/FormProcessor/API/Provider.php index 77f6f7693d567577d8e0d47e1e9cf34cb17619fe..ca9a210e8abb08b0f2cc943af08762441f7f9473 100644 --- a/Civi/FormProcessor/API/Provider.php +++ b/Civi/FormProcessor/API/Provider.php @@ -8,7 +8,11 @@ use \Civi\API\Provider\ProviderInterface as API_ProviderInterface; - +/** + * This class connects the enabled form processors to + * the the api interface of CiviCRM. That way the form processors + * could be executed over the api. + */ class Provider implements API_ProviderInterface { public function __construct() { @@ -34,7 +38,7 @@ */ public function getEntityNames($version) { return array( - 'FormProcessorExecuter' + 'FormProcessorExecutor' ); } diff --git a/Civi/FormProcessor/Type/AbstractType.php b/Civi/FormProcessor/Type/AbstractType.php new file mode 100644 index 0000000000000000000000000000000000000000..f1312b1f5525b5104abc2eadc447d7c11864045b --- /dev/null +++ b/Civi/FormProcessor/Type/AbstractType.php @@ -0,0 +1,54 @@ +<?php + +/** + * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org> + * @license http://www.gnu.org/licenses/agpl-3.0.html + */ + + namespace Civi\FormProcessor\Type; + + abstract class AbstractType { + + protected $name; + + protected $label; + + public function __construct($name, $label) { + $this->name = $name; + $this->label = $label; + } + + /** + * Returns whether the provided value is a valid + * + * @param mixed $value + * @return bool + */ + abstract public function isValueValidForType($value); + + /** + * Returns the name of the type. + * + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * Returns the label of the type. + * + * @return string + */ + public function getLabel() { + return $this->label; + } + + public function toArray() { + return array( + 'name' => $this->name, + 'label' => $this->label, + ); + } + + } diff --git a/Civi/FormProcessor/Type/Factory.php b/Civi/FormProcessor/Type/Factory.php new file mode 100644 index 0000000000000000000000000000000000000000..1151d9e1270eb26354895acf098f685b4561c9a8 --- /dev/null +++ b/Civi/FormProcessor/Type/Factory.php @@ -0,0 +1,76 @@ +<?php + +/** + * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org> + * @license http://www.gnu.org/licenses/agpl-3.0.html + */ + + namespace Civi\FormProcessor\Type; + + use \Civi\FormProcessor\Type\AbstractType; + use \Civi\FormProcessor\Type\GenericType; + + use CRM_FormProcessor_ExtensionUtil as E; + + class Factory { + + /** + * @var array<AbstractType> + */ + protected $types = array(); + + public function __construct() { + $this->addType(new GenericType('Integer', E::ts('Numeric (no-decimal)'))); + $this->addType(new GenericType('Float', E::ts('Numeric (with-decimal)'))); + $this->addType(new GenericType('String', E::ts('Short text'))); + $this->addType(new GenericType('Text', E::ts('Long text'))); + $this->addType(new GenericType('Date', E::ts('Date'))); + $this->addType(new GenericType('Time', E::ts('Time'))); + $this->addType(new GenericType('Boolean', E::ts('Yes/No'))); + $this->addType(new GenericType('Email', E::ts('E-mail'))); + } + + /** + * Add a type + * + * @param AbstractType $type + */ + public function addType(AbstractType $type) { + $this->types[$type->getName()] = $type; + return $this; + } + + /** + * Return the type + * + * @param string $name + * @return AbstractType|null + */ + public function getTypeByName($name) { + if (isset($this->types[$name])) { + return $this->types[$name]; + } + return null; + } + + /** + * @return array<AbstractType> + */ + public function getTypes() { + return $this->types; + } + + /** + * Returns an array with the name and label + * + * @return array<string> + */ + public function getTypeLabels() { + $return = array(); + foreach($this->types as $type) { + $return[] = $type->toArray(); + } + return $return; + } + + } diff --git a/Civi/FormProcessor/Type/GenericType.php b/Civi/FormProcessor/Type/GenericType.php new file mode 100644 index 0000000000000000000000000000000000000000..9c569ddf2bc0ff7f2788249d99dee3cdbb814e21 --- /dev/null +++ b/Civi/FormProcessor/Type/GenericType.php @@ -0,0 +1,21 @@ +<?php + +/** + * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org> + * @license http://www.gnu.org/licenses/agpl-3.0.html + */ + + namespace Civi\FormProcessor\Type; + + use \Civi\FormProcessor\Type\AbstractType; + + class GenericType extends AbstractType { + + public function isValueValidForType($value) { + if (\CRM_Utils_Type::validate($value, $this->name, false) === NULL) { + return false; + } + return true; + } + + } diff --git a/ang/form_processor.ang.php b/ang/form_processor.ang.php index 735fa16be0bbff828e68c1e1e867d4d67a9fb040..a49e2aa66a5f902b576fc7e5559f79128f2a3954 100644 --- a/ang/form_processor.ang.php +++ b/ang/form_processor.ang.php @@ -20,5 +20,6 @@ return array ( ), 'settings' => array ( + 'inputTypes' => \Civi::service('form_processor_type_factory')->getTypeLabels(), ), ); diff --git a/ang/form_processor/AddInputDialogCtrl.html b/ang/form_processor/AddInputDialogCtrl.html new file mode 100644 index 0000000000000000000000000000000000000000..24b22c08431a2234259c69014a569361e13f95b8 --- /dev/null +++ b/ang/form_processor/AddInputDialogCtrl.html @@ -0,0 +1,45 @@ +<div ng-controller="InputDialogCtrl" class=""> + <div class="crm-block" ng-form="addInputForm" crm-ui-id-scope> + <div class="crm-group"> + + <div crm-ui-field="{name: 'formProcessorDetailForm.type', title: ts('Type')}"> + <div>{{model.input.type.label}}</div> + </div> + + <div crm-ui-field="{name: 'addInputForm.name', title: ts('Name')}"> + <input + crm-ui-id="addInputForm.name" + type="text" + name="name" + ng-model="model.input.name" + class="big crm-form-text" + required + /> + <div ng-show="invalidName"> + <em>{{ts('WARNING: The name of the formprocessor is invalid (Only lowercase characters and _ are allowed).')}}</em> + </div> + <div ng-show="nameExists"> + <em>{{ts('WARNING: The name of the formprocessor already exists.')}}</em> + </div> + </div> + + <div crm-ui-field="{title: ts('Is required?')}"> + <input name="is_required" type="checkbox" ng-model="model.input.is_required" ng-true-value="'1'" ng-false-value="'0'"/> + </div> + + <div crm-ui-field="{name: 'addInputForm.default_value', title: ts('Default value')}"> + <input + crm-ui-id="addInputForm.default_value" + type="text" + name="title" + ng-model="model.input.default_value" + class="big crm-form-text" + /> + </div> + + <button crm-icon="fa-check" ng-click="saveClick()">{{ts('Add input')}}</button> + <button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button> + + </div> + </div> +</div> diff --git a/ang/form_processor/EditInputDialogCtrl.html b/ang/form_processor/EditInputDialogCtrl.html new file mode 100644 index 0000000000000000000000000000000000000000..47faf5872824d12064f4e6f34363899019c5f7f2 --- /dev/null +++ b/ang/form_processor/EditInputDialogCtrl.html @@ -0,0 +1,45 @@ +<div ng-controller="InputDialogCtrl" class=""> + <div class="crm-block" ng-form="editInputForm" crm-ui-id-scope> + <div class="crm-group"> + + <div crm-ui-field="{name: 'formProcessorDetailForm.type', title: ts('Type')}"> + <div>{{model.input.type.label}}</div> + </div> + + <div crm-ui-field="{name: 'editInputForm.name', title: ts('Name')}"> + <input + crm-ui-id="editInputForm.name" + type="text" + name="name" + ng-model="model.input.name" + class="big crm-form-text" + required + /> + <div ng-show="invalidName"> + <em>{{ts('WARNING: The name of the formprocessor is invalid (Only lowercase characters and _ are allowed).')}}</em> + </div> + <div ng-show="nameExists"> + <em>{{ts('WARNING: The name of the formprocessor already exists.')}}</em> + </div> + </div> + + <div crm-ui-field="{title: ts('Is required?')}"> + <input name="is_required" type="checkbox" ng-model="model.input.is_required" ng-true-value="'1'" ng-false-value="'0'"/> + </div> + + <div crm-ui-field="{name: 'editInputForm.default_value', title: ts('Default value')}"> + <input + crm-ui-id="editInputForm.default_value" + type="text" + name="title" + ng-model="model.input.default_value" + class="big crm-form-text" + /> + </div> + + <button crm-icon="fa-check" ng-click="saveClick()">{{ts('Update input')}}</button> + <button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button> + + </div> + </div> +</div> diff --git a/ang/form_processor/FormProcessors.js b/ang/form_processor/FormProcessors.js index 28f46dbeafb8f6f703c305b1a7acceb9097d6a98..b5bd75912fa0e22559e9a810709d19f613894860 100644 --- a/ang/form_processor/FormProcessors.js +++ b/ang/form_processor/FormProcessors.js @@ -13,7 +13,7 @@ } } }); - $routeProvider.when('/formProcessor/new', { + /*$routeProvider.when('/formProcessor/new', { templateUrl: '~/form_processor/edit.html', controller: 'FormProcessorCtrl', resolve: { @@ -25,28 +25,33 @@ }; } } - }); + });*/ $routeProvider.when('/formProcessor/:id', { templateUrl: '~/form_processor/edit.html', controller: 'FormProcessorCtrl', resolve: { - formProcessor: function($route, crmApi) { - return crmApi('FormProcessor', 'getsingle', { - id: $route.current.params.id, - options: {limit: 0} - }); - } + apiCalls: function($route, crmApi) { + var reqs = {}; + if ($route.current.params.id !== 'new') { + reqs.formProcessor = ['FormProcessor', 'getsingle', { + id: $route.current.params.id + }]; + } + return crmApi(reqs); + } } }); } ); - angular.module('form_processor').controller('FormProcessorCtrl', function($scope, crmApi, formProcessor) { + angular.module('form_processor').controller('FormProcessorCtrl', function($scope, dialogService, crmApi, apiCalls) { var ts = $scope.ts = CRM.ts(null); - $scope.formProcessor = formProcessor; + $scope.formProcessor = apiCalls.formProcessor; $scope.locks = {name: true}; $scope.isNameValid = false; + $scope.inputTypes = CRM.form_processor.inputTypes; + $scope.deletedInputs = []; $scope.$watch('formProcessor.name', function(newFormProcessorName, oldFrmProcessorName) { // Watch for changes in the name field @@ -75,10 +80,69 @@ result.then(function(data) { if (data.is_error === 0 || data.is_error == '0') { $scope.formProcessor.id = data.id; + + angular.forEach($scope.deletedInputs, function(input, key) { + if (input.id) { + crmApi('FormProcessorInput', 'delete', {'id': input.id}, true); + } + }); + + angular.forEach($scope.formProcessor.inputs, function(input, key) { + input.form_processor_id = $scope.formProcessor.id; + input.type = input.type.name; + crmApi('FormProcessorInput', 'create', input, true); + }); window.location.href = '#/formProcessors'; } }); }; + + $scope.removeInput = function removeInput(input) { + var index = $scope.formProcessor.inputs.indexOf(input); + if (index >= 0) { + $scope.formProcessor.inputs.splice(index, 1); + $scope.deletedInputs.push(input); + } + }; + + // Open a dialog for adding an input + $scope.addInput = function addInput(inputType) { + var options = CRM.utils.adjustDialogDefaults({ + autoOpen: false, + width: '40%', + height: 'auto', + title: ts('Add input') + }); + var model = { + formProcessor: $scope.formProcessor, + input: { + type: inputType, + 'name': '', + 'is_required': 0, + 'default_value': '', + } + }; + dialogService.open('InputDialog', '~/form_processor/AddInputDialogCtrl.html', model, options) + .then( + function(data) { + $scope.formProcessor.inputs.push(data.input); + }); + }; + + // Open a dialog for editting an input + $scope.editInput = function editInput(input) { + var options = CRM.utils.adjustDialogDefaults({ + autoOpen: false, + width: '40%', + height: 'auto', + title: ts('Add input') + }); + var model = { + formProcessor: $scope.formProcessor, + input: input + }; + dialogService.open('InputDialog', '~/form_processor/EditInputDialogCtrl.html', model, options); + }; }); angular.module('form_processor').controller('FormProcessorListCtrl', function($scope, crmApi, formProcessors) { diff --git a/ang/form_processor/InputDialogCtrl.js b/ang/form_processor/InputDialogCtrl.js new file mode 100644 index 0000000000000000000000000000000000000000..b24ab2b4f070d650cd0199fe4e50158d4114d11f --- /dev/null +++ b/ang/form_processor/InputDialogCtrl.js @@ -0,0 +1,32 @@ +(function(angular, $, _) { + + angular.module('form_processor').controller('InputDialogCtrl', function InputDialogCtrl($scope, dialogService) { + $scope.ts = CRM.ts(null); + + $scope.invalidName = false; + $scope.nameExists = false; + + $scope.$watch('model.input.name', function(newName, oldName) { + $scope.invalidName = newName && !newName.match(/^[a-z0-9_]+$/) ? true : false; + $scope.nameExists = false; + if (newName && !$scope.invalidName) { + // Check whether the name already exists + angular.forEach($scope.model.formProcessor.inputs, function(input, key) { + if (input != $scope.model.input && input.name == newName) { + $scope.nameExists = true; + } + }); + } + }, true); + + $scope.saveClick = function() { + dialogService.close('InputDialog', $scope.model); + }; + + $scope.cancelClick = function() { + dialogService.cancel('InputDialog'); + }; + + }); + +})(angular, CRM.$, CRM._); diff --git a/ang/form_processor/edit.html b/ang/form_processor/edit.html index df6ba1601aff059d482f93ceef1b6aa3b48dad21..9e59cfaa4746fff0a4eeae8ec6da3cdd21ffb65d 100644 --- a/ang/form_processor/edit.html +++ b/ang/form_processor/edit.html @@ -10,6 +10,8 @@ Required vars: formProcessor <div class="crm-block crm-form-block crmFormProcessor"> <div ng-include="'~/form_processor/formProcessorDetails.html'"></div> + + <div ng-include="'~/form_processor/formProcessorInputTable.html'"></div> <div class="crm-submit-buttons"> <button crm-icon="fa-check" ng-click="editFormProcessorForm.$setPristine(); save()" ng-disabled="editFormProcessorForm.$invalid || !isNameValid"> diff --git a/ang/form_processor/formProcessorInputTable.html b/ang/form_processor/formProcessorInputTable.html new file mode 100644 index 0000000000000000000000000000000000000000..b7832478e0f916fece475d0251ccfd1099b20112 --- /dev/null +++ b/ang/form_processor/formProcessorInputTable.html @@ -0,0 +1,46 @@ +<!-- +Controller: FormProcessorCtrl +Required vars: formProcessor +--> +<div class="crm-block" ng-form="formProcessorInputsForm" crm-ui-id-scope> + <h3>{{ts('Inputs')}}</h3> +<table> + <thead> + <tr> + <th>{{ts('Name')}}</th> + <th>{{ts('Type')}}</th> + <th>{{ts('Is required')}}</th> + <th>{{ts('Default value')}}</th> + <th></th> + </tr> + </thead> + <tbody> + <tr ng-repeat="input in formProcessor.inputs | orderBy:'name'" ng-class-even="'crm-entity even-row even'" ng-class-odd="'crm-entity odd-row odd'"> + <td>{{input.name}}</td> + <td>{{input.type.label}}</td> + <td>{{input.is_required == 1 ? ts('Yes') : ts('No')}}</td> + <td>{{input.default_value}}</td> + <td> + <a crm-icon="fa-edit" class="crm-hover-button" ng-click="editInput(input)" title="{{ts('Edit')}}">{{ts('Edit')}}</a> + <a crm-icon="fa-trash" class="crm-hover-button" ng-click="removeInput(input)" title="{{ts('Remove')}}">{{ts('Remove')}}</a> + </td> + </tr> + </tbody> + + <tfoot> + <tr class="addRow"> + <td colspan="4"> + <select + crm-ui-id="formProcessorInputsForm.type" + name="type" + ui-jq="select2" + ui-options="{dropdownAutoWidth : true, allowClear: true}" + ng-model="inputType" + ng-options="inputType.label for inputType in inputTypes"> + <option value="">{{ts('- Select input type -')}}</option> + </select> + <button crm-icon="fa-check" ng-click="addInput(inputType)">{{ts('Add input')}}</button> + </td> + </tr> + </tfoot> +</table> \ No newline at end of file diff --git a/api/v3/FormProcessor/Create.php b/api/v3/FormProcessor/Create.php index 0e0a465f153ba414b1448a9b39e76df577e84ba9..181fee3752d9972a8dfe36add83fcf3137d55574 100644 --- a/api/v3/FormProcessor/Create.php +++ b/api/v3/FormProcessor/Create.php @@ -3,7 +3,7 @@ use CRM_FormProcessor_ExtensionUtil as E; /** - * CiviRuleRule.Create API specification (optional) + * FormProcessor.Create API specification (optional) * This is used for documentation and validation. * * @param array $spec description of fields supported by this API call @@ -40,7 +40,7 @@ function _civicrm_api3_form_processor_create_spec(&$spec) { } /** - * CiviRuleRule.Create API + * FormProcessor.Create API * * @param array $params * @return array API result descriptor @@ -66,7 +66,8 @@ function civicrm_api3_form_processor_create($params) { $params['created_date'] = date('Ymd'); $params['created_user_id'] = $userId; } - $returnValues = CRM_FormProcessor_BAO_FormProcessor::add($params); + $returnValue = CRM_FormProcessor_BAO_FormProcessor::add($params); + $returnValues[$returnValue['id']] = $returnValue; return civicrm_api3_create_success($returnValues, $params, 'FormProcessor', 'Create'); } diff --git a/api/v3/FormProcessor/Delete.php b/api/v3/FormProcessor/Delete.php index f509d487785c9a2f8bd19e98e93ef7e316c703f1..ac417589a3a134b537543b1755ef86450b988c12 100644 --- a/api/v3/FormProcessor/Delete.php +++ b/api/v3/FormProcessor/Delete.php @@ -3,7 +3,7 @@ use CRM_FormProcessor_ExtensionUtil as E; /** - * CiviRuleRule.Delete API specification (optional) + * FormProcessor.Delete API specification (optional) * This is used for documentation and validation. * * @param array $spec description of fields supported by this API call @@ -19,7 +19,7 @@ function _civicrm_api3_form_processor_Delete_spec(&$spec) { } /** - * CiviRuleRule.Delete API + * FormProcessor.Delete API * * @param array $params * @return array API result descriptor diff --git a/api/v3/FormProcessor/Get.php b/api/v3/FormProcessor/Get.php index ff1e2a0c74e9d1b641605ee2f7fe43aa706e9343..43bf53e8f8a83bd203f1d0b0372c92b5d268e7a8 100644 --- a/api/v3/FormProcessor/Get.php +++ b/api/v3/FormProcessor/Get.php @@ -1,6 +1,6 @@ <?php /** - * CiviRuleRule.Get API + * FormProcessorInput.Get API * * @param array $params * @return array API result descriptor @@ -14,7 +14,7 @@ function civicrm_api3_form_processor_get($params) { } /** - * CiviRuleRule.Create API specification (optional) + * FormProcessorInput.Get API specification (optional) * This is used for documentation and validation. * * @param array $spec description of fields supported by this API call diff --git a/api/v3/FormProcessor/Validatename.php b/api/v3/FormProcessor/Validatename.php index 23df90982f7f55f9d34f9b525454506b5f572c73..f21098d3030f857145ba252f3fa460b31b57964b 100644 --- a/api/v3/FormProcessor/Validatename.php +++ b/api/v3/FormProcessor/Validatename.php @@ -3,7 +3,7 @@ use CRM_FormProcessor_ExtensionUtil as E; /** - * CiviRuleRule.Get API + * FormProcessor.Validatename API * * @param array $params * @return array API result descriptor @@ -20,7 +20,7 @@ function civicrm_api3_form_processor_validatename($params) { } /** - * CiviRuleRule.Create API specification (optional) + * FormProcessor.Validatename API specification (optional) * This is used for documentation and validation. * * @param array $spec description of fields supported by this API call diff --git a/api/v3/FormProcessorInput/Create.php b/api/v3/FormProcessorInput/Create.php new file mode 100644 index 0000000000000000000000000000000000000000..833fa22f0392c6916a63942316b45ae951b27298 --- /dev/null +++ b/api/v3/FormProcessorInput/Create.php @@ -0,0 +1,63 @@ +<?php + +use CRM_FormProcessor_ExtensionUtil as E; + +/** + * FormProcessorInput.Create API specification (optional) + * This is used for documentation and validation. + * + * @param array $spec description of fields supported by this API call + * @return void + * @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards + */ +function _civicrm_api3_form_processor_input_create_spec(&$spec) { + $spec['id'] = array( + 'title' => E::ts('ID'), + 'type' => CRM_Utils_Type::T_INT, + 'api_required' => false + ); + $spec['form_processor_id'] = array( + 'title' => E::ts('Form Processor ID'), + 'type' => CRM_Utils_Type::T_INT, + 'api_required' => true, + 'FKApiName' => 'FormProcessor', + ); + $spec['name'] = array( + 'title' => E::ts('Name'), + 'type' => CRM_Utils_Type::T_STRING, + 'api_required' => true + ); + $spec['type'] = array( + 'title' => E::ts('Type'), + 'type' => CRM_Utils_Type::T_STRING, + 'api_required' => true + ); + $spec['is_required'] = array( + 'title' => E::ts('Is required'), + 'type' => CRM_Utils_Type::T_BOOLEAN, + 'api_required' => false, + 'api.default' => false, + ); + $spec['default_value'] = array( + 'title' => E::ts('Default Value'), + 'type' => CRM_Utils_Type::T_STRING, + 'api_required' => false + ); +} + +/** + * FormProcessorInput.Create API + * + * @param array $params + * @return array API result descriptor + * @see civicrm_api3_create_success + * @see civicrm_api3_create_error + * + * + */ +function civicrm_api3_form_processor_input_create($params) { + $returnValue = CRM_FormProcessor_BAO_FormProcessorInput::add($params); + $returnValues[$returnValue['id']] = $returnValue; + return civicrm_api3_create_success($returnValues, $params, 'FormProcessorInput', 'Create'); +} + diff --git a/api/v3/FormProcessorInput/Delete.php b/api/v3/FormProcessorInput/Delete.php new file mode 100644 index 0000000000000000000000000000000000000000..86503957996227552c7f8070eca6bfbbf452a727 --- /dev/null +++ b/api/v3/FormProcessorInput/Delete.php @@ -0,0 +1,37 @@ +<?php + +use CRM_FormProcessor_ExtensionUtil as E; + +/** + * FormProcessorInput.Delete API specification (optional) + * This is used for documentation and validation. + * + * @param array $spec description of fields supported by this API call + * @return void + * @see http://wiki.civicrm.org/confluence/display/CRMDOC/API+Architecture+Standards + */ +function _civicrm_api3_form_processor_input_Delete_spec(&$spec) { + $spec['id'] = array( + 'title' => E::ts('ID'), + 'type' => CRM_Utils_Type::T_INT, + 'api_required' => true + ); +} + +/** + * FormProcessorInput.Delete API + * + * @param array $params + * @return array API result descriptor + * @see civicrm_api3_create_success + * @see civicrm_api3_create_error + * @throws API_Exception + */ +function civicrm_api3_form_processor_input_Delete($params) { + if (!array_key_exists('id', $params) || empty($params['id'])) { + throw new API_Exception('Parameter id is mandatory and can not be empty in ' . __METHOD__, 0010); + } else { + return civicrm_api3_create_success(CRM_FormProcessor_BAO_FormProcessorInput::deleteWithId($params['id']), $params, 'FormProcessorInput', 'Delete'); + } +} + diff --git a/api/v3/FormProcessorInput/Get.php b/api/v3/FormProcessorInput/Get.php new file mode 100644 index 0000000000000000000000000000000000000000..9a2cae6e59179895c3dd2905d5b6646335470867 --- /dev/null +++ b/api/v3/FormProcessorInput/Get.php @@ -0,0 +1,30 @@ +<?php +/** + * FormProcessorInput.Get API + * + * @param array $params + * @return array API result descriptor + * @see civicrm_api3_create_success + * @see civicrm_api3_create_error + * @throws API_Exception + */ +function civicrm_api3_form_processor_input_get($params) { + $returnValues = CRM_FormProcessor_BAO_FormProcessorInput::getValues($params); + return civicrm_api3_create_success($returnValues, $params, 'FormProcessorInput', 'Get'); +} + +/** + * FormProcessorInput.Get API specification (optional) + * This is used for documentation and validation. + * + * @param array $spec description of fields supported by this API call + * @return void + * @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards + */ +function _civicrm_api3_form_processor_input_get_spec(&$spec) { + $fields = CRM_FormProcessor_BAO_FormProcessorInput::fields(); + foreach($fields as $fieldname => $field) { + $spec[$fieldname] = $field; + } +} + diff --git a/form_processor.php b/form_processor.php index 8d0398a7eea4b83f1d44147befc62778138222bb..68425bf84151560995f71177bfefb7cf08205f49 100644 --- a/form_processor.php +++ b/form_processor.php @@ -3,12 +3,23 @@ require_once 'form_processor.civix.php'; use CRM_FormProcessor_ExtensionUtil as E; -function form_processor_civicrm_container($container) { +use \Symfony\Component\DependencyInjection\ContainerBuilder; +use \Symfony\Component\DependencyInjection\Definition; + +/** + * Implements hook_civicrm_container() + * + * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_container/ + */ +function form_processor_civicrm_container(ContainerBuilder $container) { + // Register the TypeFactory + $container->setDefinition('form_processor_type_factory', new Definition('Civi\FormProcessor\Type\Factory')); + + // Register our API Provider. // The API provider is used to process incoming api calls and process them // with the form processor logic. - - $apiProviderDefinition = new \Symfony\Component\DependencyInjection\Definition('Civi\FormProcessor\API\Provider'); + $apiProviderDefinition = new Definition('Civi\FormProcessor\API\Provider'); $apiKernelDefinition = $container->getDefinition('civi_api_kernel'); $apiKernelDefinition->addMethodCall('registerApiProvider', array($apiProviderDefinition)); } diff --git a/sql/create_civicrm_form_processor.sql b/sql/create_civicrm_form_processor.sql index 0e171a8cf0a4dd077e88bfd50363caf3b8311d5d..aa39e963a6e2f8a9a46e7674687579473c4fcdf6 100644 --- a/sql/create_civicrm_form_processor.sql +++ b/sql/create_civicrm_form_processor.sql @@ -11,3 +11,14 @@ CREATE TABLE IF NOT EXISTS `civicrm_form_processor` ( PRIMARY KEY (`id`), UNIQUE INDEX `name_UNIQUE` (`name` ASC) ) ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS `civicrm_form_processor_input` ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + `form_processor_id` INT UNSIGNED NOT NULL, + `name` VARCHAR(80) NOT NULL, + `type` VARCHAR(80) NOT NULL, + `is_required` TINYINT NULL DEFAULT 0, + `default_value` VARCHAR(256) NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `name_id_UNIQUE` (`id`, `name` ASC) +) ENGINE = InnoDB; diff --git a/sql/uninstall.sql b/sql/uninstall.sql index a715ab70b7a58875ad3fa93ba0a4ea3882d5a106..084e627b4aa60ae559c885db6e4bd4812501e588 100644 --- a/sql/uninstall.sql +++ b/sql/uninstall.sql @@ -1 +1,2 @@ +DROP TABLE `civicrm_form_processor_input`; DROP TABLE `civicrm_form_processor`;