From fd1998d202b5a76c610805f3fae9dd79ef3ef059 Mon Sep 17 00:00:00 2001
From: Jaap Jansma <jaap.jansma@civicoop.org>
Date: Mon, 29 Apr 2019 16:39:29 +0200
Subject: [PATCH] refactored output

---
 CRM/Dataprocessor/BAO/DataProcessor.php       |   6 +-
 CRM/Dataprocessor/BAO/DataProcessorOutput.php |  27 ++
 CRM/Dataprocessor/BAO/Output.php              | 151 ----------
 CRM/Dataprocessor/DAO/DataProcessorOutput.php | 271 ++++++++++++++++++
 CRM/Dataprocessor/DAO/Output.php              | 100 -------
 CRM/Dataprocessor/Form/DataProcessor.php      |  24 +-
 CRM/Dataprocessor/Form/Output.php             |  72 +++--
 CRM/Dataprocessor/Form/Output/API.php         |  54 ----
 CRM/Dataprocessor/Utils/Importer.php          |   4 +-
 .../Page/Download.php                         |   4 +-
 CRM/DataprocessorSearch/ActivitySearch.php    | 121 +++++++-
 CRM/DataprocessorSearch/ContactSearch.php     | 110 ++++++-
 .../Form/AbstractSearch.php                   |   5 +-
 .../OutputConfiguration/ActivitySearch.php    | 114 --------
 .../OutputConfiguration/ContactSearch.php     | 114 --------
 Civi/DataProcessor/Output/Api.php             |  65 ++++-
 Civi/DataProcessor/Output/OutputInterface.php |  34 ++-
 Civi/DataProcessor/Output/UIOutputHelper.php  |  18 +-
 api/v3/DataProcessorOutput.php                |  76 +++++
 api/v3/DataProcessorOutput/Create.php         |  76 -----
 api/v3/DataProcessorOutput/Delete.php         |  37 ---
 api/v3/DataProcessorOutput/Get.php            |  30 --
 dataprocessor.civix.php                       |   6 +
 sql/auto_install.sql                          |  24 ++
 sql/auto_uninstall.sql                        |   1 +
 .../Form/DataProcessorBlocks/Filters.tpl      |   6 -
 .../Form/DataProcessorBlocks/Outputs.tpl      |   5 -
 templates/CRM/Dataprocessor/Form/Output.tpl   |  51 +++-
 .../CRM/Dataprocessor/Form/Output/API.tpl     |  47 ++-
 .../OutputConfiguration/ActivitySearch.tpl    |  65 ++---
 .../OutputConfiguration/ContactSearch.tpl     |  65 ++---
 xml/Menu/dataprocessor.xml                    |  21 --
 .../DataProcessorOutput.entityType.php        |  11 +
 .../CRM/Dataprocessor/DataProcessorOutput.xml |  78 +++++
 34 files changed, 985 insertions(+), 908 deletions(-)
 create mode 100644 CRM/Dataprocessor/BAO/DataProcessorOutput.php
 delete mode 100644 CRM/Dataprocessor/BAO/Output.php
 create mode 100644 CRM/Dataprocessor/DAO/DataProcessorOutput.php
 delete mode 100644 CRM/Dataprocessor/DAO/Output.php
 delete mode 100644 CRM/Dataprocessor/Form/Output/API.php
 delete mode 100644 CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.php
 delete mode 100644 CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.php
 create mode 100644 api/v3/DataProcessorOutput.php
 delete mode 100644 api/v3/DataProcessorOutput/Create.php
 delete mode 100644 api/v3/DataProcessorOutput/Delete.php
 delete mode 100644 api/v3/DataProcessorOutput/Get.php
 create mode 100644 xml/schema/CRM/Dataprocessor/DataProcessorOutput.entityType.php
 create mode 100644 xml/schema/CRM/Dataprocessor/DataProcessorOutput.xml

diff --git a/CRM/Dataprocessor/BAO/DataProcessor.php b/CRM/Dataprocessor/BAO/DataProcessor.php
index 923f5e18..e90c1864 100644
--- a/CRM/Dataprocessor/BAO/DataProcessor.php
+++ b/CRM/Dataprocessor/BAO/DataProcessor.php
@@ -114,7 +114,7 @@ class CRM_Dataprocessor_BAO_DataProcessor extends CRM_Dataprocessor_DAO_DataProc
 
     CRM_Utils_Hook::pre('delete', 'DataProcessor', $id, CRM_Core_DAO::$_nullArray);
 
-    CRM_Dataprocessor_BAO_Output::deleteWithDataProcessorId($id);
+    CRM_Dataprocessor_BAO_DataProcessorOutput::deleteWithDataProcessorId($id);
     CRM_Dataprocessor_BAO_DataProcessorFilter::deleteWithDataProcessorId($id);
     CRM_Dataprocessor_BAO_DataProcessorField::deleteWithDataProcessorId($id);
     CRM_Dataprocessor_BAO_Source::deleteWithDataProcessorId($id);
@@ -465,9 +465,9 @@ class CRM_Dataprocessor_BAO_DataProcessor extends CRM_Dataprocessor_DAO_DataProc
       unset($field['data_processor_id']);
       $dataProcessor['fields'][] = $field;
     }
-    $outputs = CRM_Dataprocessor_BAO_Output::getValues(array('data_processor_id' => $id));
+    $outputs = $outputs = civicrm_api3('DataProcessorOutput', 'get', array('data_processor_id' => $id, 'options' => array('limit' => 0)));
     $dataProcessor['outputs'] = array();
