diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d81da2eeff7a188dad1a3829ee770a988c70de9..369555f5458b664c8203bb07cdc5fd9419094761 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Version 1.4.0 (not yet released) -* Search tasks (eg. Export) work with Member,Contribute,Participant,Case... +* Search tasks (eg. Export) work with Member,Contribute,Participant,Case... +* Added source to retrieve the owner membership, when owner membership is not set (meaning it is already the primary) then it will return itself. # Version 1.3.0 diff --git a/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php b/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php index bd23d1e4bfd04019480937c6dbfdee7287c6bb3a..703fce83ff2cac2cc0987ea88eed860967ca3847 100644 --- a/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php +++ b/Civi/DataProcessor/DataFlow/MultipleDataFlows/SimpleNonRequiredJoin.php @@ -59,8 +59,8 @@ class SimpleNonRequiredJoin extends SimpleJoin { */ public function getJoinClause(DataFlowDescription $sourceDataFlowDescription) { $this->initialize(); - $joinClause = ""; - if ($sourceDataFlowDescription->getJoinSpecification()) { + $joinClause = "ON 1"; + if ($this->left_table && $this->right_table && $sourceDataFlowDescription->getJoinSpecification()) { $leftColumnName = "`{$this->left_table}`.`{$this->left_field}`"; if ($this->leftFieldSpec) { $leftColumnName = $this->leftFieldSpec->getSqlColumnName($this->left_table); diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php index 12674738b2ddf70e6ed7fc640960c7f230e43c13..abbfe7716c974af7677bc45b2b0073f2251e1219 100644 --- a/Civi/DataProcessor/Factory.php +++ b/Civi/DataProcessor/Factory.php @@ -117,6 +117,7 @@ class Factory { $this->addDataSource('mailing_job', new Definition('Civi\DataProcessor\Source\Mailing\MailingJobSource'), E::ts('Mailing Job')); $this->addDataSource('mailing_group', new Definition('Civi\DataProcessor\Source\Mailing\MailingGroupSource'), E::ts('Mailing Group')); $this->addDataSource('membership', new Definition('Civi\DataProcessor\Source\Member\MembershipSource'), E::ts('Membership')); + $this->addDataSource('primary_membership', new Definition('Civi\DataProcessor\Source\Member\PrimaryMembershipSource'), E::ts('Primary Membership (retrieve the owner membership id')); $this->addDataSource('membership_type', new Definition('Civi\DataProcessor\Source\Member\MembershipTypeSource'), E::ts('Membership Type')); $this->addDataSource('membership_status', new Definition('Civi\DataProcessor\Source\Member\MembershipStatusSource'), E::ts('Membership Status')); $this->addDataSource('csv', new Definition('Civi\DataProcessor\Source\CSV'), E::ts('CSV File')); diff --git a/Civi/DataProcessor/Source/Member/PrimaryMembershipSource.php b/Civi/DataProcessor/Source/Member/PrimaryMembershipSource.php new file mode 100644 index 0000000000000000000000000000000000000000..3362fd86ff90064ad2b94aefadb46d7d4a1cac71 --- /dev/null +++ b/Civi/DataProcessor/Source/Member/PrimaryMembershipSource.php @@ -0,0 +1,167 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +namespace Civi\DataProcessor\Source\Member; + +use Civi\DataProcessor\DataFlow\CombinedDataFlow\SubqueryDataFlow; +use Civi\DataProcessor\DataFlow\MultipleDataFlows\DataFlowDescription; +use Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleJoin; +use Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleNonRequiredJoin; +use Civi\DataProcessor\DataFlow\SqlDataFlow\AndClause; +use Civi\DataProcessor\DataFlow\SqlDataFlow\OrClause; +use Civi\DataProcessor\DataFlow\SqlDataFlow\PureSqlStatementClause; +use Civi\DataProcessor\DataFlow\SqlDataFlow\SimpleWhereClause; +use Civi\DataProcessor\DataFlow\SqlTableDataFlow; +use Civi\DataProcessor\DataSpecification\DataSpecification; +use Civi\DataProcessor\DataSpecification\FieldExistsException; +use Civi\DataProcessor\DataSpecification\FieldSpecification; +use Civi\DataProcessor\Source\AbstractSource; + +use CRM_Dataprocessor_ExtensionUtil as E; + +class PrimaryMembershipSource extends AbstractSource { + + /** + * @var \Civi\DataProcessor\DataSpecification\DataSpecification + */ + protected $availableFields; + + /** + * @var \Civi\DataProcessor\DataSpecification\DataSpecification + */ + protected $availableFilterFields; + + /** + * @var SqlTableDataFlow + */ + protected $primary_membership_data_flow; + + /** + * @var SqlTableDataFlow + */ + protected $membership_data_flow; + + /** + * Initialize the join + * + * @return void + */ + public function initialize() { + if (!$this->dataFlow) { + $this->primary_membership_data_flow = new SqlTableDataFlow('civicrm_membership', $this->getSourceName().'_primary_membership'); + $this->membership_data_flow = new SqlTableDataFlow('civicrm_membership', $this->getSourceName().'_membership'); + + $joinClause = new OrClause(); + $joinClause1 = new AndClause(); + $joinClause1->addWhereClause(new SimpleWhereClause($this->membership_data_flow->getTableAlias(), 'owner_membership_id', 'IS NOT NULL', null, 'String', TRUE)); + $joinClause1->addWhereClause(new PureSqlStatementClause("`{$this->primary_membership_data_flow->getTableAlias()}`.`id` = `{$this->membership_data_flow->getTableAlias()}`.`owner_membership_id`")); + $joinClause->addWhereClause($joinClause1); + + $joinClause2 = new AndClause(); + $joinClause2->addWhereClause(new SimpleWhereClause($this->membership_data_flow->getTableAlias(), 'owner_membership_id', 'IS NULL', null, 'String', TRUE)); + $joinClause2->addWhereClause(new PureSqlStatementClause("`{$this->primary_membership_data_flow->getTableAlias()}`.`id` = `{$this->membership_data_flow->getTableAlias()}`.`id`")); + $joinClause->addWhereClause($joinClause2); + + $join = new SimpleNonRequiredJoin(null, null, null, null, 'INNER'); + $join->addFilterClause($joinClause); + + $this->dataFlow = new SubqueryDataFlow($this->getSourceName(), 'civicrm_membership', $this->getSourceName()); + $primaryMembershipDataFlowDescription = new DataFlowDescription($this->primary_membership_data_flow); + $this->dataFlow->addSourceDataFlow($primaryMembershipDataFlowDescription); + $memberShipDataFlowDescription = new DataFlowDescription($this->membership_data_flow, $join); + $this->dataFlow->addSourceDataFlow($memberShipDataFlowDescription); + + try { + $this->primary_membership_data_flow->getDataSpecification() + ->addFieldSpecification('id', new FieldSpecification('id','Integer', E::ts('Primary Membership ID'), null, 'primary_membership_id')) + ->addFieldSpecification('contact_id', new FieldSpecification('contact_id','Integer', E::ts('Primary Membership Contact ID'), null, 'primary_membership_contact_id')); + + $this->membership_data_flow->getDataSpecification() + ->addFieldSpecification('id', new FieldSpecification('id','Integer', E::ts('Membership ID'), null, 'membership_id')) + ->addFieldSpecification('contact_id', new FieldSpecification('contact_id','Integer', E::ts('Membership Contact ID'), null, 'membership_contact_id')); + + /*$this->dataFlow->getDataSpecification() + ->addFieldSpecification('primary_membership_id', $this->getAvailableFields() + ->getFieldSpecificationByName('primary_membership_id')) + ->addFieldSpecification('primary_membership_contact_id', $this->getAvailableFields() + ->getFieldSpecificationByName('primary_membership_contact_id')) + ->addFieldSpecification('membership_id', $this->getAvailableFields() + ->getFieldSpecificationByName('membership_id')) + ->addFieldSpecification('membership_contact_id', $this->getAvailableFields() + ->getFieldSpecificationByName('membership_contact_id'));*/ + } catch (\Exception $e) { + // Do nothing + } + + } + } + + /** + * @return \Civi\DataProcessor\DataSpecification\DataSpecification + * @throws \Exception + */ + public function getAvailableFields() { + if (!$this->availableFields) { + $this->availableFields = new DataSpecification(); + $this->loadFields($this->availableFields); + } + return $this->availableFields; + } + + /** + * @return \Civi\DataProcessor\DataSpecification\DataSpecification + * @throws \Exception + */ + public function getAvailableFilterFields() { + if (!$this->availableFilterFields) { + $this->availableFilterFields = new DataSpecification(); + $this->loadFields($this->availableFilterFields); + } + return $this->availableFilterFields; + } + + /** + * Add custom fields to the available fields section + * + * @param DataSpecification $dataSpecification + * @throws \Civi\DataProcessor\DataSpecification\FieldExistsException + * @throws \Exception + */ + protected function loadFields(DataSpecification $dataSpecification) { + $dataSpecification->addFieldSpecification('primary_membership_id', new FieldSpecification('primary_membership_id','Integer', E::ts('Primary Membership ID'), null, $this->getSourceName().'_primary_membership_id')); + $dataSpecification->addFieldSpecification('membership_id', new FieldSpecification('membership_id','Integer', E::ts('Membership ID'), null, $this->getSourceName().'_membership_id')); + $dataSpecification->addFieldSpecification('primary_membership_contact_id', new FieldSpecification('primary_membership_contact_id','Integer', E::ts('Primary Membership Contact ID'), null, $this->getSourceName().'_primary_membership_contact_id')); + $dataSpecification->addFieldSpecification('membership_contact_id', new FieldSpecification('membership_contact_id','Integer', E::ts('Membership Contact ID'), null, $this->getSourceName().'_membership_contact_id')); + } + + /** + * Ensures a field is in the data source + * + * @param \Civi\DataProcessor\DataSpecification\FieldSpecification $fieldSpecification + * @return \Civi\DataProcessor\Source\SourceInterface + * @throws \Exception + */ + public function ensureFieldInSource(FieldSpecification $fieldSpecification) { + try { + $this->dataFlow->getDataSpecification()->addFieldSpecification($fieldSpecification->alias, $fieldSpecification); + } catch (FieldExistsException $e) { + // Do nothing. + } + return $this; + } + + /** + * Ensure that filter field is accesible in the query + * + * @param FieldSpecification $field + * @return \Civi\DataProcessor\DataFlow\AbstractDataFlow|null + * @throws \Exception + */ + public function ensureField(FieldSpecification $field) { + return $this->dataFlow; + } + +}