Skip to content
Snippets Groups Projects
Commit f1dcd2e0 authored by Tim Otten's avatar Tim Otten
Browse files

Merge pull request #2378 from totten/4.4-absence-data-helpers

HR-238 - Helpers
parents 144fb5a0 6bc90ee8
No related branches found
No related tags found
No related merge requests found
...@@ -635,5 +635,48 @@ class CRM_Utils_Array { ...@@ -635,5 +635,48 @@ class CRM_Utils_Array {
} }
return $default; return $default;
} }
/**
* Generate the Cartesian product of zero or more vectors
*
* @param array $dimensions list of dimensions to multiply; each key is a dimension name; each value is a vector
* @param array $template a base set of values included in every output
* @return array each item is a distinct combination of values from $dimensions
*
* For example, the product of
* {
* fg => {red, blue},
* bg => {white, black}
* }
* would be
* {
* {fg => red, bg => white},
* {fg => red, bg => black},
* {fg => blue, bg => white},
* {fg => blue, bg => black}
* }
*/
static function product($dimensions, $template = array()) {
if (empty($dimensions)) {
return array($template);
}
foreach ($dimensions as $key => $value) {
$firstKey = $key;
$firstValues = $value;
break;
}
unset($dimensions[$key]);
$results = array();
foreach ($firstValues as $firstValue) {
foreach (self::product($dimensions, $template) as $result) {
$result[$firstKey] = $firstValue;
$results[] = $result;
}
}
return $results;
}
} }
...@@ -32,14 +32,14 @@ ...@@ -32,14 +32,14 @@
}; };
switch (method) { switch (method) {
case 'read': case 'read':
CRM.api(model.crmEntityName, 'get', model.toCrmCriteria(), apiOptions); CRM.api(model.crmEntityName, model.toCrmAction('get'), model.toCrmCriteria(), apiOptions);
break; break;
// replace all entities matching "x.crmCriteria" with new entities in "x.models" // replace all entities matching "x.crmCriteria" with new entities in "x.models"
case 'crm-replace': case 'crm-replace':
var params = this.toCrmCriteria(); var params = this.toCrmCriteria();
params.version = 3; params.version = 3;
params.values = this.toJSON(); params.values = this.toJSON();
CRM.api(model.crmEntityName, 'replace', params, apiOptions); CRM.api(model.crmEntityName, model.toCrmAction('replace'), params, apiOptions);
break; break;
default: default:
apiOptions.error({is_error: 1, error_message: "CRM.Backbone.sync(" + method + ") not implemented for collections"}); apiOptions.error({is_error: 1, error_message: "CRM.Backbone.sync(" + method + ") not implemented for collections"});
...@@ -74,9 +74,9 @@ ...@@ -74,9 +74,9 @@
params.options || (params.options = {}); params.options || (params.options = {});
params.options.reload = 1; params.options.reload = 1;
if (!model._isDuplicate) { if (!model._isDuplicate) {
CRM.api(model.crmEntityName, 'create', params, apiOptions); CRM.api(model.crmEntityName, model.toCrmAction('create'), params, apiOptions);
} else { } else {
CRM.api(model.crmEntityName, 'duplicate', params, apiOptions); CRM.api(model.crmEntityName, model.toCrmAction('duplicate'), params, apiOptions);
} }
break; break;
case 'read': case 'read':
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
apiOptions.error({is_error: 1, error_message: 'Missing ID for ' + model.crmEntityName}); apiOptions.error({is_error: 1, error_message: 'Missing ID for ' + model.crmEntityName});
return; return;
} }
CRM.api(model.crmEntityName, apiAction, params, apiOptions); CRM.api(model.crmEntityName, model.toCrmAction(apiAction), params, apiOptions);
break; break;
default: default:
apiOptions.error({is_error: 1, error_message: "CRM.Backbone.sync(" + method + ") not implemented for models"}); apiOptions.error({is_error: 1, error_message: "CRM.Backbone.sync(" + method + ") not implemented for models"});
...@@ -116,6 +116,10 @@ ...@@ -116,6 +116,10 @@
// Defaults - if specified in ModelClass, preserve // Defaults - if specified in ModelClass, preserve
_.defaults(ModelClass.prototype, { _.defaults(ModelClass.prototype, {
crmEntityName: crmEntityName, crmEntityName: crmEntityName,
crmActions: {}, // map: string backboneActionName => string serverSideActionName
toCrmAction: function(action) {
return this.crmActions[action] ? this.crmActions[action] : action;
},
toCrmCriteria: function() { toCrmCriteria: function() {
return (this.get('id')) ? {id: this.get('id')} : {}; return (this.get('id')) ? {id: this.get('id')} : {};
}, },
...@@ -308,6 +312,10 @@ ...@@ -308,6 +312,10 @@
// Defaults - if specified in CollectionClass, preserve // Defaults - if specified in CollectionClass, preserve
_.defaults(CollectionClass.prototype, { _.defaults(CollectionClass.prototype, {
crmEntityName: CollectionClass.prototype.model.prototype.crmEntityName, crmEntityName: CollectionClass.prototype.model.prototype.crmEntityName,
crmActions: {}, // map: string backboneActionName => string serverSideActionName
toCrmAction: function(action) {
return this.crmActions[action] ? this.crmActions[action] : action;
},
toCrmCriteria: function() { toCrmCriteria: function() {
return (this.crmCriteria) ? _.extend({}, this.crmCriteria) : {}; return (this.crmCriteria) ? _.extend({}, this.crmCriteria) : {};
}, },
...@@ -365,6 +373,9 @@ ...@@ -365,6 +373,9 @@
} else if (options.crmCriteria) { } else if (options.crmCriteria) {
this.crmCriteria = options.crmCriteria; this.crmCriteria = options.crmCriteria;
} }
if (options.crmActions) {
this.crmActions = _.extend(this.crmActions, options.crmActions);
}
if (origInit) { if (origInit) {
return origInit.apply(this, arguments); return origInit.apply(this, arguments);
} }
......
...@@ -33,7 +33,7 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase { ...@@ -33,7 +33,7 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase {
$inputs[] = array( $inputs[] = array(
'lang' => 'en', 'lang' => 'en',
'msgid' => 'greeting', 'msgid' => 'greeting',
'familiar' => false, 'familiar' => FALSE,
'value' => 'Hello' 'value' => 'Hello'
); );
$inputs[] = array( $inputs[] = array(
...@@ -54,7 +54,7 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase { ...@@ -54,7 +54,7 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase {
$inputs[] = array( $inputs[] = array(
'lang' => 'en', 'lang' => 'en',
'msgid' => 'greeting', 'msgid' => 'greeting',
'familiar' => true, 'familiar' => TRUE,
'value' => 'Hey' 'value' => 'Hey'
); );
...@@ -82,4 +82,41 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase { ...@@ -82,4 +82,41 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase {
$this->assertEquals($expected, CRM_Utils_Array::collect('catWord', $arr)); $this->assertEquals($expected, CRM_Utils_Array::collect('catWord', $arr));
} }
function testProduct0() {
$actual = CRM_Utils_Array::product(
array(),
array('base data' => 1)
);
$this->assertEquals(array(
array('base data' => 1),
), $actual);
}
function testProduct1() {
$actual = CRM_Utils_Array::product(
array('dim1' => array('a', 'b')),
array('base data' => 1)
);
$this->assertEquals(array(
array('base data' => 1, 'dim1' => 'a'),
array('base data' => 1, 'dim1' => 'b'),
), $actual);
}
function testProduct3() {
$actual = CRM_Utils_Array::product(
array('dim1' => array('a', 'b'), 'dim2' => array('alpha', 'beta'), 'dim3' => array('one', 'two')),
array('base data' => 1)
);
$this->assertEquals(array(
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'alpha', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'alpha', 'dim3' => 'two'),
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'beta', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'beta', 'dim3' => 'two'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'alpha', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'alpha', 'dim3' => 'two'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'beta', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'beta', 'dim3' => 'two'),
), $actual);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment