Add Examples to api explorer
authorColeman Watts <coleman@civicrm.org>
Wed, 4 Feb 2015 20:14:55 +0000 (15:14 -0500)
committerColeman Watts <coleman@civicrm.org>
Wed, 4 Feb 2015 21:08:04 +0000 (16:08 -0500)
CRM/Admin/Page/APIExplorer.php
CRM/Core/xml/Menu/Misc.xml
templates/CRM/Admin/Page/APIExplorer.js
templates/CRM/Admin/Page/APIExplorer.tpl

index 7b93156a49115872e166df0d1bc16cb01c5ec687..79a7bacebea0347c4061837fd753ee91825388d1 100644 (file)
@@ -42,12 +42,24 @@ class CRM_Admin_Page_APIExplorer extends CRM_Core_Page {
    * @return string
    */
   public function run() {
-    CRM_Utils_System::setTitle(ts('API explorer and generator'));
+    CRM_Utils_System::setTitle('CiviCRM API');
     CRM_Core_Resources::singleton()
       ->addScriptFile('civicrm', 'templates/CRM/Admin/Page/APIExplorer.js')
       ->addScriptUrl('//cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js', 99)
       ->addStyleUrl('//cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css', 99);
+
     $this->assign('operators', CRM_Core_DAO::acceptedSQLOperators());
+
+    // List example directories
+    global $civicrm_root;
+    $examples = array();
+    foreach (scandir($civicrm_root . 'api/v3/examples') as $item) {
+      if ($item && strpos($item, '.') === FALSE) {
+        $examples[] = $item;
+      }
+    }
+    $this->assign('examples', $examples);
+
     return parent::run();
   }
 
@@ -61,4 +73,31 @@ class CRM_Admin_Page_APIExplorer extends CRM_Core_Page {
     return 'civicrm/api/explorer';
   }
 
+  /**
+   * AJAX callback to fetch examples
+   */
+  public static function getExampleFile() {
+    global $civicrm_root;
+    if (!empty($_GET['entity']) && strpos($_GET['entity'], '.') === FALSE) {
+      $examples = array();
+      foreach (scandir($civicrm_root . 'api/v3/examples/' . $_GET['entity']) as $item) {
+        $item = str_replace('.php', '', $item);
+        if ($item && strpos($item, '.') === FALSE) {
+          $examples[] = array('key' => $item, 'value' => $item);
+        }
+      }
+      CRM_Utils_JSON::output($examples);
+    }
+    if (!empty($_GET['file']) && strpos($_GET['file'], '.') === FALSE) {
+      $fileName = $civicrm_root . 'api/v3/examples/' . $_GET['file'] . '.php';
+      if (file_exists($fileName)) {
+        echo file_get_contents($fileName);
+      }
+      else {
+        echo "Not found.";
+      }
+      CRM_Utils_System::civiExit();
+    }
+  }
+
 }
index 0d023c655f5e4904f36caf6871c6b4367bfca8d2..8abeb0894a21bf93346a9f837a67ac24c6452ace 100644 (file)
      <page_callback>CRM_Admin_Page_APIExplorer</page_callback>
      <access_arguments>access CiviCRM</access_arguments>
   </item>
+  <item>
+     <path>civicrm/ajax/apiexample</path>
+     <page_callback>CRM_Admin_Page_APIExplorer::getExampleFile</page_callback>
+     <access_arguments>access CiviCRM</access_arguments>
+  </item>
   <item>
      <path>civicrm/api/doc</path>
      <aapage_callback>CRM_Utils_REST::APIDoc</aapage_callback>
index 5723df8cacd5549979a2cf1b9c958c9c562ba840..e8c8119cf98548391bf2115475a827bbf83ab1f0 100644 (file)
@@ -1,4 +1,6 @@
 (function($, _, undefined) {
+  "use strict";
+  /* jshint validthis: true */
   var
     entity,
     action,
     });
   }
 
