From 2409bd5df17736e98a7faaaa7bfaf75568562dd4 Mon Sep 17 00:00:00 2001
From: Josh Pollock <josh@calderawp.com>
Date: Thu, 5 Apr 2018 20:31:55 -0400
Subject: [PATCH] impliment select by field value feature

---
 .../Features/FeatureHelperMethodsTest.php     | 80 +++++++++++++++++++
 .../Features/QueryByUserIdTest.php            | 44 ----------
 Tests/Integration/IntegrationTestCase.php     |  9 ++-
 Tests/Integration/Select/EntryTest.php        | 43 +++++++++-
 src/Features/FeatureContainer.php             | 35 ++++++++
 src/Select/Entry.php                          | 16 ++++
 src/Select/EntryValues.php                    |  8 +-
 7 files changed, 185 insertions(+), 50 deletions(-)
 create mode 100644 Tests/Integration/Features/FeatureHelperMethodsTest.php
 delete mode 100644 Tests/Integration/Features/QueryByUserIdTest.php

diff --git a/Tests/Integration/Features/FeatureHelperMethodsTest.php b/Tests/Integration/Features/FeatureHelperMethodsTest.php
new file mode 100644
index 0000000..fbfccd8
--- /dev/null
+++ b/Tests/Integration/Features/FeatureHelperMethodsTest.php
@@ -0,0 +1,80 @@
+<?php
+namespace calderawp\CalderaFormsQuery\Tests\Integration\Features;
+
+
+use calderawp\CalderaFormsQuery\CreatesSelectQueries;
+use calderawp\CalderaFormsQuery\Features\FeatureContainer;
+use calderawp\CalderaFormsQuery\Tests\Integration\IntegrationTestCase;
+use calderawp\CalderaFormsQuery\Tests\Traits\CanCreateEntryWithEmailField;
+
+class FeatureHelperMethodsTest extends IntegrationTestCase
+{
+
+	use CanCreateEntryWithEmailField;
+
+	/**
+	 *
+	 * @covers FeatureContainer::selectByUserId()
+	 * @covers FeatureContainer::collectResults()
+	 * @covers FeatureContainer::collectEntryValues()
+	 */
+	public function testByUserId()
+	{
+		$container = $this->containerFactory();
+
+		//Create an entry for a known user.
+		$email = 'nom@noms.noms';
+		$userId = $this->factory()->user->create(
+			[ 'user_email' => $email ]
+		);
+		wp_set_current_user( $userId );
+		$entryId = $this->createEntryWithEmail( $email );
+
+		$results = $container->selectByUserId( $userId );
+		$this->assertEquals( $entryId, $results[0]['entry']->id);
+		$this->assertEquals( $entryId, $results[0]['entry']->id);
+
+		$found = false;
+		foreach ( $results[0]['values'] as $entryValue )
+		{
+			if( $entryValue->slug === $this->getEmailFieldSlug() ){
+				$this->assertSame( $email, $entryValue->value );
+				$found = true;
+			}
+		}
+
+		$this->assertTrue( $found );
+
+
+	}
+
+	/**
+	 * Test selecting by a field value such as an email
+	 *
+	 * @covers FeatureContainer::selectByFieldValue()
+	 */
+	public function testByFieldValue()
+	{
+		$container = $this->containerFactory();
+		//Create one entry for unknown user
+		$this->createEntryWithEmail( rand(). 'email.com' );
+
+		//Create two entries for a known user.
+		$email = 'nom@noms.noms';
+		$userId = $this->factory()->user->create(
+			[ 'user_email' => $email ]
+		);
+		wp_set_current_user( $userId );
+		$this->createEntryWithEmail( $email );
+		$this->createEntryWithEmail( $email );
+
+		$results = $container->selectByFieldValue(
+			$this->getEmailFieldSlug(),
+			$email
+		);
+		$this->assertSame(2, count($results));
+		$this->assertSame( $email,$results[0]['values'][1]->value );
+		$this->assertSame( $email,$results[1]['values'][1]->value );
+
+	}
+}
\ No newline at end of file
diff --git a/Tests/Integration/Features/QueryByUserIdTest.php b/Tests/Integration/Features/QueryByUserIdTest.php
deleted file mode 100644
index 897712c..0000000
--- a/Tests/Integration/Features/QueryByUserIdTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-namespace calderawp\CalderaFormsQuery\Tests\Integration\Features;
-
-
-use calderawp\CalderaFormsQuery\CreatesSelectQueries;
-use calderawp\CalderaFormsQuery\Tests\Integration\IntegrationTestCase;
-use calderawp\CalderaFormsQuery\Tests\Traits\CanCreateEntryWithEmailField;
-
-class QueryByUserIdTest extends IntegrationTestCase
-{
-
-	use CanCreateEntryWithEmailField;
-
-
-	public function testByUserId()
-	{
-		$container = $this->containerFactory();
-
-		//Create an entry for a known user.
-		$email = 'nom@noms.noms';
-		$userId = $this->factory()->user->create(
-			[ 'user_email' => $email ]
-		);
-		wp_set_current_user( $userId );
-		$entryId = $this->createEntryWithEmail( $email );
-
-		$results = $container->selectByUserId( $userId );
-		$this->assertEquals( $entryId, $results[0]['entry']->id);
-		$this->assertEquals( $entryId, $results[0]['entry']->id);
-
-		$found = false;
-		foreach ( $results[0]['values'] as $entryValue )
-		{
-			if( $entryValue->slug === $this->getEmailFieldSlug() ){
-				$this->assertSame( $email, $entryValue->value );
-				$found = true;
-			}
-		}
-
-		$this->assertTrue( $found );
-
-
-	}
-}
\ No newline at end of file
diff --git a/Tests/Integration/IntegrationTestCase.php b/Tests/Integration/IntegrationTestCase.php
index 0a6d0ed..9953b20 100755
--- a/Tests/Integration/IntegrationTestCase.php
+++ b/Tests/Integration/IntegrationTestCase.php
@@ -98,7 +98,14 @@ abstract class IntegrationTestCase extends \WP_UnitTestCase
 		return $this->create_entry( $this->mock_form );
 	}
 
-
+	/**
+	 * @return int
+	 */
+	protected function createEntryWithMockFormAndGetEntryId()
+	{
+		$details = $this->create_entry( $this->mock_form );
+		return $details[ 'id' ];
+	}
 
 
 
diff --git a/Tests/Integration/Select/EntryTest.php b/Tests/Integration/Select/EntryTest.php
index a316556..6a4b886 100644
--- a/Tests/Integration/Select/EntryTest.php
+++ b/Tests/Integration/Select/EntryTest.php
@@ -57,7 +57,7 @@ class EntryTest extends IntegrationTestCase
 	 */
 	public function testQueryByEntryId()
 	{
-		$entry = $this->createEntryWithMockForm();
+		$entryId = $this->createEntryWithMockFormAndGetEntryId();
 		$entryGenerator = $this->entryGeneratorFactory();
 		//No results for a non-existent entry
 		$entryGenerator->queryByEntryId(42);
@@ -66,24 +66,57 @@ class EntryTest extends IntegrationTestCase
 
 		//One entry: one result with the correct ID
 		$entryGenerator = $this->entryGeneratorFactory();
-		$entryGenerator->queryByEntryId($entry['id']);
+		$entryGenerator->queryByEntryId($entryId);
 		$sql = $entryGenerator->getPreparedSql();
 		$results =  $this->queryWithWPDB($sql);
 		$this->assertTrue( ! empty( $results ));
 		$this->assertSame( 1, count( $results ) );
-		$this->assertEquals( $results[0]->id, $entry['id']);
+		$this->assertEquals( $results[0]->id, $entryId);
 
 		//Two more entries: one result for original entry ID
 		$this->createEntryWithMockForm();
 		$this->createEntryWithMockForm();
 		$entryGenerator = $this->entryGeneratorFactory();
-		$entryGenerator->queryByEntryId($entry['id']);
+		$entryGenerator->queryByEntryId($entryId);
 		$sql = $entryGenerator->getPreparedSql();
 		$results =  $this->queryWithWPDB($sql);
 		$this->assertTrue( ! empty( $results ));
 		$this->assertSame( 1, count( $results ) );
 	}
 
