From 242ad09867b3aa09aa34f5cf6f0fba506ef43207 Mon Sep 17 00:00:00 2001
From: Jaap Jansma <jaap.jansma@civicoop.org>
Date: Mon, 24 Sep 2018 10:08:38 +0200
Subject: [PATCH] fix minor things

---
 CRM/Dataprocessor/Form/Join/Simple.php        |  4 --
 Civi/DataProcessor/DataFlow/SqlDataFlow.php   | 60 ++++++++++++-------
 .../SqlDataFlow/SimpleWhereClause.php         |  6 +-
 Civi/DataProcessor/Factory.php                |  1 +
 Civi/DataProcessor/Output/Api.php             |  2 +-
 .../Source/AbstractCivicrmEntitySource.php    | 26 ++++----
 .../Source/GroupContactSource.php             | 35 +++++++++++
 7 files changed, 92 insertions(+), 42 deletions(-)
 create mode 100644 Civi/DataProcessor/Source/GroupContactSource.php

diff --git a/CRM/Dataprocessor/Form/Join/Simple.php b/CRM/Dataprocessor/Form/Join/Simple.php
index 7b646616..3a84e6d9 100644
--- a/CRM/Dataprocessor/Form/Join/Simple.php
+++ b/CRM/Dataprocessor/Form/Join/Simple.php
@@ -19,7 +19,6 @@ class CRM_Dataprocessor_Form_Join_Simple extends CRM_Core_Form {
    * @access public
    */
   function preProcess() {
-    $session = CRM_Core_Session::singleton();
     $this->dataProcessorId = CRM_Utils_Request::retrieve('data_processor_id', 'Integer');
     $this->assign('data_processor_id', $this->dataProcessorId);
 
@@ -31,9 +30,6 @@ class CRM_Dataprocessor_Form_Join_Simple extends CRM_Core_Form {
 
     $title = E::ts('Data Processor Source Join Conifuration');
     CRM_Utils_System::setTitle($title);
-
-    $url = CRM_Utils_System::url('civicrm/dataprocessor/form/edit', array('id' => $this->dataProcessorId, 'action' => 'update', 'reset' => 1));
-    $session->pushUserContext($url);
   }
 
   public function buildQuickForm() {
diff --git a/Civi/DataProcessor/DataFlow/SqlDataFlow.php b/Civi/DataProcessor/DataFlow/SqlDataFlow.php
index bdba010f..45f9c830 100644
--- a/Civi/DataProcessor/DataFlow/SqlDataFlow.php
+++ b/Civi/DataProcessor/DataFlow/SqlDataFlow.php
@@ -25,6 +25,8 @@ abstract class SqlDataFlow extends AbstractDataFlow {
 
   protected $sqlStatement;
 
+  protected $sqlCountStatement;
+
   /**
    * Returns an array with the fields for in the select statement in the sql query.
    *
@@ -58,29 +60,38 @@ abstract class SqlDataFlow extends AbstractDataFlow {
       return;
     }
 
-    $from = $this->getFromStatement();
-    $where = $this->getWhereStatement();
-    $groupBy = $this->getGroupByStatement();
-
-    $countSql = "SELECT COUNT(*) {$from} {$where} {$groupBy}";
-    $this->count = \CRM_Core_DAO::singleValueQuery($countSql);
-
-    $sql = "{$this->getSelectQueryStatement()} {$where} {$groupBy}";
-
-    // Build Limit and Offset.
-    $limitStatement = "";
-    if ($this->offset !== false && $this->limit !== false) {
-      $limitStatement = "LIMIT {$this->offset}, {$this->limit}";
-    } elseif ($this->offset === false && $this->limit !== false) {
-      $limitStatement = "LIMIT 0, {$this->limit}";
-    }
-    elseif ($this->offset !== false && $this->limit === false) {
-      $calculatedLimit = $this->count - $this->offset;
-      $limitStatement = "LIMIT {$this->offset}, {$calculatedLimit}";
+    try {
+      $from = $this->getFromStatement();
+      $where = $this->getWhereStatement();
+      $groupBy = $this->getGroupByStatement();
+
+      $countSql = "SELECT COUNT(*) {$from} {$where} {$groupBy}";
+      $this->sqlCountStatement = $countSql;
+      $this->count = \CRM_Core_DAO::singleValueQuery($countSql);
+
+      $sql = "{$this->getSelectQueryStatement()} {$where} {$groupBy}";
+
+      // Build Limit and Offset.
+      $limitStatement = "";
+      if ($this->offset !== FALSE && $this->limit !== FALSE) {
+        $limitStatement = "LIMIT {$this->offset}, {$this->limit}";
+      }
+      elseif ($this->offset === FALSE && $this->limit !== FALSE) {
+        $limitStatement = "LIMIT 0, {$this->limit}";
+      }
+      elseif ($this->offset !== FALSE && $this->limit === FALSE) {
+        $calculatedLimit = $this->count - $this->offset;
+        $limitStatement = "LIMIT {$this->offset}, {$calculatedLimit}";
+      }
+      $sql .= " {$limitStatement}";
+      $this->sqlStatement = $sql;
+      $this->dao = \CRM_Core_DAO::executeQuery($sql);
+    } catch (\Exception $e) {
+      throw new \Exception(
+        "Error in query. 
+        \r\nCount query: {$this->sqlCountStatement}
+        \r\nQuery: $this->sqlStatement", 0, $e);
     }
-    $sql .= " {$limitStatement}";
-    $this->sqlStatement = $sql;
-    $this->dao = \CRM_Core_DAO::executeQuery($sql);
   }
 
   /**
@@ -176,6 +187,11 @@ abstract class SqlDataFlow extends AbstractDataFlow {
    * @return \Civi\DataProcessor\DataFlow\SqlDataFlow
    */
   public function addWhereClause(WhereClauseInterface $clause) {
+    foreach($this->whereClauses as $c) {
+      if ($c->getWhereClause() == $clause->getWhereClause()) {
+        return $this; // Where clause is already added do not add it again.
+      }
+    }
     $this->whereClauses[] = $clause;
     return $this;
   }
diff --git a/Civi/DataProcessor/DataFlow/SqlDataFlow/SimpleWhereClause.php b/Civi/DataProcessor/DataFlow/SqlDataFlow/SimpleWhereClause.php
index 0e1bd02f..9b82a4a3 100644
--- a/Civi/DataProcessor/DataFlow/SqlDataFlow/SimpleWhereClause.php
+++ b/Civi/DataProcessor/DataFlow/SqlDataFlow/SimpleWhereClause.php
@@ -21,7 +21,11 @@ class SimpleWhereClause implements WhereClauseInterface {
     $this->field = $field;
     $this->operator = $operator;
     if (is_array($value)) {
-      $this->value = "(".implode(", ",\CRM_Utils_Type::escapeAll($value, $valueType)).")";
+      $esacpedValues = array();
+      foreach($value as $val) {
+        $esacpedValues[] = "'". \CRM_Utils_Type::escape($val, $valueType)."'";
+      }
+      $this->value = "(".implode(", ",$esacpedValues).")";
     } else {
       $this->value = \CRM_Utils_Type::escape($value, $valueType);
     }
diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php
index df910c0e..68d0f1a6 100644
--- a/Civi/DataProcessor/Factory.php
+++ b/Civi/DataProcessor/Factory.php
@@ -77,6 +77,7 @@ class Factory {
     $this->addDataProcessorType('default', 'Civi\DataProcessor\ProcessorType\DefaultProcessorType', E::ts('Default'));
     $this->addDataSource('contact', 'Civi\DataProcessor\Source\ContactSource', E::ts('Contact'));
     $this->addDataSource('group', 'Civi\DataProcessor\Source\GroupSource', E::ts('Group'));
+    $this->addDataSource('group_contact', 'Civi\DataProcessor\Source\GroupContactSource', E::ts('Contacts in a group'));
     $this->addDataSource('email', 'Civi\DataProcessor\Source\EmailSource', E::ts('E-mail'));
     $this->addDataSource('contribution', 'Civi\DataProcessor\Source\ContributionSource', E::ts('Contribution'));
     $this->addDataSource('relationship', 'Civi\DataProcessor\Source\RelationshipSource', E::ts('Relationship'));
diff --git a/Civi/DataProcessor/Output/Api.php b/Civi/DataProcessor/Output/Api.php
index f4af4a40..3c4ffc35 100644
--- a/Civi/DataProcessor/Output/Api.php
+++ b/Civi/DataProcessor/Output/Api.php
@@ -159,7 +159,7 @@ class Api implements OutputInterface, API_ProviderInterface, EventSubscriberInte
 
     if ($isCountAction) {
       $count = $dataProcessor->getDataFlow()->recordCount();
-      return array('count' => $count, 'is_error' => 0);
+      return array('result' => $count, 'is_error' => 0);
     } else {
       $options = _civicrm_api3_get_options_from_params($apiRequest['params']);
 
diff --git a/Civi/DataProcessor/Source/AbstractCivicrmEntitySource.php b/Civi/DataProcessor/Source/AbstractCivicrmEntitySource.php
index 4d24e939..4fa396d9 100644
--- a/Civi/DataProcessor/Source/AbstractCivicrmEntitySource.php
+++ b/Civi/DataProcessor/Source/AbstractCivicrmEntitySource.php
@@ -122,23 +122,21 @@ abstract class AbstractCivicrmEntitySource implements SourceInterface {
     if (!$this->primaryDataFlow) {
       $this->primaryDataFlow = new SqlTableDataFlow($this->getTable(), $this->getSourceName());
     }
-    if (!$this->dataFlow) {
-      $this->addFilters($this->configuration);
-
-      if (count($this->customGroupDataFlowDescriptions) || count($this->additionalDataFlowDescriptions)) {
-        $this->dataFlow = new CombinedSqlDataFlow('', $this->primaryDataFlow->getTable(), $this->primaryDataFlow->getTableAlias());
-        $this->dataFlow->addSourceDataFlow(new DataFlowDescription($this->primaryDataFlow));
-        foreach ($this->customGroupDataFlowDescriptions as $customGroupDataFlowDescription) {
-          $this->dataFlow->addSourceDataFlow($customGroupDataFlowDescription);
-        }
-        foreach ($this->additionalDataFlowDescriptions as $additionalDataFlowDescription) {
-          $this->dataFlow->addSourceDataFlow($additionalDataFlowDescription);
-        }
+    $this->addFilters($this->configuration);
+
+    if (count($this->customGroupDataFlowDescriptions) || count($this->additionalDataFlowDescriptions)) {
+      $this->dataFlow = new CombinedSqlDataFlow('', $this->primaryDataFlow->getTable(), $this->primaryDataFlow->getTableAlias());
+      $this->dataFlow->addSourceDataFlow(new DataFlowDescription($this->primaryDataFlow));
+      foreach ($this->customGroupDataFlowDescriptions as $customGroupDataFlowDescription) {
+        $this->dataFlow->addSourceDataFlow($customGroupDataFlowDescription);
       }
-      else {
-        $this->dataFlow = $this->primaryDataFlow;
+      foreach ($this->additionalDataFlowDescriptions as $additionalDataFlowDescription) {
+        $this->dataFlow->addSourceDataFlow($additionalDataFlowDescription);
       }
     }
+    else {
+      $this->dataFlow = clone $this->primaryDataFlow;
+    }
   }
 
   protected function reset() {
diff --git a/Civi/DataProcessor/Source/GroupContactSource.php b/Civi/DataProcessor/Source/GroupContactSource.php
new file mode 100644
index 00000000..5763b701
--- /dev/null
+++ b/Civi/DataProcessor/Source/GroupContactSource.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Jaap Jansma <jaap.jansma@civicoop.org>
+ * @license AGPL-3.0
+ */
+
+namespace Civi\DataProcessor\Source;
+
+use Civi\DataProcessor\DataFlow\SqlTableDataFlow;
+use Civi\DataProcessor\DataSpecification\DataSpecification;
+use Civi\DataProcessor\DataSpecification\FieldSpecification;
+
+use CRM_Dataprocessor_ExtensionUtil as E;
+
+class GroupContactSource extends AbstractCivicrmEntitySource {
+
+  /**
+   * Returns the entity name
+   *
+   * @return String
+   */
+  protected function getEntity() {
+    return 'GroupContact';
+  }
+
+  /**
+   * Returns the table name of this entity
+   *
+   * @return String
+   */
+  protected function getTable() {
+    return 'civicrm_group_contact';
+  }
+
+}
\ No newline at end of file
-- 
GitLab