+  /**
+   * Fetch list of example files for a given entity
+   */
+  function getExamples() {
+    CRM.utils.setOptions($('#example-action').prop('disabled', true).addClass('loading'), []);
+    $.getJSON(CRM.url('civicrm/ajax/apiexample', {entity: $(this).val()}))
+      .done(function(result) {
+        CRM.utils.setOptions($('#example-action').prop('disabled', false).removeClass('loading'), result);
+      });
+  }
+
+  /**
+   * Fetch and display an example file
+   */
+  function getExample() {
+    var
+      entity = $('#example-entity').val(),
+      action = $('#example-action').val();
+    if (entity && action) {
+      $('#example-result').block();
+      $.get(CRM.url('civicrm/ajax/apiexample', {file: entity + '/' + action}))
+        .done(function(result) {
+          $('#example-result').unblock().addClass('prettyprint').removeClass('prettyprinted').text(result);
+          prettyPrint();
+        });
+    } else {
+      $('#example-result').text($('#example-result').attr('title'));
+    }
+  }
+
   $(document).ready(function() {
-    $('#api-entity').crmSelect2({
+    // Set up tabs - bind active tab to document hash because... it's cool?
+    document.location.hash = document.location.hash || 'explorer';
+      $('#mainTabContainer')
+      .tabs({
+          active: $(document.location.hash + '-tab').index() - 1
+        })
+      .on('tabsactivate', function(e, ui) {
+        if (ui.newPanel) {
+          document.location.hash = ui.newPanel.attr('id').replace('-tab', '');
+        }
+      });
+
+    // Initialize widgets
+    $('#api-entity, #example-entity').crmSelect2({
       // Add strikethough class to selection to indicate deprecated apis
       formatSelection: function(option) {
         return $(option.element).hasClass('strikethrough') ? '<span class="strikethrough">' + option.text + '</span>' : option.text;
         buildParams();
       })
       .on('change', 'select.api-chain-entity', getChainedAction);
+    $('#example-entity').on('change', getExamples);
+    $('#example-action').on('change', getExample);
     $('#api-params-add').on('click', function(e) {
       e.preventDefault();
       addField();
index 8d157803b0aa2a69eb544304819f7969e3499270..e85dc00a4ad9bc170d836bc3719a342b54b85f87 100644 (file)
 *}
 <style>
   {literal}
-  #api-explorer pre {
+  #mainTabContainer {
+    background: transparent;
+    border: 0 none;
+  }
+  #mainTabContainer pre {
     line-height: 1.3em;
     font-size: 11px;
     margin: 0;
     border: 0 none;
   }
-  pre#api-result {
+  #mainTabContainer ul.ui-tabs-nav {
+    font-size: 1.1em;
+    margin-bottom: .6em;
+  }
+  pre#api-result,
+  pre#example-result {
     padding:1em;
     max-height: 50em;
     border: 1px solid lightgrey;
+    margin-top: 1em;
+    overflow: auto;
   }
   #api-params-table th:first-child,
   #api-params-table td:first-child {
@@ -51,7 +62,7 @@
   #api-params .red-icon {
     margin-top: .5em;
   }
-  #api-explorer label {
+  #mainTabContainer label {
     display: inline;
     font-weight: bold;
   }
   {/literal}
 </style>
 
-<form id="api-explorer">
-  <label for="api-entity">{ts}Entity{/ts}:</label>
-  <select class="crm-form-select" id="api-entity" name="entity">
-    <option value="" selected="selected">{ts}Choose{/ts}...</option>
-    {crmAPI entity="Entity" action="get" var="entities" version=3}
-    {foreach from=$entities.values item=entity}
-      <option value="{$entity}" {if !empty($entities.deprecated) && in_array($entity, $entities.deprecated)}class="strikethrough"{/if}>
-        {$entity}
-      </option>
-    {/foreach}
-  </select>
-  &nbsp;&nbsp;
-  <label for="api-action">{ts}Action{/ts}:</label>
-  <input class="crm-form-text" id="api-action" name="action" value="get">
-  &nbsp;&nbsp;
+<div id="mainTabContainer">
+  <ul>
+    <li class="ui-corner-all"><a href="#explorer-tab">{ts}Explorer{/ts}</a></li>
+    <li class="ui-corner-all"><a href="#examples-tab">{ts}Examples{/ts}</a></li>
+  </ul>
 