-    foreach($outputs as $i => $output) {
+    foreach($outputs['values'] as $i => $output) {
       unset($output['id']);
       unset($output['data_processor_id']);
       $dataProcessor['outputs'][] = $output;
diff --git a/CRM/Dataprocessor/BAO/DataProcessorOutput.php b/CRM/Dataprocessor/BAO/DataProcessorOutput.php
new file mode 100644
index 00000000..049a96dd
--- /dev/null
+++ b/CRM/Dataprocessor/BAO/DataProcessorOutput.php
@@ -0,0 +1,27 @@
+<?php
+use CRM_Dataprocessor_ExtensionUtil as E;
+
+class CRM_Dataprocessor_BAO_DataProcessorOutput extends CRM_Dataprocessor_DAO_DataProcessorOutput {
+
+  /**
+   * Function to delete a Data Processor Output with id
+   *
+   * @param int $id
+   * @throws Exception when $id is empty
+   * @access public
+   * @static
+   */
+  public static function deleteWithDataProcessorId($id) {
+    if (empty($id)) {
+      throw new Exception('id can not be empty when attempting to delete a data processor filter');
+    }
+
+    $field = new CRM_Dataprocessor_DAO_DataProcessorOutput();
+    $field->data_processor_id = $id;
+    $field->find(FALSE);
+    while ($field->fetch()) {
+      civicrm_api3('DataProcessorOutput', 'delete', array('id' => $field->id));
+    }
+  }
+
+}
diff --git a/CRM/Dataprocessor/BAO/Output.php b/CRM/Dataprocessor/BAO/Output.php
deleted file mode 100644
index 7b3fc979..00000000
--- a/CRM/Dataprocessor/BAO/Output.php
+++ /dev/null
@@ -1,151 +0,0 @@
-<?php
-/**
- * @author Jaap Jansma <jaap.jansma@civicoop.org>
- * @license AGPL-3.0
- */
-
-class CRM_Dataprocessor_BAO_Output extends CRM_Dataprocessor_DAO_Output {
-
-  /**
-   * Function to get values
-   *
-   * @return array $result found rows with data
-   * @access public
-   * @static
-   */
-  public static function getValues($params) {
-    $factory = dataprocessor_get_factory();
-    $types = $factory->getOutputs();
-
-    $result = array();
-    $output = new CRM_Dataprocessor_DAO_Output();
-    if (!empty($params)) {
-      $fields = self::fields();
-      foreach ($params as $key => $value) {
-        if (isset($fields[$key])) {
-          $output->$key = $value;
-        }
-      }
-    }
-    $output->find();
-    while ($output->fetch()) {
-      $row = array();
-      self::storeValues($output, $row);
-
-      if (isset($types[$row['type']])) {
-        $row['type_name'] = $types[$row['type']];
-      } else {
-        $row['type_name'] = '';
-      }
-
-      if (isset($row['configuration']) && is_string($row['configuration']) && strlen($row['configuration'])) {
-        $row['configuration'] = json_decode($row['configuration'], true);
-      } else {
-        $row['configuration'] = array();
-      }
-
-      $result[$row['id']] = $row;
-    }
-    return $result;
-  }
-
-  /**
-   * Function to add or update a DataProcessor
-   *
-   * @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 data processor output');
-    }
-
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::pre('edit', 'DataProcessorOutput', $params['id'], $params);
-    }
-    else {
-      CRM_Utils_Hook::pre('create', 'DataProcessorOutput', NULL, $params);
-    }
-
-    $output = new CRM_Dataprocessor_DAO_Output();
-    $fields = self::fields();
-    foreach ($params as $key => $value) {
-      if (isset($fields[$key])) {
-        $output->$key = $value;
-      }
-    }
-    if (!isset($output->configuration)) {
-      $output->configuration = array();
-    }
-    if (is_array($output->configuration)) {
-      $output->configuration = json_encode($output->configuration);
-    }
-
-    $output->save();
-    $id = $output->id;
-    $output = new CRM_Dataprocessor_BAO_Output();
-    $output->id = $id;
-    $output->find(true);
-    CRM_Dataprocessor_BAO_DataProcessor::updateAndChekStatus($output->data_processor_id);
-    self::storeValues($output, $result);
-
-    if (!empty($params['id'])) {
-      CRM_Utils_Hook::post('edit', 'DataProcessorOutput', $output->id, $output);
-    }
-    else {
-      CRM_Utils_Hook::post('create', 'DataProcessorOutput', $output->id, $output);
-    }
-
-    return $result;
-  }
-
-  /**
-   * Function to delete a Data Processor Output 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 data processor output');
-    }
-
-    CRM_Utils_Hook::pre('delete', 'DataProcessorOutput', $id, CRM_Core_DAO::$_nullArray);
-
-    $output = new CRM_Dataprocessor_DAO_Output();
-    $output->id = $id;
-    $output->delete();
-
-    CRM_Utils_Hook::post('delete', 'DataProcessorOutput', $id, CRM_Core_DAO::$_nullArray);
-
-    return;
-  }
-
-  /**
-   * Function to delete a Data Processor Output with id
-   *
-   * @param int $id
-   * @throws Exception when $id is empty
-   * @access public
-   * @static
-   */
-  public static function deleteWithDataProcessorId($id) {
-    if (empty($id)) {
-      throw new Exception('id can not be empty when attempting to delete a data processor output');
-    }
-
-    $output = new CRM_Dataprocessor_DAO_Output();
-    $output->data_processor_id = $id;
-    $output->find(FALSE);
-    while ($output->fetch()) {
-      self::deleteWithId($output->id);
-    }
-  }
-
-}
\ No newline at end of file
diff --git a/CRM/Dataprocessor/DAO/DataProcessorOutput.php b/CRM/Dataprocessor/DAO/DataProcessorOutput.php
new file mode 100644
index 00000000..292d810a
--- /dev/null
+++ b/CRM/Dataprocessor/DAO/DataProcessorOutput.php
@@ -0,0 +1,271 @@
+<?php
+
+/**
+ * @package CRM
+ * @copyright CiviCRM LLC (c) 2004-2019
+ *
+ * Generated from /buildkit/build/search/sites/default/files/civicrm/ext/dataprocessor/xml/schema/CRM/Dataprocessor/DataProcessorOutput.xml
+ * DO NOT EDIT.  Generated by CRM_Core_CodeGen
+ * (GenCodeChecksum:f38dc40dc234990d0664637ae1b9a8d6)
+ */
+
+/**
+ * Database access object for the DataProcessorOutput entity.
+ */
+class CRM_Dataprocessor_DAO_DataProcessorOutput extends CRM_Core_DAO {
+
+  /**
+   * Static instance to hold the table name.
+   *
+   * @var string
+   */
+  static $_tableName = 'civicrm_data_processor_output';
+
+  /**
+   * Should CiviCRM log any modifications to this table in the civicrm_log table.
+   *
+   * @var bool
+   */
+  static $_log = FALSE;
+
+  /**
+   * Unique DataProcessorOutput ID
+   *
+   * @var int unsigned
+   */
+  public $id;
+
+  /**
+   * FK to Data Processor
+   *
+   * @var int unsigned
+   */
+  public $data_processor_id;
+
+  /**
+   * @var string
+   */
+  public $type;
+
+  /**
+   * @var text
+   */
+  public $configuration;
+
+  /**
+   * @var string
+   */
+  public $permission;
+
+  /**
+   * @var string
+   */
+  public $api_entity;
+
+  /**
+   * @var string
+   */
+  public $api_action;
+
+  /**
+   * @var string
+   */
+  public $api_count_action;
+
+  /**
+   * Class constructor.
+   */
+  public function __construct() {
+    $this->__table = 'civicrm_data_processor_output';
+    parent::__construct();
+  }
+
+  /**
+   * Returns foreign keys and entity references.
+   *
+   * @return array
+   *   [CRM_Core_Reference_Interface]
+   */
+  public static function getReferenceColumns() {
+    if (!isset(Civi::$statics[__CLASS__]['links'])) {
+      Civi::$statics[__CLASS__]['links'] = static ::createReferenceColumns(__CLASS__);
+      Civi::$statics[__CLASS__]['links'][] = new CRM_Core_Reference_Basic(self::getTableName(), 'data_processor_id', 'civicrm_data_processor', 'id');
+      CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'links_callback', Civi::$statics[__CLASS__]['links']);
+    }
+    return Civi::$statics[__CLASS__]['links'];
+  }
+
+  /**
+   * Returns all the column names of this table
+   *
+   * @return array
+   */
+  public static function &fields() {
+    if (!isset(Civi::$statics[__CLASS__]['fields'])) {
+      Civi::$statics[__CLASS__]['fields'] = [
+        'id' => [
+          'name' => 'id',
+          'type' => CRM_Utils_Type::T_INT,
+          'description' => CRM_Dataprocessor_ExtensionUtil::ts('Unique DataProcessorOutput ID'),
+          'required' => TRUE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+        ],
+        'data_processor_id' => [
+          'name' => 'data_processor_id',
+          'type' => CRM_Utils_Type::T_INT,
+          'title' => CRM_Dataprocessor_ExtensionUtil::ts('Data Processor ID'),
+          'description' => CRM_Dataprocessor_ExtensionUtil::ts('FK to Data Processor'),
+          'required' => TRUE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+        ],
+        'type' => [
+          'name' => 'type',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => CRM_Dataprocessor_ExtensionUtil::ts('Type'),
+          'required' => TRUE,
+          'maxlength' => 255,
+          'size' => CRM_Utils_Type::HUGE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+        ],
+        'configuration' => [
+          'name' => 'configuration',
+          'type' => CRM_Utils_Type::T_TEXT,
+          'title' => CRM_Dataprocessor_ExtensionUtil::ts('Configuration'),
+          'required' => FALSE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+          'serialize' => self::SERIALIZE_JSON,
+        ],
+        'permission' => [
+          'name' => 'permission',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => CRM_Dataprocessor_ExtensionUtil::ts('Permission'),
+          'required' => FALSE,
+          'maxlength' => 255,
+          'size' => CRM_Utils_Type::HUGE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+        ],
+        'api_entity' => [
+          'name' => 'api_entity',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => CRM_Dataprocessor_ExtensionUtil::ts('API Entity'),
+          'required' => FALSE,
+          'maxlength' => 255,
+          'size' => CRM_Utils_Type::HUGE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+        ],
+        'api_action' => [
+          'name' => 'api_action',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => CRM_Dataprocessor_ExtensionUtil::ts('API Action'),
+          'required' => FALSE,
+          'maxlength' => 255,
+          'size' => CRM_Utils_Type::HUGE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+        ],
+        'api_count_action' => [
+          'name' => 'api_count_action',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => CRM_Dataprocessor_ExtensionUtil::ts('API Getcount action'),
+          'required' => FALSE,
+          'maxlength' => 255,
+          'size' => CRM_Utils_Type::HUGE,
+          'table_name' => 'civicrm_data_processor_output',
+          'entity' => 'DataProcessorOutput',
+          'bao' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+          'localizable' => 0,
+        ],
+      ];
+      CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
+    }
+    return Civi::$statics[__CLASS__]['fields'];
+  }
+
+  /**
+   * Return a mapping from field-name to the corresponding key (as used in fields()).
+   *
+   * @return array
+   *   Array(string $name => string $uniqueName).
+   */
+  public static function &fieldKeys() {
+    if (!isset(Civi::$statics[__CLASS__]['fieldKeys'])) {
+      Civi::$statics[__CLASS__]['fieldKeys'] = array_flip(CRM_Utils_Array::collect('name', self::fields()));
+    }
+    return Civi::$statics[__CLASS__]['fieldKeys'];
+  }
+
+  /**
+   * Returns the names of this table
+   *
+   * @return string
+   */
+  public static function getTableName() {
+    return self::$_tableName;
+  }
+
+  /**
+   * Returns if this table needs to be logged
+   *
+   * @return bool
+   */
+  public function getLog() {
+    return self::$_log;
+  }
+
+  /**
+   * Returns the list of fields that can be imported
+   *
+   * @param bool $prefix
+   *
+   * @return array
+   */
+  public static function &import($prefix = FALSE) {
+    $r = CRM_Core_DAO_AllCoreTables::getImports(__CLASS__, 'data_processor_output', $prefix, []);
+    return $r;
+  }
+
+  /**
+   * Returns the list of fields that can be exported
+   *
+   * @param bool $prefix
+   *
+   * @return array
+   */
+  public static function &export($prefix = FALSE) {
+    $r = CRM_Core_DAO_AllCoreTables::getExports(__CLASS__, 'data_processor_output', $prefix, []);
+    return $r;
+  }
+
+  /**
+   * Returns the list of indices
+   *
+   * @param bool $localize
+   *
+   * @return array
+   */
+  public static function indices($localize = TRUE) {
+    $indices = [];
+    return ($localize && !empty($indices)) ? CRM_Core_DAO_AllCoreTables::multilingualize(__CLASS__, $indices) : $indices;
+  }
+
+}
diff --git a/CRM/Dataprocessor/DAO/Output.php b/CRM/Dataprocessor/DAO/Output.php
deleted file mode 100644
index f1da9d55..00000000
--- a/CRM/Dataprocessor/DAO/Output.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-
-use CRM_Dataprocessor_ExtensionUtil as E;
-
-/**
- * @author Jaap Jansma (CiviCooP) <jaap.jansma@civicoop.org>
- * @license http://www.gnu.org/licenses/agpl-3.0.html
- */
-class CRM_Dataprocessor_DAO_Output 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_data_processor_output';
-  }
-  /**
-   * 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
-        ) ,
-        'data_processor_id' => array(
-          'name' => 'data_processor_id',
-          'title' => E::ts('Data Processor ID'),
-          'type' => CRM_Utils_Type::T_INT,
-          'required' => true,
-          'FKApiName' => 'DataProcessor',
-        ),
-        'type' => array(
-          'name' => 'type',
-          'title' => E::ts('Type'),
-          'type' => CRM_Utils_Type::T_STRING,
-          'maxlength' => 80,
-          'required' => true,
-        ),
-        'configuration' => array(
-          'name' => 'configuration',
-          'title' => E::ts('Configuration'),
-          'type' => CRM_Utils_Type::T_TEXT,
-        ),
-        'permission' => array(
-          'name' => 'permission',
-          'title' => E::ts('Permission'),
-          'type' => CRM_Utils_Type::T_STRING
-        ),
-        'api_entity' => array(
-          'name' => 'api_entity',
-          'title' => E::ts('API Entity'),
-          'type' => CRM_Utils_Type::T_STRING
-        ),
-        'api_action' => array(
-          'name' => 'api_action',
-          'title' => E::ts('API Action Name'),
-          'type' => CRM_Utils_Type::T_STRING
-        ),
-        'api_count_action' => array(
-          'name' => 'api_count_action',
-          'title' => E::ts('API GetCount Action Name'),
-          'type' => CRM_Utils_Type::T_STRING
-        ),
-      );
-    }
-    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',
-        'data_processor_id' => 'data_processor_id',
-        'type' => 'type',
-        'configuration' => 'configuration',
-      );
-    }
-    return self::$_fieldKeys;
-  }
-}
\ No newline at end of file
diff --git a/CRM/Dataprocessor/Form/DataProcessor.php b/CRM/Dataprocessor/Form/DataProcessor.php
index d9498926..00f05d4c 100644
--- a/CRM/Dataprocessor/Form/DataProcessor.php
+++ b/CRM/Dataprocessor/Form/DataProcessor.php
@@ -85,9 +85,6 @@ class CRM_Dataprocessor_Form_DataProcessor extends CRM_Core_Form {
   protected function addFields() {
     $fields = civicrm_api3('DataProcessorField', 'get', array('data_processor_id' => $this->dataProcessorId, 'options' => array('limit' => 0)));
     $fields = $fields['values'];
-    foreach($fields as $idx => $field) {
-      $fields[$idx]['configuration_link'] = '';
-    }
     CRM_Utils_Weight::addOrder($fields, 'CRM_Dataprocessor_DAO_DataProcessorField', 'id', $this->currentUrl, 'data_processor_id='.$this->dataProcessorId);
     $this->assign('fields', $fields);
   }
@@ -95,9 +92,6 @@ class CRM_Dataprocessor_Form_DataProcessor extends CRM_Core_Form {
   protected function addFilters() {
     $filters = civicrm_api3('DataProcessorFilter', 'get', array('data_processor_id' => $this->dataProcessorId, 'options' => array('limit' => 0)));
     $filters = $filters['values'];
-    foreach($filters as $idx => $filter) {
-      $filters[$idx]['configuration_link'] = '';
-    }
     CRM_Utils_Weight::addOrder($filters, 'CRM_Dataprocessor_DAO_DataProcessorFilter', 'id', $this->currentUrl, 'data_processor_id='.$this->dataProcessorId);
     $this->assign('filters', $filters);
   }
@@ -119,18 +113,16 @@ class CRM_Dataprocessor_Form_DataProcessor extends CRM_Core_Form {
 
   protected function addOutputs() {
     $factory = dataprocessor_get_factory();
-    $outputs = CRM_Dataprocessor_BAO_Output::getValues(array('data_processor_id' => $this->dataProcessorId));
+    $types = $factory->getOutputs();
+    $outputs = civicrm_api3('DataProcessorOutput', 'get', array('data_processor_id' => $this->dataProcessorId, 'options' => array('limit' => 0)));
+    $outputs = $outputs['values'];
     foreach($outputs as $idx => $output) {
-      $outputs[$idx]['configuration_link'] = '';
-      $outputClass  = $factory->getOutputByName($output['type']);
-      if  ($outputClass->getConfigurationUrl()) {
-        $outputs[$idx]['configuration_link'] = CRM_Utils_System::url($outputClass->getConfigurationUrl(), [
-          'reset' => 1,
-          'action' =>  'update',
-          'id' => $output['id'],
-          'data_processor_id' => $this->dataProcessorId
-        ]);
+      if (isset($types[$output['type']])) {
+        $outputs[$idx]['type_name'] = $types[$output['type']];
+      } else {
+        $outputs[$idx]['type_name'] = '';
       }
+      $outputs[$idx]['configuration_link'] = '';
     }
     $this->assign('outputs', $outputs);
   }
diff --git a/CRM/Dataprocessor/Form/Output.php b/CRM/Dataprocessor/Form/Output.php
index 7b57ab4d..a67dde36 100644
--- a/CRM/Dataprocessor/Form/Output.php
+++ b/CRM/Dataprocessor/Form/Output.php
@@ -13,12 +13,28 @@ class CRM_Dataprocessor_Form_Output extends CRM_Core_Form {
 
   private $id;
 
+  private $output;
+
+  /**
+   * @var Civi\DataProcessor\Output\OutputInterface
+   */
+  private $outputTypeClass;
+
+  private $snippet;
+
   /**
    * Function to perform processing before displaying form (overrides parent function)
    *
    * @access public
    */
   function preProcess() {
+    $this->snippet = CRM_Utils_Request::retrieve('snippet', 'String');
+    if ($this->snippet) {
+      $this->assign('suppressForm', TRUE);
+      $this->controller->_generateQFKey = FALSE;
+    }
+
+    $factory = dataprocessor_get_factory();
     $session = CRM_Core_Session::singleton();
     $this->dataProcessorId = CRM_Utils_Request::retrieve('data_processor_id', 'Integer');
     $this->assign('data_processor_id', $this->dataProcessorId);
@@ -27,8 +43,20 @@ class CRM_Dataprocessor_Form_Output extends CRM_Core_Form {
     $this->assign('id', $this->id);
 
     if ($this->id) {
-      $output = CRM_Dataprocessor_BAO_Output::getValues(array('id' => $this->id));
-      $this->assign('output', $output[$this->id]);
+      $this->output = civicrm_api3('DataProcessorOutput', 'getsingle', array('id' => $this->id));
+      $this->assign('output', $this->output);
+      $this->outputTypeClass = $factory->getOutputByName($this->output['type']);
+      $this->assign('has_configuration', $this->outputTypeClass->hasConfiguration());
+    }
+
+    $type = CRM_Utils_Request::retrieve('type', 'String');
+    if ($type) {
+      $this->outputTypeClass = $factory->getOutputByName($type);
+      $this->assign('has_configuration', $this->outputTypeClass->hasConfiguration());
+    }
+
+    if (!$this->output) {
+      $this->output['data_processor_id'] = $this->dataProcessorId;
     }
 
     $title = E::ts('Data Processor Output');
@@ -41,20 +69,20 @@ class CRM_Dataprocessor_Form_Output extends CRM_Core_Form {
   public function buildQuickForm() {
     $this->add('hidden', 'data_processor_id');
     $this->add('hidden', 'id');
-    if ($this->_action != CRM_Core_Action::DELETE) {
-      $factory = dataprocessor_get_factory();
-      $types = array(' - select - ')  + $factory->getOutputs();
-      $this->add('select', 'type', ts('Select output'), $types, true, array('class' => 'crm-select2'));
-    }
-    if ($this->_action == CRM_Core_Action::ADD) {
-      $this->addButtons(array(
-        array('type' => 'next', 'name' => E::ts('Next'), 'isDefault' => TRUE,),
-        array('type' => 'cancel', 'name' => E::ts('Cancel'))));
-    } elseif ($this->_action == CRM_Core_Action::DELETE) {
+    if ($this->_action == CRM_Core_Action::DELETE) {
       $this->addButtons(array(
         array('type' => 'next', 'name' => E::ts('Delete'), 'isDefault' => TRUE,),
         array('type' => 'cancel', 'name' => E::ts('Cancel'))));
     } else {
+      $factory = dataprocessor_get_factory();
+      $types = array(' - select - ')  + $factory->getOutputs();
+      $this->add('select', 'type', ts('Select output'), $types, true, array('class' => 'crm-select2'));
+
+      if ($this->outputTypeClass && $this->outputTypeClass->hasConfiguration()) {
+        $this->outputTypeClass->buildConfigurationForm($this, $this->output);
+        $this->assign('configuration_template', $this->outputTypeClass->getConfigurationTemplateFileName());
+      }
+
       $this->addButtons(array(
         array('type' => 'next', 'name' => E::ts('Save'), 'isDefault' => TRUE,),
         array('type' => 'cancel', 'name' => E::ts('Cancel'))));
@@ -67,9 +95,8 @@ class CRM_Dataprocessor_Form_Output extends CRM_Core_Form {
     $defaults['data_processor_id'] = $this->dataProcessorId;
     $defaults['id'] = $this->id;
 
-    $output = CRM_Dataprocessor_BAO_Output::getValues(array('id' => $this->id));
-    if (isset($output[$this->id]['type'])) {
-      $defaults['type'] = $output[$this->id]['type'];
+    if (isset($this->output['type'])) {
+      $defaults['type'] = $this->output['type'];
     }
     return $defaults;
   }
@@ -78,7 +105,7 @@ class CRM_Dataprocessor_Form_Output extends CRM_Core_Form {
     $session = CRM_Core_Session::singleton();
     $redirectUrl = $session->readUserContext();
     if ($this->_action == CRM_Core_Action::DELETE) {
-      CRM_Dataprocessor_BAO_Output::deleteWithId($this->id);
+      civicrm_api3('DataProcessorOutput', 'delete', array('id' => $this->id));
       $session->setStatus(E::ts('Data Processor Output removed'), E::ts('Removed'), 'success');
       CRM_Utils_System::redirect($redirectUrl);
     }
@@ -91,17 +118,8 @@ class CRM_Dataprocessor_Form_Output extends CRM_Core_Form {
     if ($this->id) {
       $params['id'] = $this->id;
     }
-    $result = CRM_Dataprocessor_BAO_Output::add($params);
-    $factory = dataprocessor_get_factory();
-    $outputClass  = $factory->getOutputByName($result['type']);
-    if  ($outputClass->getConfigurationUrl()) {
-      $redirectUrl = CRM_Utils_System::url($outputClass->getConfigurationUrl(), [
-        'reset' => 1,
-        'action' =>  'update',
-        'id' => $result['id'],
-        'data_processor_id' => $this->dataProcessorId
-      ]);
-    }
+    $params['configuration'] = $this->outputTypeClass->processConfiguration($values, $params);
+    $result = civicrm_api3('DataProcessorOutput', 'create', $params);
 
     CRM_Utils_System::redirect($redirectUrl);
     parent::postProcess();
diff --git a/CRM/Dataprocessor/Form/Output/API.php b/CRM/Dataprocessor/Form/Output/API.php
deleted file mode 100644
index c1318405..00000000
--- a/CRM/Dataprocessor/Form/Output/API.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-use CRM_Dataprocessor_ExtensionUtil as E;
-
-/**
- * Form controller class
- *
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/QuickForm+Reference
- */
-class CRM_Dataprocessor_Form_Output_API extends CRM_Dataprocessor_Form_Output_AbstractOutputForm {
-
-
-  public function buildQuickForm() {
-    parent::buildQuickForm();
-    $this->add('select','permission', E::ts('Permission'), CRM_Core_Permission::basicPermissions(), true, array(
-      'style' => 'min-width:250px',
-      'class' => 'crm-select2 huge',
-      'placeholder' => E::ts('- select -'),
-    ));
-    $this->add('text', 'api_entity', E::ts('API Entity'), true);
-    $this->add('text', 'api_action', E::ts('API Action Name'), true);
-    $this->add('text', 'api_count_action', E::ts('API GetCount Action Name'), true);
-  }
-
-  function setDefaultValues() {
-    $defaults = parent::setDefaultValues();
-    if ($this->output) {
-      $defaults['permission'] = $this->output['permission'];
-      $defaults['api_entity'] = $this->output['api_entity'];
-      $defaults['api_action'] = $this->output['api_action'];
-      $defaults['api_count_action'] = $this->output['api_count_action'];
-    } else {
-      $defaults['permission'] = 'access CiviCRM';
-    }
-    return $defaults;
-  }
-
-  public function postProcess() {
-    $session = CRM_Core_Session::singleton();
-    $redirectUrl = $session->readUserContext();
-
-    $values = $this->exportValues();
-    $params['id'] = $this->id;
-    $params['permission'] = $values['permission'];
-    $params['api_entity'] = $values['api_entity'];
-    $params['api_action'] = $values['api_action'];
-    $params['api_count_action'] = $values['api_count_action'];
-    CRM_Dataprocessor_BAO_Output::add($params);
-
-    CRM_Utils_System::redirect($redirectUrl);
-    parent::postProcess();
-  }
-
-}
\ No newline at end of file
diff --git a/CRM/Dataprocessor/Utils/Importer.php b/CRM/Dataprocessor/Utils/Importer.php
index a5b70651..23836204 100644
--- a/CRM/Dataprocessor/Utils/Importer.php
+++ b/CRM/Dataprocessor/Utils/Importer.php
@@ -75,7 +75,7 @@ class CRM_Dataprocessor_Utils_Importer {
     CRM_Dataprocessor_BAO_Source::deleteWithDataProcessorId($id);
     CRM_Dataprocessor_BAO_DataProcessorFilter::deleteWithDataProcessorId($id);
     CRM_Dataprocessor_BAO_DataProcessorField::deleteWithDataProcessorId($id);
-    CRM_Dataprocessor_BAO_Output::deleteWithDataProcessorId($id);
+    CRM_Dataprocessor_BAO_DataProcessorOutput::deleteWithDataProcessorId($id);
 
     foreach($data['data_sources'] as $data_source) {
       $params = $data_source;
@@ -95,7 +95,7 @@ class CRM_Dataprocessor_Utils_Importer {
     foreach($data['outputs'] as $output) {
       $params = $output;
       $params['data_processor_id'] = $id;
-      $result = CRM_Dataprocessor_BAO_Output::add($params);
+      civicrm_api3('DataProcessorOutput', 'create', $params);
     }
 
     return $id;
diff --git a/CRM/DataprocessorOutputExport/Page/Download.php b/CRM/DataprocessorOutputExport/Page/Download.php
index 33a6a31d..84f0bf50 100644
--- a/CRM/DataprocessorOutputExport/Page/Download.php
+++ b/CRM/DataprocessorOutputExport/Page/Download.php
@@ -32,8 +32,8 @@ class CRM_DataprocessorOutputExport_Page_Download extends CRM_Core_Page {
     $download_name = $prefix.'_'.$download_name;
 
     $data_processors = CRM_Dataprocessor_BAO_DataProcessor::getValues(array('id' => $dataProcessorId));
-    $outputs = CRM_Dataprocessor_BAO_Output::getValues(array('id' => $outputId));
-    $outputClass = $factory->getOutputByName($outputs[$outputId]['type']);
+    $output = civicrm_api3("DataProcessorOutput", "getsingle", array('id' => $outputId));
+    $outputClass = $factory->getOutputByName($output['type']);
     if (!$outputClass instanceof \Civi\DataProcessor\Output\ExportOutputInterface) {
       CRM_Core_Error::statusBounce("Malformed filename");
     } elseif ($userId != CRM_Core_Session::getLoggedInContactID()) {
diff --git a/CRM/DataprocessorSearch/ActivitySearch.php b/CRM/DataprocessorSearch/ActivitySearch.php
index bb22bd31..501953ac 100644
--- a/CRM/DataprocessorSearch/ActivitySearch.php
+++ b/CRM/DataprocessorSearch/ActivitySearch.php
@@ -6,8 +6,119 @@
 
 use Civi\DataProcessor\Output\UIOutputInterface;
 
+use CRM_Dataprocessor_ExtensionUtil as E;
+
 class CRM_DataprocessorSearch_ActivitySearch implements UIOutputInterface {
 
+  /**
+   * Returns true when this filter has additional configuration
+   *
+   * @return bool
+   */
+  public function hasConfiguration() {
+    return true;
+  }
+
+  /**
+   * When this filter type has additional configuration you can add
+   * the fields on the form with this function.
+   *
+   * @param \CRM_Core_Form $form
+   * @param array $filter
+   */
+  public function buildConfigurationForm(\CRM_Core_Form $form, $output=array()) {
+    $navigation = CRM_Dataprocessor_Utils_Navigation::singleton();
+    $dataProcessor = \CRM_Dataprocessor_BAO_DataProcessor::getDataProcessorById($output['data_processor_id']);
+    $fields = array();
+    foreach($dataProcessor->getDataFlow()->getOutputFieldHandlers() as $outputFieldHandler) {
+      $field = $outputFieldHandler->getOutputFieldSpecification();
+      $fields[$field->alias] = $field->title;
+    }
+
+    $form->add('text', 'title', E::ts('Title'), true);
+
+    $form->add('select','permission', E::ts('Permission'), \CRM_Core_Permission::basicPermissions(), true, array(
+      'style' => 'min-width:250px',
+      'class' => 'crm-select2 huge',
+      'placeholder' => E::ts('- select -'),
+    ));
+    $form->add('select', 'activity_id_field', E::ts('Activity ID field'), $fields, true, array(
+      'style' => 'min-width:250px',
+      'class' => 'crm-select2 huge',
+      'placeholder' => E::ts('- select -'),
+    ));
+    $form->add('select', 'hide_id_field', E::ts('Show Activity ID field'), array(0=>'Activity ID is Visible', 1=> 'Activity ID is hidden'));
+
+    $form->add('wysiwyg', 'help_text', E::ts('Help text for this search'), array('rows' => 6, 'cols' => 80));
+
+    // navigation field
+    $navigationOptions = $navigation->getNavigationOptions();
+    if (isset($output['configuration']['navigation_id'])) {
+      $navigationPath = $navigation->getNavigationPathById($output['configuration']['navigation_id']);
+      unset($navigationOptions[$navigationPath]);
+    }
+    $form->add('select', 'navigation_parent_path', ts('Parent Menu'), array('' => ts('- select -')) + $navigationOptions, true);
+
+    $defaults = array();
+    if ($output) {
+      if (isset($output['permission'])) {
+        $defaults['permission'] = $output['permission'];
+      }
+      if (isset($output['configuration']) && is_array($output['configuration'])) {
+        if (isset($output['configuration']['activity_id_field'])) {
+          $defaults['activity_id_field'] = $output['configuration']['activity_id_field'];
+        }
+        if (isset($output['configuration']['navigation_id'])) {
+          $defaults['navigation_parent_path'] = $navigation->getNavigationParentPathById($output['configuration']['navigation_id']);
+        }
+        if (isset($output['configuration']['title'])) {
+          $defaults['title'] = $output['configuration']['title'];
+        }
+        if (isset($output['configuration']['hide_id_field'])) {
+          $defaults['hide_id_field'] = $output['configuration']['hide_id_field'];
+        }
+        if (isset($output['configuration']['help_text'])) {
+          $defaults['help_text'] = $output['configuration']['help_text'];
+        }
+      }
+    }
+    if (!isset($defaults['permission'])) {
+      $defaults['permission'] = 'access CiviCRM';
+    }
+    if (empty($defaults['title'])) {
+      $defaults['title'] = civicrm_api3('DataProcessor', 'getvalue', array('id' => $output['data_processor_id'], 'return' => 'title'));
+    }
+    $form->setDefaults($defaults);
+  }
+
+  /**
+   * When this filter type has configuration specify the template file name
+   * for the configuration form.
+   *
+   * @return false|string
+   */
+  public function getConfigurationTemplateFileName() {
+    return "CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl";
+  }
+
+
+  /**
+   * Process the submitted values and create a configuration array
+   *
+   * @param $submittedValues
+   * @param array $output
+   * @return array
+   */
+  public function processConfiguration($submittedValues, &$output) {
+    $output['permission'] = $submittedValues['permission'];
+    $configuration['title'] = $submittedValues['title'];
+    $configuration['activity_id_field'] = $submittedValues['activity_id_field'];
+    $configuration['navigation_parent_path'] = $submittedValues['navigation_parent_path'];
+    $configuration['hide_id_field'] = $submittedValues['hide_id_field'];
+    $configuration['help_text'] = $submittedValues['help_text'];
+    return $configuration;
+  }
+
   /**
    * Returns the url for the page/form this output will show to the user
    *
@@ -50,16 +161,6 @@ class CRM_DataprocessorSearch_ActivitySearch implements UIOutputInterface {
     return 'CRM_DataprocessorSearch_Controller_ActivitySearch';
   }
 
-  /**
-   * Return the url to a configuration page.
-   * Or return false when no configuration page exists.
-   *
-   * @return string|false
-   */
-  public function getConfigurationUrl() {
-    return 'civicrm/dataprocessor/form/output/activity_search';
-  }
-
   /**
    * Checks whether the current user has access to this output
    *
diff --git a/CRM/DataprocessorSearch/ContactSearch.php b/CRM/DataprocessorSearch/ContactSearch.php
index 9c6bbc87..66ceeec5 100644
--- a/CRM/DataprocessorSearch/ContactSearch.php
+++ b/CRM/DataprocessorSearch/ContactSearch.php
@@ -5,17 +5,117 @@
  */
 
 use Civi\DataProcessor\Output\UIOutputInterface;
+use CRM_Dataprocessor_ExtensionUtil as E;
 
 class CRM_DataprocessorSearch_ContactSearch implements UIOutputInterface {
 
   /**
-   * Return the url to a configuration page.
-   * Or return false when no configuration page exists.
+   * Returns true when this filter has additional configuration
    *
-   * @return string|false
+   * @return bool
+   */
+  public function hasConfiguration() {
+    return true;
+  }
+
+  /**
+   * When this filter type has additional configuration you can add
+   * the fields on the form with this function.
+   *
+   * @param \CRM_Core_Form $form
+   * @param array $filter
+   */
+  public function buildConfigurationForm(\CRM_Core_Form $form, $output=array()) {
+    $navigation = CRM_Dataprocessor_Utils_Navigation::singleton();
+    $dataProcessor = \CRM_Dataprocessor_BAO_DataProcessor::getDataProcessorById($output['data_processor_id']);
+    $fields = array();
+    foreach($dataProcessor->getDataFlow()->getOutputFieldHandlers() as $outputFieldHandler) {
+      $field = $outputFieldHandler->getOutputFieldSpecification();
+      $fields[$field->alias] = $field->title;
+    }
+
+    $form->add('text', 'title', E::ts('Title'), true);
+
+    $form->add('select','permission', E::ts('Permission'), \CRM_Core_Permission::basicPermissions(), true, array(
+      'style' => 'min-width:250px',
+      'class' => 'crm-select2 huge',
+      'placeholder' => E::ts('- select -'),
+    ));
+    $form->add('select', 'contact_id_field', E::ts('Contact ID field'), $fields, true, array(
+      'style' => 'min-width:250px',
+      'class' => 'crm-select2 huge',
+      'placeholder' => E::ts('- select -'),
+    ));
+    $form->add('select', 'hide_id_field', E::ts('Show Contact ID field'), array(0=>'Contact ID is Visible', 1=> 'Contact ID is hidden'));
+
+    $form->add('wysiwyg', 'help_text', E::ts('Help text for this search'), array('rows' => 6, 'cols' => 80));
+
+    // navigation field
+    $navigationOptions = $navigation->getNavigationOptions();
+    if (isset($output['configuration']['navigation_id'])) {
+      $navigationPath = $navigation->getNavigationPathById($output['configuration']['navigation_id']);
+      unset($navigationOptions[$navigationPath]);
+    }
+    $form->add('select', 'navigation_parent_path', ts('Parent Menu'), array('' => ts('- select -')) + $navigationOptions, true);
+
+    $defaults = array();
+    if ($output) {
+      if (isset($output['permission'])) {
+        $defaults['permission'] = $output['permission'];
+      }
+      if (isset($output['configuration']) && is_array($output['configuration'])) {
+        if (isset($output['configuration']['contact_id_field'])) {
+          $defaults['contact_id_field'] = $output['configuration']['contact_id_field'];
+        }
+        if (isset($output['configuration']['navigation_id'])) {
+          $defaults['navigation_parent_path'] = $navigation->getNavigationParentPathById($output['configuration']['navigation_id']);
+        }
+        if (isset($output['configuration']['title'])) {
+          $defaults['title'] = $output['configuration']['title'];
+        }
+        if (isset($output['configuration']['hide_id_field'])) {
+          $defaults['hide_id_field'] = $output['configuration']['hide_id_field'];
+        }
+        if (isset($output['configuration']['help_text'])) {
+          $defaults['help_text'] = $output['configuration']['help_text'];
+        }
+      }
+    }
+    if (!isset($defaults['permission'])) {
+      $defaults['permission'] = 'access CiviCRM';
+    }
+    if (empty($defaults['title'])) {
+      $defaults['title'] = civicrm_api3('DataProcessor', 'getvalue', array('id' => $output['data_processor_id'], 'return' => 'title'));
+    }
+    $form->setDefaults($defaults);
+  }
+
+  /**
+   * When this filter type has configuration specify the template file name
+   * for the configuration form.
+   *
+   * @return false|string
+   */
+  public function getConfigurationTemplateFileName() {
+    return "CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl";
+  }
+
+
+  /**
+   * Process the submitted values and create a configuration array
+   *
+   * @param $submittedValues
+   * @param array $output
+   * @return array
    */
-  public function getConfigurationUrl() {
-    return 'civicrm/dataprocessor/form/output/contact_search';
+  public function processConfiguration($submittedValues, &$output) {
+    $output['permission'] = $submittedValues['permission'];
+    $configuration['title'] = $submittedValues['title'];
+    $configuration['contact_id_field'] = $submittedValues['contact_id_field'];
+    $configuration['navigation_parent_path'] = $submittedValues['navigation_parent_path'];
+    $configuration['hide_id_field'] = $submittedValues['hide_id_field'];
+    $configuration['help_text'] = $submittedValues['help_text'];
+    return $configuration;
   }
 
   /**
diff --git a/CRM/DataprocessorSearch/Form/AbstractSearch.php b/CRM/DataprocessorSearch/Form/AbstractSearch.php
index b363382b..eb5d5600 100644
--- a/CRM/DataprocessorSearch/Form/AbstractSearch.php
+++ b/CRM/DataprocessorSearch/Form/AbstractSearch.php
@@ -166,8 +166,7 @@ abstract class CRM_DataprocessorSearch_Form_AbstractSearch extends CRM_Dataproce
   protected function runExport($export_id) {
     $factory = dataprocessor_get_factory();
     self::applyFilters($this->dataProcessor, $this->_formValues);
-    $outputs = CRM_Dataprocessor_BAO_Output::getValues(array('id' => $export_id));
-    $output = $outputs[$export_id];
+    $output = civicrm_api3("DataProcessorOutput", "getsingle", array('id' => $export_id));
     $outputClass = $factory->getOutputByName($output['type']);
     if ($outputClass instanceof \Civi\DataProcessor\Output\ExportOutputInterface) {
       $outputClass->downloadExport($this->dataProcessor, $this->dataProcessorBAO, $output, $this->_formValues);
@@ -307,7 +306,7 @@ abstract class CRM_DataprocessorSearch_Form_AbstractSearch extends CRM_Dataproce
    */
   protected function addExportOutputs() {
     $factory = dataprocessor_get_factory();
-    $outputs = CRM_Dataprocessor_BAO_Output::getValues(array('data_processor_id' => $this->dataProcessorId));
+    $outputs = civicrm_api3('DataProcessorOutput', 'get', array('data_processor_id' => $this->dataProcessorId, 'options' => array('limit' => 0)));
     $otherOutputs = array();
     foreach($outputs as $output) {
       if ($output['id'] == $this->dataProcessorOutput['id']) {
diff --git a/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.php b/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.php
deleted file mode 100644
index cd422d9e..00000000
--- a/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-
-use CRM_Dataprocessor_ExtensionUtil as E;
-
-/**
- * Form controller class
- *
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/QuickForm+Reference
- */
-class CRM_DataprocessorSearch_Form_OutputConfiguration_ActivitySearch extends CRM_Dataprocessor_Form_Output_AbstractOutputForm {
-
-  /**
-   * @var CRM_Dataprocessor_Utils_Navigation
-   */
-  protected $navigation;
-
-  public function preProcess() {
-    parent::preProcess();
-    $this->navigation = CRM_Dataprocessor_Utils_Navigation::singleton();
-  }
-
-  public function buildQuickForm() {
-    parent::buildQuickForm();
-
-    $dataProcessor = CRM_Dataprocessor_BAO_DataProcessor::getDataProcessorById($this->dataProcessorId);
-    $fields = array();
-    foreach($dataProcessor->getDataFlow()->getOutputFieldHandlers() as $outputFieldHandler) {
-      $field = $outputFieldHandler->getOutputFieldSpecification();
-      $fields[$field->alias] = $field->title;
-    }
-
-    $this->add('text', 'title', E::ts('Title'), true);
-
-    $this->add('select','permission', E::ts('Permission'), CRM_Core_Permission::basicPermissions(), true, array(
-      'style' => 'min-width:250px',
-      'class' => 'crm-select2 huge',
-      'placeholder' => E::ts('- select -'),
-    ));
-    $this->add('select', 'activity_id_field', E::ts('Activity ID field'), $fields, true, array(
-      'style' => 'min-width:250px',
-      'class' => 'crm-select2 huge',
-      'placeholder' => E::ts('- select -'),
-    ));
-    $this->add('select', 'hide_id_field', E::ts('Show Activity ID field'), array(0=>'Activity ID is Visible', 1=> 'Activity ID is hidden'));
-
-    $this->add('wysiwyg', 'help_text', E::ts('Help text for this search'), array('rows' => 6, 'cols' => 80));
-
-    // navigation field
-    $navigationOptions = $this->navigation->getNavigationOptions();
-    if (isset($this->output['configuration']['navigation_id'])) {
-      $navigationPath = $this->navigation->getNavigationPathById($this->output['configuration']['navigation_id']);
-      unset($navigationOptions[$navigationPath]);
-    }
-    $this->add('select', 'navigation_parent_path', ts('Parent Menu'), array('' => ts('- select -')) + $navigationOptions, true);
-  }
-
-  function setDefaultValues() {
-    $dataProcessors = CRM_Dataprocessor_BAO_DataProcessor::getValues(array('id' => $this->dataProcessorId));
-    $dataProcessor = $dataProcessors[$this->dataProcessorId];
-
-    $defaults = parent::setDefaultValues();
-    if ($this->output) {
-      if (isset($this->output['permission'])) {
-        $defaults['permission'] = $this->output['permission'];
-      }
-      if (isset($this->output['configuration']) && is_array($this->output['configuration'])) {
-        if (isset($this->output['configuration']['activity_id_field'])) {
-          $defaults['activity_id_field'] = $this->output['configuration']['activity_id_field'];
-        }
-        if (isset($this->output['configuration']['navigation_id'])) {
-          $defaults['navigation_parent_path'] = $this->navigation->getNavigationParentPathById($this->output['configuration']['navigation_id']);
-        }
-        if (isset($this->output['configuration']['title'])) {
-          $defaults['title'] = $this->output['configuration']['title'];
-        }
-        if (isset($this->output['configuration']['hide_id_field'])) {
-          $defaults['hide_id_field'] = $this->output['configuration']['hide_id_field'];
-        }
-        if (isset($this->output['configuration']['help_text'])) {
-          $defaults['help_text'] = $this->output['configuration']['help_text'];
-        }
-      }
-    }
-    if (!isset($defaults['permission'])) {
-      $defaults['permission'] = 'access CiviCRM';
-    }
-    if (empty($defaults['title'])) {
-      $defaults['title'] = $dataProcessor['title'];
-    }
-
-    return $defaults;
-  }
-
-  public function postProcess() {
-    $values = $this->exportValues();
-
-    $session = CRM_Core_Session::singleton();
-    $redirectUrl = $session->readUserContext();
-
-    $params['id'] = $this->id;
-    $params['permission'] = $values['permission'];
-    $params['configuration']['title'] = $values['title'];
-    $params['configuration']['activity_id_field'] = $values['activity_id_field'];
-    $params['configuration']['navigation_parent_path'] = $values['navigation_parent_path'];
-    $params['configuration']['hide_id_field'] = $values['hide_id_field'];
-    $params['configuration']['help_text'] = $values['help_text'];
-
-    CRM_Dataprocessor_BAO_Output::add($params);
-
-    CRM_Utils_System::redirect($redirectUrl);
-    parent::postProcess();
-  }
-
-}
\ No newline at end of file
diff --git a/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.php b/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.php
deleted file mode 100644
index 71530ee1..00000000
--- a/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-
-use CRM_Dataprocessor_ExtensionUtil as E;
-
-/**
- * Form controller class
- *
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/QuickForm+Reference
- */
-class CRM_DataprocessorSearch_Form_OutputConfiguration_ContactSearch extends CRM_Dataprocessor_Form_Output_AbstractOutputForm {
-
-  /**
-   * @var CRM_Dataprocessor_Utils_Navigation
-   */
-  protected $navigation;
-
-  public function preProcess() {
-    parent::preProcess();
-    $this->navigation = CRM_Dataprocessor_Utils_Navigation::singleton();
-  }
-
-  public function buildQuickForm() {
-    parent::buildQuickForm();
-
-    $dataProcessor = CRM_Dataprocessor_BAO_DataProcessor::getDataProcessorById($this->dataProcessorId);
-    $fields = array();
-    foreach($dataProcessor->getDataFlow()->getOutputFieldHandlers() as $outputFieldHandler) {
-      $field = $outputFieldHandler->getOutputFieldSpecification();
-      $fields[$field->alias] = $field->title;
-    }
-
-    $this->add('text', 'title', E::ts('Title'), true);
-
-    $this->add('select','permission', E::ts('Permission'), CRM_Core_Permission::basicPermissions(), true, array(
-      'style' => 'min-width:250px',
-      'class' => 'crm-select2 huge',
-      'placeholder' => E::ts('- select -'),
-    ));
-    $this->add('select', 'contact_id_field', E::ts('Contact ID field'), $fields, true, array(
-      'style' => 'min-width:250px',
-      'class' => 'crm-select2 huge',
-      'placeholder' => E::ts('- select -'),
-    ));
-    $this->add('select', 'hide_id_field', E::ts('Show Contact ID field'), array(0=>'Contact ID is Visible', 1=> 'Contact ID is hidden'));
-
-    $this->add('wysiwyg', 'help_text', E::ts('Help text for this search'), array('rows' => 6, 'cols' => 80));
-
-    // navigation field
-    $navigationOptions = $this->navigation->getNavigationOptions();
-    if (isset($this->output['configuration']['navigation_id'])) {
-      $navigationPath = $this->navigation->getNavigationPathById($this->output['configuration']['navigation_id']);
-      unset($navigationOptions[$navigationPath]);
-    }
-    $this->add('select', 'navigation_parent_path', ts('Parent Menu'), array('' => ts('- select -')) + $navigationOptions, true);
-  }
-
-  function setDefaultValues() {
-    $dataProcessors = CRM_Dataprocessor_BAO_DataProcessor::getValues(array('id' => $this->dataProcessorId));
-    $dataProcessor = $dataProcessors[$this->dataProcessorId];
-
-    $defaults = parent::setDefaultValues();
-    if ($this->output) {
-      if (isset($this->output['permission'])) {
-        $defaults['permission'] = $this->output['permission'];
-      }
-      if (isset($this->output['configuration']) && is_array($this->output['configuration'])) {
-        if (isset($this->output['configuration']['contact_id_field'])) {
-          $defaults['contact_id_field'] = $this->output['configuration']['contact_id_field'];
-        }
-        if (isset($this->output['configuration']['navigation_id'])) {
-          $defaults['navigation_parent_path'] = $this->navigation->getNavigationParentPathById($this->output['configuration']['navigation_id']);
-        }
-        if (isset($this->output['configuration']['title'])) {
-          $defaults['title'] = $this->output['configuration']['title'];
-        }
-        if (isset($this->output['configuration']['hide_id_field'])) {
-          $defaults['hide_id_field'] = $this->output['configuration']['hide_id_field'];
-        }
-        if (isset($this->output['configuration']['help_text'])) {
-          $defaults['help_text'] = $this->output['configuration']['help_text'];
-        }
-      }
-    }
-    if (!isset($defaults['permission'])) {
-      $defaults['permission'] = 'access CiviCRM';
-    }
-    if (empty($defaults['title'])) {
-      $defaults['title'] = $dataProcessor['title'];
-    }
-
-    return $defaults;
-  }
-
-  public function postProcess() {
-    $values = $this->exportValues();
-
-    $session = CRM_Core_Session::singleton();
-    $redirectUrl = $session->readUserContext();
-
-    $params['id'] = $this->id;
-    $params['permission'] = $values['permission'];
-    $params['configuration']['title'] = $values['title'];
-    $params['configuration']['contact_id_field'] = $values['contact_id_field'];
-    $params['configuration']['navigation_parent_path'] = $values['navigation_parent_path'];
-    $params['configuration']['hide_id_field'] = $values['hide_id_field'];
-    $params['configuration']['help_text'] = $values['help_text'];
-
-    CRM_Dataprocessor_BAO_Output::add($params);
-
-    CRM_Utils_System::redirect($redirectUrl);
-    parent::postProcess();
-  }
-
-}
\ No newline at end of file
diff --git a/Civi/DataProcessor/Output/Api.php b/Civi/DataProcessor/Output/Api.php
index 24238765..b15dd606 100644
--- a/Civi/DataProcessor/Output/Api.php
+++ b/Civi/DataProcessor/Output/Api.php
@@ -13,6 +13,8 @@ use Civi\API\Provider\ProviderInterface as API_ProviderInterface;
 use Civi\DataProcessor\ProcessorType\AbstractProcessorType;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
+use \CRM_Dataprocessor_ExtensionUtil as E;
+
 class Api implements OutputInterface, API_ProviderInterface, EventSubscriberInterface{
 
   public function __construct() {
@@ -20,13 +22,66 @@ class Api implements OutputInterface, API_ProviderInterface, EventSubscriberInte
   }
 
   /**
-   * Return the url to a configuration page.
-   * Or return false when no configuration page exists.
+   * Returns true when this filter has additional configuration
+   *
+   * @return bool
+   */
+  public function hasConfiguration() {
+    return true;
+  }
+
+  /**
+   * When this filter type has additional configuration you can add
+   * the fields on the form with this function.
    *
-   * @return string|false
+   * @param \CRM_Core_Form $form
+   * @param array $filter
+   */
+  public function buildConfigurationForm(\CRM_Core_Form $form, $output=array()) {
+    $form->add('select','permission', E::ts('Permission'), \CRM_Core_Permission::basicPermissions(), true, array(
+      'style' => 'min-width:250px',
+      'class' => 'crm-select2 huge',
+      'placeholder' => E::ts('- select -'),
+    ));
+    $form->add('text', 'api_entity', E::ts('API Entity'), true);
+    $form->add('text', 'api_action', E::ts('API Action Name'), true);
+    $form->add('text', 'api_count_action', E::ts('API GetCount Action Name'), true);
+
+    if ($output) {
+      $defaults['permission'] = $output['permission'];
+      $defaults['api_entity'] = $output['api_entity'];
+      $defaults['api_action'] = $output['api_action'];
+      $defaults['api_count_action'] = $output['api_count_action'];
+    } else {
+      $defaults['permission'] = 'access CiviCRM';
+    }
+    $form->setDefaults($defaults);
+  }
+
+  /**
+   * When this filter type has configuration specify the template file name
+   * for the configuration form.
+   *
+   * @return false|string
+   */
+  public function getConfigurationTemplateFileName() {
+    return "CRM/Dataprocessor/Form/Output/API.tpl";
+  }
+
+
+  /**
+   * Process the submitted values and create a configuration array
+   *
+   * @param $submittedValues
+   * @param array $output
+   * @return array
    */
-  public function getConfigurationUrl() {
-    return 'civicrm/dataprocessor/form/output/api';
+  public function processConfiguration($submittedValues, &$output) {
+    $output['permission'] = $submittedValues['permission'];
+    $output['api_entity'] = $submittedValues['api_entity'];
+    $output['api_action'] = $submittedValues['api_action'];
+    $output['api_count_action'] = $submittedValues['api_count_action'];
+    return array();
   }
 
   /**
diff --git a/Civi/DataProcessor/Output/OutputInterface.php b/Civi/DataProcessor/Output/OutputInterface.php
index e3a780e7..89e871be 100644
--- a/Civi/DataProcessor/Output/OutputInterface.php
+++ b/Civi/DataProcessor/Output/OutputInterface.php
@@ -9,11 +9,37 @@ namespace Civi\DataProcessor\Output;
 interface OutputInterface {
 
   /**
-   * Return the url to a configuration page.
-   * Or return false when no configuration page exists.
+   * Returns true when this output has additional configuration
    *
-   * @return string|false
+   * @return bool
    */
-  public function getConfigurationUrl();
+  public function hasConfiguration();
+
+  /**
+   * When this output type has additional configuration you can add
+   * the fields on the form with this function.
+   *
+   * @param \CRM_Core_Form $form
+   * @param array $output
+   */
+  public function buildConfigurationForm(\CRM_Core_Form $form, $output=array());
+
+  /**
+   * When this output type has configuration specify the template file name
+   * for the configuration form.
+   *
+   * @return false|string
+   */
+  public function getConfigurationTemplateFileName();
+
+
+  /**
+   * Process the submitted values and create a configuration array
+   *
+   * @param $submittedValues
+   * @param array $output
+   * @return array $output
+   */
+  public function processConfiguration($submittedValues, &$output);
 
 }
\ No newline at end of file
diff --git a/Civi/DataProcessor/Output/UIOutputHelper.php b/Civi/DataProcessor/Output/UIOutputHelper.php
index 13b5c00b..bb1e9f33 100644
--- a/Civi/DataProcessor/Output/UIOutputHelper.php
+++ b/Civi/DataProcessor/Output/UIOutputHelper.php
@@ -34,8 +34,7 @@ class UIOutputHelper {
     while ($dao->fetch()) {
       $outputClass = $factory->getOutputByName($dao->type);
       if ($outputClass instanceof \Civi\DataProcessor\Output\UIOutputInterface) {
-        $outputs = \CRM_Dataprocessor_BAO_Output::getValues(['id' => $dao->output_id]);
-        $output = $outputs[$dao->output_id];
+        $output = civicrm_api3('DataProcessorOutput', 'getsingle', array('id' => $dao->output_id));
         $dataprocessors = \CRM_Dataprocessor_BAO_DataProcessor::getValues(['id' => $dao->id]);
         $dataprocessor = $dataprocessors[$dao->id];
         $url = $outputClass->getUrlToUi($output, $dataprocessor);
@@ -68,21 +67,20 @@ class UIOutputHelper {
       return;
     }
     if ($op == 'delete') {
-      $outputs = \CRM_Dataprocessor_BAO_Output::getValues(array('id' => $id));
-      if (isset($outputs[$id]['configuration']['navigation_id'])) {
-        $navId = $outputs[$id]['configuration']['navigation_id'];
+      $output = civicrm_api3('DataProcessorOutput', 'getsingle', array('id' => $id));
+      if (isset($output['configuration']['navigation_id'])) {
+        $navId = $output['configuration']['navigation_id'];
         \CRM_Core_BAO_Navigation::processDelete($navId);
         \CRM_Core_BAO_Navigation::resetNavigation();
         self::$rebuildMenu = TRUE;
       }
     } elseif ($op == 'edit') {
-      $outputs = \CRM_Dataprocessor_BAO_Output::getValues(array('id' => $id));
-      $output = $outputs[$id];
+      $output = civicrm_api3('DataProcessorOutput', 'getsingle', array('id' => $id));
       if (!isset($output['configuration']['navigation_id']) && !isset($params['configuration']['navigation_parent_path'])) {
         return;
       } elseif (!isset($params['configuration']['navigation_parent_path'])) {
         // Delete the navigation item
-        $navId = $outputs[$id]['configuration']['navigation_id'];
+        $navId = $output['configuration']['navigation_id'];
         \CRM_Core_BAO_Navigation::processDelete($navId);
         \CRM_Core_BAO_Navigation::resetNavigation();
         self::$rebuildMenu = TRUE;
@@ -92,10 +90,10 @@ class UIOutputHelper {
 
         // Retrieve the current navigation params.
         $navigationParams = [];
-        if (isset($outputs[$id]['configuration']['navigation_id'])) {
+        if (isset($output['configuration']['navigation_id'])) {
           // Get the default navigation parent id.
           $navigationDefaults = [];
-          $navParams = ['id' => $outputs[$id]['configuration']['navigation_id']];
+          $navParams = ['id' => $output['configuration']['navigation_id']];
           \CRM_Core_BAO_Navigation::retrieve($navParams, $navigationDefaults);
           if (!empty($navigationDefaults['id'])) {
             $navigationParams['id'] = $navigationDefaults['id'];
diff --git a/api/v3/DataProcessorOutput.php b/api/v3/DataProcessorOutput.php
new file mode 100644
index 00000000..79a33215
--- /dev/null
+++ b/api/v3/DataProcessorOutput.php
@@ -0,0 +1,76 @@
+<?php
+use CRM_Dataprocessor_ExtensionUtil as E;
+
+/**
+ * DataProcessorOutput.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/CRMDOC/API+Architecture+Standards
+ */
+function _civicrm_api3_data_processor_output_create_spec(&$spec) {
+  $fields = CRM_Dataprocessor_DAO_DataProcessorOutput::fields();
+  foreach($fields as $fieldname => $field) {
+    $spec[$fieldname] = $field;
+    if ($fieldname != 'id' && isset($field['required']) && $field['required']) {
+      $spec[$fieldname]['api.required'] = true;
+    }
+  }
+}
+
+/**
+ * DataProcessorOutput.create API
+ *
+ * @param array $params
+ * @return array API result descriptor
+ * @throws API_Exception
+ */
+function civicrm_api3_data_processor_output_create($params) {
+  return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+}
+
+/**
+ * DataProcessorOutput.delete API
+ *
+ * @param array $params
+ * @return array API result descriptor
+ * @throws API_Exception
+ */
+function civicrm_api3_data_processor_output_delete($params) {
+  return _civicrm_api3_basic_delete(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+}
+
+/**
+ * DataProcessorOutput.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/CRMDOC/API+Architecture+Standards
+ */
+function civicrm_api3_data_processor_output_get_spec(&$spec) {
+  $fields = CRM_Dataprocessor_DAO_DataProcessorOutput::fields();
+  foreach($fields as $fieldname => $field) {
+    $spec[$fieldname] = $field;
+  }
+}
+
+/**
+ * DataProcessorOutput.get API
+ *
+ * @param array $params
+ * @return array API result descriptor
+ * @throws API_Exception
+ */
+function civicrm_api3_data_processor_output_get($params) {
+  $return = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+  foreach($return['values'] as $id => $value) {
+    if (isset($value['configuration'])) {
+      $return['values'][$id]['configuration'] = json_decode($value['configuration'], TRUE);
+    } else {
+      $return['values'][$id]['configuration'] = array();
+    }
+  }
+  return $return;
+}
diff --git a/api/v3/DataProcessorOutput/Create.php b/api/v3/DataProcessorOutput/Create.php
deleted file mode 100644
index a217729f..00000000
--- a/api/v3/DataProcessorOutput/Create.php
+++ /dev/null
@@ -1,76 +0,0 @@
-<?php
-
-use CRM_Dataprocessor_ExtensionUtil as E;
-
-/**
- * DataProcessorOutput.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_data_processor_output_create_spec(&$spec) {
-  $spec['id'] = array(
-		'title' => E::ts('ID'),
-		'type' => CRM_Utils_Type::T_INT,
-		'api.required' => false
-	);
-  $spec['data_processor_id'] = array(
-    'title' => E::ts('Data Processor ID'),
-    'type' => CRM_Utils_Type::T_INT,
-    'api.required' => true,
-  );
-  $spec['type'] = array(
-    'title' => E::ts('Type'),
-    'type' => CRM_Utils_Type::T_STRING,
-    'api.required' => true
-  );
-	$spec['title'] = array(
-		'title' => E::ts('Title'),
-		'type' => CRM_Utils_Type::T_STRING,
-		'api.required' => true
-	);
-	$spec['configuration'] = array(
-    'title' => E::ts('Description'),
-    'type' => CRM_Utils_Type::T_TEXT,
-    'api.required' => false,
-	);
-  $spec['permission'] = array(
-    'name' => 'permission',
-    'title' => E::ts('Permission'),
-    'type' => CRM_Utils_Type::T_STRING
-  );
-  $spec['api_entity'] = array(
-    'name' => 'api_entity',
-    'title' => E::ts('API Entity'),
-    'type' => CRM_Utils_Type::T_STRING
-  );
-  $spec['api_action'] = array(
-    'name' => 'api_action',
-    'title' => E::ts('API Action name'),
-    'type' => CRM_Utils_Type::T_STRING
-  );
-  $spec['api_count_action'] = array(
-    'name' => 'api_count_action',
-    'title' => E::ts('API GetCount Action name'),
-    'type' => CRM_Utils_Type::T_STRING
-  );
-}
-
-/**
- * DataProcessorOutput.Create API
- *
- * @param array $params
- * @return array API result descriptor
- * @see civicrm_api3_create_success
- * @see civicrm_api3_create_error
- *
- *
- */
-function civicrm_api3_data_processor_output_create($params) {
-  $returnValue = CRM_Dataprocessor_BAO_Output::add($params);
-	$returnValues[$returnValue['id']] = $returnValue;
-  return civicrm_api3_create_success($returnValues, $params, 'DataProcessorOutput', 'Create');
-}
-
diff --git a/api/v3/DataProcessorOutput/Delete.php b/api/v3/DataProcessorOutput/Delete.php
deleted file mode 100644
index 35dd1e3a..00000000
--- a/api/v3/DataProcessorOutput/Delete.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-use CRM_Dataprocessor_ExtensionUtil as E;
-
-/**
- * DataProcessor.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_data_processor_Delete_spec(&$spec) {
-  $spec['id'] = array(
-		'title' => E::ts('ID'),
-		'type' => CRM_Utils_Type::T_INT,
-		'api.required' => true
-	);
-}
-
-/**
- * DataProcessor.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_data_processor_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_Dataprocessor_BAO_DataProcessor::deleteWithId($params['id']), $params, 'DataProcessor', 'Delete');
-  }
-}
-
diff --git a/api/v3/DataProcessorOutput/Get.php b/api/v3/DataProcessorOutput/Get.php
deleted file mode 100644
index 7e5d5341..00000000
--- a/api/v3/DataProcessorOutput/Get.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-/**
- * DataProcessorOutput.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_data_processor_output_get($params) {
-  $returnValues = CRM_Dataprocessor_BAO_Output::getValues($params);
-  return civicrm_api3_create_success($returnValues, $params, 'DataProcessorOutput', 'Get');
-}
-
-/**
- * DataProcessorOutput.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_data_processor_output_get_spec(&$spec) {
-	$fields = CRM_Dataprocessor_BAO_Output::fields();
-	foreach($fields as $fieldname => $field) {
-		$spec[$fieldname] = $field;
-	}
-}
-
diff --git a/dataprocessor.civix.php b/dataprocessor.civix.php
index e993b955..79799c6a 100644
--- a/dataprocessor.civix.php
+++ b/dataprocessor.civix.php
@@ -469,5 +469,11 @@ function _dataprocessor_civix_civicrm_entityTypes(&$entityTypes) {
       'class' => 'CRM_Dataprocessor_DAO_DataProcessorFilter',
       'table' => 'civicrm_data_processor_filter',
     ),
+    'CRM_Dataprocessor_DAO_DataProcessorOutput' => 
+    array (
+      'name' => 'DataProcessorOutput',
+      'class' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+      'table' => 'civicrm_data_processor_output',
+    ),
   ));
 }
diff --git a/sql/auto_install.sql b/sql/auto_install.sql
index e2e5878e..deb614e8 100644
--- a/sql/auto_install.sql
+++ b/sql/auto_install.sql
@@ -62,6 +62,7 @@
 
 SET FOREIGN_KEY_CHECKS=0;
 
+DROP TABLE IF EXISTS `civicrm_data_processor_output`;
 DROP TABLE IF EXISTS `civicrm_data_processor_filter`;
 DROP TABLE IF EXISTS `civicrm_data_processor_field`;
 
@@ -117,4 +118,27 @@ CREATE TABLE `civicrm_data_processor_filter` (
 ,          CONSTRAINT FK_civicrm_data_processor_filter_data_processor_id FOREIGN KEY (`data_processor_id`) REFERENCES `civicrm_data_processor`(`id`) ON DELETE CASCADE  
 )    ;
 
+-- /*******************************************************
+-- *
+-- * civicrm_data_processor_output
+-- *
+-- *******************************************************/
+CREATE TABLE `civicrm_data_processor_output` (
+
+
+     `id` int unsigned NOT NULL AUTO_INCREMENT  COMMENT 'Unique DataProcessorOutput ID',
+     `data_processor_id` int unsigned NOT NULL   COMMENT 'FK to Data Processor',
+     `type` varchar(255) NOT NULL   ,
+     `configuration` text NULL   ,
+     `permission` varchar(255) NULL   ,
+     `api_entity` varchar(255) NULL   ,
+     `api_action` varchar(255) NULL   ,
+     `api_count_action` varchar(255) NULL    
+,
+        PRIMARY KEY (`id`)
+ 
+ 
+,          CONSTRAINT FK_civicrm_data_processor_output_data_processor_id FOREIGN KEY (`data_processor_id`) REFERENCES `civicrm_data_processor`(`id`) ON DELETE CASCADE  
+)    ;
+
  
diff --git a/sql/auto_uninstall.sql b/sql/auto_uninstall.sql
index f4972768..9bb45afb 100644
--- a/sql/auto_uninstall.sql
+++ b/sql/auto_uninstall.sql
@@ -33,6 +33,7 @@
 
 SET FOREIGN_KEY_CHECKS=0;
 
+DROP TABLE IF EXISTS `civicrm_data_processor_output`;
 DROP TABLE IF EXISTS `civicrm_data_processor_filter`;
 DROP TABLE IF EXISTS `civicrm_data_processor_field`;
 
diff --git a/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Filters.tpl b/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Filters.tpl
index 27e44682..90448919 100644
--- a/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Filters.tpl
+++ b/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Filters.tpl
@@ -8,7 +8,6 @@
                 <th></th>
                 <th></th>
                 <th></th>
-                <th></th>
             </tr>
             {foreach from=$filters item=filter}
                 <tr>
@@ -20,11 +19,6 @@
                     </td>
                     <td><span class="description">{$filter.name}</span></td>
                     <td>{if ($filter.weight && !is_numeric($filter.weight))}{$filter.weight}{/if}</td>
-                    <td>
-                        {if $filter.configuration_link}
-                            <a href="{$filter.configuration_link}">{ts}Configure Filter{/ts}</a>
-                        {/if}
-                    </td>
                     <td>
                         <a href="{crmURL p="civicrm/dataprocessor/form/filter" q="reset=1&action=update&data_processor_id=`$filter.data_processor_id`&id=`$filter.id`"}">{ts}Edit{/ts}</a>
                     </td>
diff --git a/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Outputs.tpl b/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Outputs.tpl
index 8dac0620..34153305 100644
--- a/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Outputs.tpl
+++ b/templates/CRM/Dataprocessor/Form/DataProcessorBlocks/Outputs.tpl
@@ -6,16 +6,11 @@
             <th>{ts}Output{/ts}</th>
             <th></th>
             <th></th>
-            <th></th>
         </tr>
         {foreach from=$outputs item=output}
             <tr>
                 <td>{$output.type_name}</td>
                 <td>
-                    {if ($output.configuration_link)}
-                        <a href="{$output.configuration_link}">{ts}Configure{/ts}</a>
-                    {/if}
-                </td><td>
                     <a href="{crmURL p="civicrm/dataprocessor/form/output" q="reset=1&action=update&data_processor_id=`$output.data_processor_id`&id=`$output.id`"}">{ts}Edit{/ts}</a>
                 </td><td>
                     <a href="{crmURL p="civicrm/dataprocessor/form/output" q="reset=1&action=delete&data_processor_id=`$output.data_processor_id`&id=`$output.id`"}">{ts}Remove{/ts}</a>
diff --git a/templates/CRM/Dataprocessor/Form/Output.tpl b/templates/CRM/Dataprocessor/Form/Output.tpl
index 46ef08e8..f0628bc9 100644
--- a/templates/CRM/Dataprocessor/Form/Output.tpl
+++ b/templates/CRM/Dataprocessor/Form/Output.tpl
@@ -1,7 +1,4 @@
 {crmScope extensionKey='dataprocessor'}
-<div class="crm-submit-buttons">
-    {include file="CRM/common/formButtons.tpl" location="top"}
-</div>
 
 {if $action eq 8}
     {* Are you sure to delete form *}
@@ -9,20 +6,56 @@
     <div class="crm-block crm-form-block crm-data-processor_label-block">
         <div class="crm-section">{ts}Are you sure to delete data processor output?{/ts}</div>
     </div>
-{else}
+
+    <div class="crm-submit-buttons">
+        {include file="CRM/common/formButtons.tpl" location="bottom"}
+    </div>
+{elseif (!$snippet)}
 
     {* block for rule data *}
-    <h3>{ts}Data Processor Source{/ts}</h3>
+    <h3>{ts}Data Processor Output{/ts}</h3>
     <div class="crm-block crm-form-block crm-data-processor_output-block">
         <div class="crm-section">
             <div class="label">{$form.type.label}</div>
             <div class="content">{$form.type.html}</div>
             <div class="clear"></div>
         </div>
+
+    <div id="type_configuration">
+        {if ($configuration_template)}
+            {include file=$configuration_template}
+        {/if}
+    </div>
+
     </div>
-{/if}
 
-<div class="crm-submit-buttons">
-    {include file="CRM/common/formButtons.tpl" location="bottom"}
-</div>
+    <div class="crm-submit-buttons">
+        {include file="CRM/common/formButtons.tpl" location="bottom"}
+    </div>
+
+    <script type="text/javascript">
+        {literal}
+        CRM.$(function($) {
+          var id = {/literal}{if ($output)}{$output.id}{else}false{/if}{literal};
+          var data_processor_id = {/literal}{$data_processor_id}{literal};
+
+          $('#type').on('change', function() {
+            var type = $('#type').val();
+            if (type) {
+              var dataUrl = CRM.url('civicrm/dataprocessor/form/output', {type: type, 'data_processor_id': data_processor_id, 'id': id});
+              CRM.loadPage(dataUrl, {'target': '#type_configuration'});
+            }
+          });
+
+          $('#type').change();
+        });
+        {/literal}
+    </script>
+{else}
+    <div id="type_configuration">
+        {if ($configuration_template)}
+            {include file=$configuration_template}
+        {/if}
+    </div>
+{/if}
 {/crmScope}
\ No newline at end of file
diff --git a/templates/CRM/Dataprocessor/Form/Output/API.tpl b/templates/CRM/Dataprocessor/Form/Output/API.tpl
index b2f11813..ad3520df 100644
--- a/templates/CRM/Dataprocessor/Form/Output/API.tpl
+++ b/templates/CRM/Dataprocessor/Form/Output/API.tpl
@@ -1,33 +1,24 @@
 {crmScope extensionKey='dataprocessor'}
-    <div class="crm-submit-buttons">
-        {include file="CRM/common/formButtons.tpl" location="top"}
-    </div>
 
-    <h3>{ts}Output configuration{/ts}</h3>
-    <div class="crm-block crm-form-block crm-data-processor_output-block">
-        <div class="crm-section">
-            <div class="label">{$form.api_entity.label}</div>
-            <div class="content">{$form.api_entity.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.api_action.label}</div>
-            <div class="content">{$form.api_action.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.api_count_action.label}</div>
-            <div class="content">{$form.api_count_action.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.permission.label}</div>
-            <div class="content">{$form.permission.html}</div>
-            <div class="clear"></div>
-        </div>
+    <div class="crm-section">
+        <div class="label">{$form.api_entity.label}</div>
+        <div class="content">{$form.api_entity.html}</div>
+        <div class="clear"></div>
     </div>
-
-    <div class="crm-submit-buttons">
-        {include file="CRM/common/formButtons.tpl" location="bottom"}
+    <div class="crm-section">
+        <div class="label">{$form.api_action.label}</div>
+        <div class="content">{$form.api_action.html}</div>
+        <div class="clear"></div>
+    </div>
+    <div class="crm-section">
+        <div class="label">{$form.api_count_action.label}</div>
+        <div class="content">{$form.api_count_action.html}</div>
+        <div class="clear"></div>
     </div>
+    <div class="crm-section">
+        <div class="label">{$form.permission.label}</div>
+        <div class="content">{$form.permission.html}</div>
+        <div class="clear"></div>
+    </div>
+
 {/crmScope}
\ No newline at end of file
diff --git a/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl
index adf7c385..9f0bbbbb 100644
--- a/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl
+++ b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl
@@ -1,43 +1,32 @@
 {crmScope extensionKey='dataprocessor'}
-    <div class="crm-submit-buttons">
-        {include file="CRM/common/formButtons.tpl" location="top"}
+    <div class="crm-section">
+        <div class="label">{$form.title.label}</div>
+        <div class="content">{$form.title.html}</div>
+        <div class="clear"></div>
     </div>
-
-    <h3>{ts}Output configuration{/ts}</h3>
-    <div class="crm-block crm-form-block crm-data-processor_output-block">
-        <div class="crm-section">
-            <div class="label">{$form.title.label}</div>
-            <div class="content">{$form.title.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.navigation_parent_path.label}</div>
-            <div class="content">{$form.navigation_parent_path.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.permission.label}</div>
-            <div class="content">{$form.permission.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.activity_id_field.label}</div>
-            <div class="content">{$form.activity_id_field.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.hide_id_field.label}</div>
-            <div class="content">{$form.hide_id_field.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.help_text.label}</div>
-            <div class="content">{$form.help_text.html}</div>
-            <div class="clear"></div>
-        </div>
+    <div class="crm-section">
+        <div class="label">{$form.navigation_parent_path.label}</div>
+        <div class="content">{$form.navigation_parent_path.html}</div>
+        <div class="clear"></div>
     </div>
-
-    <div class="crm-submit-buttons">
-        {include file="CRM/common/formButtons.tpl" location="bottom"}
+    <div class="crm-section">
+        <div class="label">{$form.permission.label}</div>
+        <div class="content">{$form.permission.html}</div>
+        <div class="clear"></div>
+    </div>
+    <div class="crm-section">
+        <div class="label">{$form.activity_id_field.label}</div>
+        <div class="content">{$form.activity_id_field.html}</div>
+        <div class="clear"></div>
+    </div>
+    <div class="crm-section">
+        <div class="label">{$form.hide_id_field.label}</div>
+        <div class="content">{$form.hide_id_field.html}</div>
+        <div class="clear"></div>
+    </div>
+    <div class="crm-section">
+        <div class="label">{$form.help_text.label}</div>
+        <div class="content">{$form.help_text.html}</div>
+        <div class="clear"></div>
     </div>
 {/crmScope}
\ No newline at end of file
diff --git a/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl
index 91f8eece..4a606293 100644
--- a/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl
+++ b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl
@@ -1,43 +1,32 @@
 {crmScope extensionKey='dataprocessor'}
-    <div class="crm-submit-buttons">
-        {include file="CRM/common/formButtons.tpl" location="top"}
+    <div class="crm-section">
+        <div class="label">{$form.title.label}</div>
+        <div class="content">{$form.title.html}</div>
+        <div class="clear"></div>
     </div>
-
-    <h3>{ts}Output configuration{/ts}</h3>
-    <div class="crm-block crm-form-block crm-data-processor_output-block">
-        <div class="crm-section">
-            <div class="label">{$form.title.label}</div>
-            <div class="content">{$form.title.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.navigation_parent_path.label}</div>
-            <div class="content">{$form.navigation_parent_path.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.permission.label}</div>
-            <div class="content">{$form.permission.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.contact_id_field.label}</div>
-            <div class="content">{$form.contact_id_field.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.hide_id_field.label}</div>
-            <div class="content">{$form.hide_id_field.html}</div>
-            <div class="clear"></div>
-        </div>
-        <div class="crm-section">
-            <div class="label">{$form.help_text.label}</div>
-            <div class="content">{$form.help_text.html}</div>
-            <div class="clear"></div>
-        </div>
+    <div class="crm-section">
+        <div class="label">{$form.navigation_parent_path.label}</div>
+        <div class="content">{$form.navigation_parent_path.html}</div>
+        <div class="clear"></div>
     </div>
-
-    <div class="crm-submit-buttons">
-        {include file="CRM/common/formButtons.tpl" location="bottom"}
+    <div class="crm-section">
+        <div class="label">{$form.permission.label}</div>
+        <div class="content">{$form.permission.html}</div>
+        <div class="clear"></div>
+    </div>
+    <div class="crm-section">
+        <div class="label">{$form.contact_id_field.label}</div>
+        <div class="content">{$form.contact_id_field.html}</div>
+        <div class="clear"></div>
+    </div>
+    <div class="crm-section">
+        <div class="label">{$form.hide_id_field.label}</div>
+        <div class="content">{$form.hide_id_field.html}</div>
+        <div class="clear"></div>
+    </div>
+    <div class="crm-section">
+        <div class="label">{$form.help_text.label}</div>
+        <div class="content">{$form.help_text.html}</div>
+        <div class="clear"></div>
     </div>
 {/crmScope}
\ No newline at end of file
diff --git a/xml/Menu/dataprocessor.xml b/xml/Menu/dataprocessor.xml
index dad787ee..461929c2 100644
--- a/xml/Menu/dataprocessor.xml
+++ b/xml/Menu/dataprocessor.xml
@@ -77,27 +77,6 @@
     <access_arguments>access CiviCRM</access_arguments>
     <access_arguments>administer CiviCRM</access_arguments>
   </item>
-  <item>
-    <path>civicrm/dataprocessor/form/output/api</path>
-    <page_callback>CRM_Dataprocessor_Form_Output_API</page_callback>
-    <title>DataProcessor</title>
-    <access_arguments>access CiviCRM</access_arguments>
-    <access_arguments>administer CiviCRM</access_arguments>
-  </item>
-  <item>
-    <path>civicrm/dataprocessor/form/output/contact_search</path>
-    <page_callback>CRM_DataprocessorSearch_Form_OutputConfiguration_ContactSearch</page_callback>
-    <title>DataProcessor</title>
-    <access_arguments>access CiviCRM</access_arguments>
-    <access_arguments>administer CiviCRM</access_arguments>
-  </item>
-  <item>
-    <path>civicrm/dataprocessor/form/output/activity_search</path>
-    <page_callback>CRM_DataprocessorSearch_Form_OutputConfiguration_ActivitySearch</page_callback>
-    <title>DataProcessor</title>
-    <access_arguments>access CiviCRM</access_arguments>
-    <access_arguments>administer CiviCRM</access_arguments>
-  </item>
   <item>
     <path>civicrm/dataprocessor/form/output/download</path>
     <title>Browse Uploaded files</title>
diff --git a/xml/schema/CRM/Dataprocessor/DataProcessorOutput.entityType.php b/xml/schema/CRM/Dataprocessor/DataProcessorOutput.entityType.php
new file mode 100644
index 00000000..bd708746
--- /dev/null
+++ b/xml/schema/CRM/Dataprocessor/DataProcessorOutput.entityType.php
@@ -0,0 +1,11 @@
+<?php
+// This file declares a new entity type. For more details, see "hook_civicrm_entityTypes" at:
+// http://wiki.civicrm.org/confluence/display/CRMDOC/Hook+Reference
+return array (
+  0 => 
+  array (
+    'name' => 'DataProcessorOutput',
+    'class' => 'CRM_Dataprocessor_DAO_DataProcessorOutput',
+    'table' => 'civicrm_data_processor_output',
+  ),
+);
diff --git a/xml/schema/CRM/Dataprocessor/DataProcessorOutput.xml b/xml/schema/CRM/Dataprocessor/DataProcessorOutput.xml
new file mode 100644
index 00000000..38fd8815
--- /dev/null
+++ b/xml/schema/CRM/Dataprocessor/DataProcessorOutput.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="iso-8859-1" ?>
+
+<table>
+  <base>CRM/Dataprocessor</base>
+  <class>DataProcessorOutput</class>
+  <name>civicrm_data_processor_output</name>
+  <log>false</log>
+
+  <field>
+    <name>id</name>
+    <type>int unsigned</type>
+    <required>true</required>
+    <comment>Unique DataProcessorOutput ID</comment>
+  </field>
+  <primaryKey>
+    <name>id</name>
+    <autoincrement>true</autoincrement>
+  </primaryKey>
+  <field>
+    <name>data_processor_id</name>
+    <title>Data Processor ID</title>
+    <type>int unsigned</type>
+    <required>true</required>
+    <comment>FK to Data Processor</comment>
+  </field>
+  <field>
+    <name>type</name>
+    <title>Type</title>
+    <type>varchar</type>
+    <required>true</required>
+    <length>255</length>
+  </field>
+  <field>
+    <name>configuration</name>
+    <title>Configuration</title>
+    <type>text</type>
+    <required>false</required>
+    <length>255</length>
+    <serialize>JSON</serialize>
+  </field>
+
+  <field>
+    <name>permission</name>
+    <title>Permission</title>
+    <type>varchar</type>
+    <required>false</required>
+    <length>255</length>
+  </field>
+  <field>
+    <name>api_entity</name>
+    <title>API Entity</title>
+    <type>varchar</type>
+    <required>false</required>
+    <length>255</length>
+  </field>
+  <field>
+    <name>api_action</name>
+    <title>API Action</title>
+    <type>varchar</type>
+    <required>false</required>
+    <length>255</length>
+  </field>
+  <field>
+    <name>api_count_action</name>
+    <title>API Getcount action</title>
+    <type>varchar</type>
+    <required>false</required>
+    <length>255</length>
+  </field>
+
+  <foreignKey>
+    <name>data_processor_id</name>
+    <table>civicrm_data_processor</table>
+    <key>id</key>
+    <onDelete>CASCADE</onDelete>
+  </foreignKey>
+
+</table>
-- 
GitLab