+	/**
+	 * Test querying by IDs
+	 *
+	 * @covers Entry::queryByEntryIds()
+	 */
+	public function testByEntryIds()
+	{
+		$entryIdOne = $this->createEntryWithMockFormAndGetEntryId();
+		$entryIdTwo = $this->createEntryWithMockFormAndGetEntryId();
+		$entryIdThree = $this->createEntryWithMockFormAndGetEntryId();
+
+		//Two results when asking for IN One and Three
+		$entryGenerator = $this->entryGeneratorFactory();
+		$sql = $entryGenerator->queryByEntryIds( [
+				$entryIdOne,
+				$entryIdThree
+			])
+			->getPreparedSql();
+		$results = $this->queryWithWPDB( $sql );
+		$this->assertSame( 2, count( $results ) );
+
+		//One results when asking for IN Two
+		$entryGenerator = $this->entryGeneratorFactory();
+		$sql = $entryGenerator->queryByEntryIds( [
+			$entryIdTwo
+		])
+			->getPreparedSql();
+		$results = $this->queryWithWPDB( $sql );
+		$this->assertSame( 1, count( $results ) );
+
+
+	}
+
 	/**
 	 * Test query by user ID
 	 *
@@ -140,4 +173,6 @@ class EntryTest extends IntegrationTestCase
 
 
 
+
+
 }
\ No newline at end of file
diff --git a/src/Features/FeatureContainer.php b/src/Features/FeatureContainer.php
index c3ae76e..1c37459 100644
--- a/src/Features/FeatureContainer.php
+++ b/src/Features/FeatureContainer.php
@@ -134,6 +134,41 @@ class FeatureContainer extends Container
 		return $this->collectResults( $this->select( $query ) );
 	}
 
+	/**
+	 * Find all entries that have or do not have field with a slug and value
+	 *
+	 * @param string $fieldSlug Field slug
+	 * @param string $fieldValue Field value
+	 * @param bool $have Optional. Default: true. If true query is for fields with this value
+	 *
+	 * @return array
+	 */
+	public function selectByFieldValue($fieldSlug, $fieldValue, $have = true )
+	{
+
+		$type = $have ? 'equals' : 'notEquals';
+		$queryForEntryValues = $this
+			->getQueries()
+			->entryValuesSelect()
+			->queryByFieldValue($fieldSlug, $fieldValue, $type, 'AND', [
+				'entry_id'
+			] );
+		$results = $this->select( $queryForEntryValues );
+		if( empty( $results ) || 0 >= count( $results )){
+			return [];
+		}
+		foreach ( $results as &$result ){
+			$result = $result->entry_id;
+		}
+
+		$queryForValues = $this
+			->getQueries()
+			->entrySelect()
+			->queryByEntryIds($results);
+
+		return $this->collectResults( $this->select( $queryForValues ) );
+	}
+
 	/**
 	 * @return string
 	 */
diff --git a/src/Select/Entry.php b/src/Select/Entry.php
index 1a930b3..7aa2824 100644
--- a/src/Select/Entry.php
+++ b/src/Select/Entry.php
@@ -33,6 +33,22 @@ class Entry extends SelectQueryBuilder
 		return $this->is('id', $entryId);
 	}
 
+	/**
+	 * Query by entry ids
+	 *
+	 * @param array $entryIds An array of IDs to query by
+	 *
+	 * @return $this
+	 */
+	public function queryByEntryIds(array $entryIds)
+	{
+		$this
+			->getSelectQuery()
+			->where()
+			->in( 'id', $entryIds );
+		return $this;
+	}
+
 	/**
 	 * Get all entries for a specific user
 	 *
diff --git a/src/Select/EntryValues.php b/src/Select/EntryValues.php
index a2f1860..a4fa43a 100644
--- a/src/Select/EntryValues.php
+++ b/src/Select/EntryValues.php
@@ -30,10 +30,16 @@ class EntryValues extends SelectQueryBuilder
 	 * @param string $fieldValue Field value
 	 * @param string $type Optional. Type of comparison. Values: equals|notEquals|like Default: 'equals'
 	 * @param string $whereOperator Optional. Type of where. Default is 'AND'. Any valid WHERE operator is accepted
+	 * @param array $columns Optional. Array of columns to select. Leave empty to select *
 	 * @return $this
 	 */
-	public function queryByFieldValue($fieldSlug, $fieldValue, $type = 'equals', $whereOperator = 'AND')
+	public function queryByFieldValue($fieldSlug, $fieldValue, $type = 'equals', $whereOperator = 'AND', $columns = [])
 	{
+		if( ! empty( $columns ) ){
+			$this
+				->getSelectQuery()
+				->setColumns( $columns );
+		}
 		switch ($type) {
 			case 'equals':
 				$this
-- 
GitLab