-  <label for="debug-checkbox" title="{ts}Display debug output with results.{/ts}">
-    <input type="checkbox" class="crm-form-checkbox api-param-checkbox api-input" id="debug-checkbox" name="debug" value="1" >debug
-  </label>
-  &nbsp;|&nbsp;
+  <div id="explorer-tab">
 
-  <label for="sequential-checkbox" title="{ts}Sequential is more compact format, well-suited for json and smarty.{/ts}">
-    <input type="checkbox" class="crm-form-checkbox api-param-checkbox api-input" id="sequential-checkbox" name="sequential" checked="checked" value="1">sequential
-  </label>
+    <form id="api-explorer">
+      <label for="api-entity">{ts}Entity{/ts}:</label>
+      <select class="crm-form-select big required" id="api-entity" name="entity">
+        <option value="" selected="selected">{ts}Choose{/ts}...</option>
+        {crmAPI entity="Entity" action="get" var="entities" version=3}
+        {foreach from=$entities.values item=entity}
+          <option value="{$entity}" {if !empty($entities.deprecated) && in_array($entity, $entities.deprecated)}class="strikethrough"{/if}>
+            {$entity}
+          </option>
+        {/foreach}
+      </select>
+      &nbsp;&nbsp;
+      <label for="api-action">{ts}Action{/ts}:</label>
+      <input class="crm-form-text" id="api-action" name="action" value="get">
+      &nbsp;&nbsp;
 
