X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=templates%2FCRM%2FAdmin%2FPage%2FAPIExplorer.js;h=e530b27a49b566139fc6d036690e2db7d7c3d1e4;hb=77099ee0f0fac9999a8e7a7746f06fd3a71e6032;hp=0a4f89e198bf79210efa9d6663385c32017a34a5;hpb=fc39f196c427ec3f13f2a240967bd36f426e9609;p=civicrm-core.git diff --git a/templates/CRM/Admin/Page/APIExplorer.js b/templates/CRM/Admin/Page/APIExplorer.js index 0a4f89e198..e530b27a49 100644 --- a/templates/CRM/Admin/Page/APIExplorer.js +++ b/templates/CRM/Admin/Page/APIExplorer.js @@ -10,7 +10,12 @@ fieldTpl = _.template($('#api-param-tpl').html()), optionsTpl = _.template($('#api-options-tpl').html()), returnTpl = _.template($('#api-return-tpl').html()), - chainTpl = _.template($('#api-chain-tpl').html()); + chainTpl = _.template($('#api-chain-tpl').html()), + + // Operators with special properties + BOOL = ['IS NULL', 'IS NOT NULL'], + TEXT = ['LIKE', 'NOT LIKE'], + MULTI = ['IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN']; /** * Call prettyPrint function if it successfully loaded from the cdn @@ -28,7 +33,7 @@ function addField(name) { $('#api-params').append($(fieldTpl({name: name || ''}))); var $row = $('tr:last-child', '#api-params'); - $('.api-param-name', $row).crmSelect2({ + $('input.api-param-name', $row).crmSelect2({ data: fields.concat({id: '-', text: ts('Other') + '...'}) }).change(); } @@ -126,9 +131,9 @@ */ function getActions() { if (entity) { + $('#api-action').addClass('loading'); CRM.api3(entity, 'getactions').done(function(data) { - // Ensure 'get' is always an action - actions = _.union(['get'], data.values); + actions = data.values || ['get']; populateActions(); }); } else { @@ -142,9 +147,14 @@ * @param el */ function populateActions(el) { - $('#api-action').select2({ + var val = $('#api-action').val(); + $('#api-action').removeClass('loading').select2({ data: _.transform(actions, function(ret, item) {ret.push({text: item, id: item})}) }); + // If previously selected action is not available, set it to 'get' if possible + if (_.indexOf(actions, val) < 0) { + $('#api-action').select2('val', _.indexOf(actions, 'get') < 0 ? actions[0] : 'get', true); + } } /** @@ -162,20 +172,45 @@ } /** - * Add/remove option list for selected field's pseudoconstant + * Render value input as a textfield, option list, or hidden, + * Depending on selected param name and operator */ - function toggleOptions() { - var name = $(this).val(), - $valField = $(this).closest('tr').find('.api-param-value'); - if (options[name]) { - $valField.val('').select2({ - multiple: true, + function renderValueField() { + var $row = $(this).closest('tr'), + name = $('input.api-param-name', $row).val(), + operator = $('.api-param-op', $row).val(), + operatorType = $.inArray(operator, MULTI) > -1 ? 'multi' : ($.inArray(operator, BOOL) > -1 ? 'bool' : 'single'), + $valField = $('input.api-param-value', $row), + currentVal = $valField.val(); + // Boolean fields only have 1 possible value + if (operatorType == 'bool') { + if ($valField.data('select2')) { + $valField.select2('destroy'); + } + $valField.css('visibility', 'hidden').val('1'); + return; + } + $valField.css('visibility', ''); + // Option list input + if (options[name] && $.inArray(operator, TEXT) < 0) { + // Reset value before switching to a select from something else + if ($(this).is('.api-param-name') || !$valField.data('select2')) { + $valField.val(''); + } + // When switching from multi-select to single select + else if (operatorType == 'single' && currentVal.indexOf(',') > -1) { + $valField.val(currentVal.split(',')[0]); + } + $valField.select2({ + multiple: (operatorType === 'multi'), data: _.transform(options[name], function(result, option) { result.push({id: option.key, text: option.value}); }) }); + return; } - else if ($valField.data('select2')) { + // Plain text input + if ($valField.data('select2')) { $valField.select2('destroy'); } } @@ -188,12 +223,12 @@ function evaluate(val, makeArray) { try { if (!val.length) { - return val; + return makeArray ? [] : ''; } var first = val.charAt(0), last = val.slice(-1); // Simple types - if (val === 'true' || val === 'false' || val === 'null' || !isNaN(val)) { + if (val === 'true' || val === 'false' || val === 'null') { return eval(val); } // Quoted strings @@ -205,8 +240,16 @@ return eval('(' + val + ')'); } // Transform csv to array - if (makeArray && val.indexOf(',') > 0) { - return val.split(','); + if (makeArray) { + var result = []; + $.each(val.split(','), function(k, v) { + result.push(evaluate($.trim(v)) || v); + }); + return result; + } + // Integers - quote any number that starts with 0 to avoid oddities + if (!isNaN(val) && val.search(/[^\d]/) < 0 && (val.length === 1 || first !== '0')) { + return parseInt(val, 10); } // Ok ok it's really a string return val; @@ -234,7 +277,7 @@ }); return 'array(' + ret + ')'; } - return JSON.stringify(val); + return JSON.stringify(val).replace(/\$/g, '\\$'); } /** @@ -260,9 +303,9 @@ }); $('input.api-param-value, input.api-option-value').each(function() { var $row = $(this).closest('tr'), - val = evaluate($(this).val(), $(this).is('.select2-offscreen')), + op = $('select.api-param-op', $row).val() || '=', name = $('input.api-param-name', $row).val(), - op = $('select.api-param-op', $row).val() || '='; + val = evaluate($(this).val(), $.inArray(op, MULTI) > -1); // Ignore blank values for the return field if ($(this).is('#api-return-value') && !val) { @@ -323,6 +366,8 @@ smarty: "{crmAPI var='result' entity='" + entity + "' action='" + action + "'", php: "$result = civicrm_api3('" + entity + "', '" + action + "'", json: "CRM.api3('" + entity + "', '" + action + "'", + drush: "drush cvapi " + entity + '.' + action + ' ', + wpcli: "wp cv api " + entity + '.' + action + ' ', rest: CRM.config.resourceBase + "extern/rest.php?entity=" + entity + "&action=" + action + "&json=" + JSON.stringify(params) + "&api_key=yoursitekey&key=yourkey" }; smartyStub = false; @@ -337,6 +382,9 @@ q.php += " '" + key + "' => " + phpFormat(value) + ",\n"; q.json += " \"" + key + '": ' + js; q.smarty += ' ' + key + '=' + smartyFormat(js, key); + // FIXME: This is not totally correct cli syntax + q.drush += key + '=' + js + ' '; + q.wpcli += key + '=' + js + ' '; }); if (i) { q.php += ")"; @@ -348,7 +396,7 @@ if (action.indexOf('get') < 0) { q.smarty = '{* Smarty API only works with get actions *}'; } else if (smartyStub) { - q.smarty = "{* Smarty does not have a syntax for array literals; assign complex variables on the server *}\n" + q.smarty; + q.smarty = "{* Smarty does not have a syntax for array literals; assign complex variables from php *}\n" + q.smarty; } $.each(q, function(type, val) { $('#api-' + type).removeClass('prettyprinted').text(val); @@ -362,7 +410,7 @@ alert(ts('Select an entity.')); return; } - if (action.indexOf('get') < 0) { + if (action.indexOf('get') < 0 && action != 'check') { var msg = action === 'delete' ? ts('This will delete data from CiviCRM. Are you sure?') : ts('This will write to the database. Continue?'); CRM.confirm({title: ts('Confirm %1', {1: action}), message: msg}).on('crmConfirm:yes', execute); } else { @@ -370,6 +418,10 @@ } } + /** + * Execute api call and display the results + * Note: We have to manually execute the ajax in order to add the secret extra "prettyprint" param + */ function execute() { $('#api-result').html('
'); $.ajax({ @@ -393,7 +445,6 @@ .on('change', '#api-entity, #api-action', function() { entity = $('#api-entity').val(); if ($(this).is('#api-entity')) { - $('#api-action').select2('val', 'get'); getActions(); } action = $('#api-action').val(); @@ -410,8 +461,8 @@ .on('change keyup', 'input.api-input, #api-params select', buildParams) .on('submit', submit); $('#api-params') - .on('change', '.api-param-name', toggleOptions) - .on('change', '.api-param-name, .api-option-name', function() { + .on('change', 'input.api-param-name, select.api-param-op', renderValueField) + .on('change', 'input.api-param-name, .api-option-name', function() { if ($(this).val() === '-') { $(this).select2('destroy'); $(this).val('').focus();