-  <table id="api-params-table">
-    <thead style="display: none;">
-      <tr>
-        <th>{ts}Name{/ts} {help id='param-name'}</th>
-        <th>{ts}Operator{/ts} {help id='param-op'}</th>
-        <th>{ts}Value{/ts} {help id='param-value'}</th>
-      </tr>
-    </thead>
-    <tbody id="api-params"></tbody>
-  </table>
-  <div id="api-param-buttons" style="display: none;">
-    <a href="#" class="crm-hover-button" id="api-params-add"><span class="icon ui-icon-plus"></span>{ts}Add Parameter{/ts}</a>
-    <a href="#" class="crm-hover-button" id="api-option-add"><span class="icon ui-icon-gear"></span>{ts}Add Option{/ts}</a>
-    <a href="#" class="crm-hover-button" id="api-chain-add"><span class="icon ui-icon-link"></span>{ts}Chain API Call{/ts}</a>
-  </div>
-  <div id="api-generated-wraper">
-    <table id="api-generated" border=1>
-      <caption>{ts}Code{/ts}</caption>
-      <tr><td>Rest</td><td><pre class="prettyprint" id="api-rest"></pre></td></tr>
-      <tr><td>Smarty</td><td><pre class="prettyprint linenums" id="api-smarty" title='smarty syntax (for get actions)'></pre></td></tr>
-      <tr><td>Php</td><td><pre class="prettyprint linenums" id="api-php" title='php syntax'></pre></td></tr>
-      <tr><td>Javascript</td><td><pre class="prettyprint linenums" id="api-json" title='javascript syntax'></pre></td></tr>
-      {if $config->userSystem->is_drupal}
-        <tr><td>Drush</td><td><pre class="prettyprint" id="api-drush" title='drush syntax'></pre></td></tr>
-      {/if}
-      {if $config->userSystem->is_wordpress}
-        <tr><td>WP-CLI</td><td><pre class="prettyprint" id="api-wpcli" title='wp-cli syntax'></pre></td></tr>
-      {/if}
-    </table>
-  </div>
-  <div class="crm-submit-buttons">
-    <span class="crm-button crm-icon-button">
-      <span class="crm-button-icon ui-icon-check"> </span> <input type="submit" value="{ts}Execute{/ts}" class="crm-form-submit" accesskey="S" title="{ts}Execute API call and display results{/ts}"/>
-    </span>
-  </div>
+      <label for="debug-checkbox" title="{ts}Display debug output with results.{/ts}">
+        <input type="checkbox" class="crm-form-checkbox api-param-checkbox api-input" id="debug-checkbox" name="debug" value="1" >debug
+      </label>
+      &nbsp;|&nbsp;
+
+      <label for="sequential-checkbox" title="{ts}Sequential is more compact format, well-suited for json and smarty.{/ts}">
+        <input type="checkbox" class="crm-form-checkbox api-param-checkbox api-input" id="sequential-checkbox" name="sequential" checked="checked" value="1">sequential
+      </label>
+
+      <table id="api-params-table">
+        <thead style="display: none;">
+          <tr>
+            <th>{ts}Name{/ts} {help id='param-name'}</th>
+            <th>{ts}Operator{/ts} {help id='param-op'}</th>
+            <th>{ts}Value{/ts} {help id='param-value'}</th>
+          </tr>
+        </thead>
+        <tbody id="api-params"></tbody>
+      </table>
+      <div id="api-param-buttons" style="display: none;">
+        <a href="#" class="crm-hover-button" id="api-params-add"><span class="icon ui-icon-plus"></span>{ts}Add Parameter{/ts}</a>
+        <a href="#" class="crm-hover-button" id="api-option-add"><span class="icon ui-icon-gear"></span>{ts}Add Option{/ts}</a>
+        <a href="#" class="crm-hover-button" id="api-chain-add"><span class="icon ui-icon-link"></span>{ts}Chain API Call{/ts}</a>
+      </div>
+      <div id="api-generated-wraper">
+        <table id="api-generated" border=1>
+          <caption>{ts}Code{/ts}</caption>
+          <tr><td>Rest</td><td><pre class="prettyprint" id="api-rest"></pre></td></tr>
+          <tr><td>Smarty</td><td><pre class="prettyprint linenums" id="api-smarty" title='smarty syntax (for get actions)'></pre></td></tr>
+          <tr><td>Php</td><td><pre class="prettyprint linenums" id="api-php" title='php syntax'></pre></td></tr>
+          <tr><td>Javascript</td><td><pre class="prettyprint linenums" id="api-json" title='javascript syntax'></pre></td></tr>
+          {if $config->userSystem->is_drupal}
+            <tr><td>Drush</td><td><pre class="prettyprint" id="api-drush" title='drush syntax'></pre></td></tr>
+          {/if}
+          {if $config->userSystem->is_wordpress}
+            <tr><td>WP-CLI</td><td><pre class="prettyprint" id="api-wpcli" title='wp-cli syntax'></pre></td></tr>
+          {/if}
+        </table>
+      </div>
+      <div class="crm-submit-buttons">
+        <span class="crm-button crm-icon-button">
+          <span class="crm-button-icon ui-icon-check"> </span> <input type="submit" value="{ts}Execute{/ts}" class="crm-form-submit" accesskey="S" title="{ts}Execute API call and display results{/ts}"/>
+        </span>
+      </div>
 <pre id="api-result" class="linenums">
-{ts}The result of api calls are displayed in this area.{/ts}
+{ts}Results are displayed here.{/ts}
+</pre>
+    </form>
+  </div>
+
+  <div id="examples-tab">
+    <form id="api-examples">
+      <label for="example-entity">{ts}Entity{/ts}:</label>
+      <select class="crm-form-select big required" id="example-entity" name="entity">
+        <option value="" selected="selected">{ts}Choose{/ts}...</option>
+        {foreach from=$examples item=entity}
+          <option value="{$entity}" {if !empty($entities.deprecated) && in_array($entity, $entities.deprecated)}class="strikethrough"{/if}>
+            {$entity}
+          </option>
+        {/foreach}
+      </select>
+      &nbsp;&nbsp;
+      <label for="example-action">{ts}Example{/ts}:</label>
+      <select class="crm-form-select big crm-select2" id="example-action" name="action">
+        <option value="" selected="selected">{ts}Choose{/ts}...</option>
+      </select>
+<pre id="example-result" class="linenums lang-php" title="{ts escape='html'}Results are displayed here.{/ts}">
+{ts}Results are displayed here.{/ts}
 </pre>
-</form>
+    </form>
+  </div>
+</div>
 
 {strip}
 <script type="text/template" id="api-param-tpl">