Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatting date field to match the data dictionary (DD) import value #3869

Merged
merged 120 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
7854925
Formatting date field to match the data dictionary value being imported
Nov 9, 2022
1ee3cea
adidng a condition for when DD isn't active
Nov 10, 2022
78a80b9
fixing code climate errors
Nov 14, 2022
27b2567
fixing code climate errors p2
Nov 14, 2022
8a086e1
fixing code climate errors p3
Nov 14, 2022
bd02972
fixing code climate errors p4
Nov 14, 2022
dd10f4b
fixing code climate errors p5
Nov 14, 2022
6e18a2e
fixing code climate errors p6
Nov 14, 2022
d6d6886
fixing code climate errors p7
Nov 14, 2022
5942488
fixing code climate errors p8
Nov 14, 2022
44cc2e1
fixing code climate errors p9
Nov 14, 2022
03ea121
Fixing CircleCI error
Nov 14, 2022
85e41ee
reset QueryDownloadController.php
Nov 14, 2022
184257f
adding back changes to QueryDownloadController.php
Nov 14, 2022
eb8c4ce
updating circleci config to get around ddev error
Nov 15, 2022
66aaadc
updating circleci config to get around ddev error
Nov 15, 2022
7eda3a5
resetting QueryDownloadController.php to match 2.x
Nov 15, 2022
2d242e6
adding back changes to QueryDownloadController.php
Nov 15, 2022
660c7d8
moving the result varialbe to see if that makes a difference
Nov 15, 2022
044debc
resource_id varialbe wasn't being set
Nov 15, 2022
f0c75bb
seeing if updating the services included resolves the issue
Nov 15, 2022
828e03d
resetting Controller/QueryDownloadControllerTest.php
Nov 15, 2022
6485202
fixing error from update
Nov 15, 2022
4b1d369
adding date formating to AbstractDatabaseTable.php
Dec 12, 2022
c057cdc
Fixing code climate errors
Dec 12, 2022
80a9b4f
Fixing more code climate errors
Dec 12, 2022
517af21
Fixing more code climate errors p3
Dec 12, 2022
3d38699
Moving date formatting back to the select factory
Dec 20, 2022
95e6a7a
hold filefetcher to 4.1.0
janette Dec 30, 2022
8bdce6e
Work done:
Jan 11, 2023
8f8719b
Fixing code climate issues
Jan 11, 2023
e464790
Fixing code climate issues p2
Jan 11, 2023
62e84ff
Fixing code climate issues p3
Jan 11, 2023
3507a34
trying to fix failing phpunit tests
Jan 11, 2023
0423624
more phpunit test fix
Jan 11, 2023
996b80f
more phpunit test fix pt2
Jan 11, 2023
16628ad
Updating unit test to add datastore service
Jan 23, 2023
e9a5fa7
setting getDataDictionaryFields in mock chain
Jan 25, 2023
4e9bd4b
moving the getDataDictionaryFields mock
Jan 25, 2023
37fc185
changing the getDataDictionaryFields mock to Query
Jan 25, 2023
cc8b385
adding DictionaryEnforcer to mock list
Jan 25, 2023
69d9519
fixing static class error
Jan 25, 2023
684fb98
found service call error
Jan 25, 2023
dd01d94
fixing getDataDictionaryFields missing error
Jan 25, 2023
9ebec8e
Adding getDatastoreService function to be called in the test
Jan 25, 2023
a73a438
more mock work
Jan 25, 2023
0263cce
adding pack getDataDictionaryFields
Jan 25, 2023
1bec987
adding back dictionary_enforcer
Jan 25, 2023
78c2553
fixing error in DatastoreQueryTest
Jan 25, 2023
6dbde5b
updating ServiceTest.php
Jan 25, 2023
b4fd2a5
adding additional tests for DictionaryEnforcerTest
Jan 25, 2023
0c41f97
updating test
Jan 25, 2023
94cdc4b
updating test
Jan 25, 2023
a77c3f5
updating test again
Jan 25, 2023
0499e3e
updating test again
Jan 25, 2023
e6d1756
fixing syntax error
Jan 25, 2023
e6ab227
fixing syntax error
Jan 25, 2023
0a99acc
changing function being called in mock
Jan 25, 2023
c9528b6
fixing variable
Jan 25, 2023
098b664
removing var_dump
Jan 25, 2023
1f0c0cf
making more changes to the test
Jan 25, 2023
e35cb25
updating new tests
Feb 1, 2023
0fa38c7
fixing syntax error
Feb 1, 2023
06463f8
fixing syntax error p2
Feb 1, 2023
26a2b6b
fixing syntax error p3
Feb 1, 2023
f4fc1a3
I was returning the wrong type of variable
Feb 1, 2023
f09f1e8
removing resrouce_id from DD lookup
Feb 1, 2023
b1bd237
creating test for getDataDictionaryFields
Feb 1, 2023
f5f79bb
fining coding climate errors
Feb 1, 2023
938079d
fixing code climate issue
Feb 1, 2023
ecea581
fixing testing error
Feb 1, 2023
2407e25
fixing testing error
Feb 1, 2023
4890595
Adding a new test called testGetDatastoreService
Feb 3, 2023
ba7c66c
making additional changes to testGetDatastoreService
Feb 3, 2023
7bcbc20
making changes to testGetDatastoreService
Feb 3, 2023
3070910
making changes to testGetDatastoreService
Feb 3, 2023
d80afd0
making changes to testGetDatastoreService p3
Feb 3, 2023
ebdc24c
adding the rest of the missing functions
Feb 6, 2023
40cbf67
adding another missing function
Feb 6, 2023
d3885fa
adding missing Yaml declaration
Feb 6, 2023
adcc319
fixing coding error
Feb 6, 2023
eb8b405
making changes to the test
Feb 6, 2023
f7dc29a
resetting the QueryControllerTest.php file
Feb 6, 2023
dcd71b5
reseting QueryControllerTest.php to branch 2.x
Feb 6, 2023
147fef2
Merge branch '2.x' into WCMS-12139
Feb 6, 2023
be69229
fixing service test
Feb 6, 2023
9b92227
removing get datastore service function
Feb 6, 2023
a5ffecf
changing QueryDownloadControllerTest
Feb 6, 2023
8eb5c2a
changing QueryDownloadControllerTest again
Feb 6, 2023
738ce18
changing QueryDownloadControllerTest again
Feb 6, 2023
f76e5de
fixing typo
Feb 6, 2023
1c928bb
fixing QueryDownloadControllerTest
Feb 6, 2023
43e1d87
fixing QueryDownloadControllerTest
Feb 6, 2023
906df3c
fixing QueryDownloadControllerTest
Feb 6, 2023
33eaddb
fixing QueryDownloadControllerTest
Feb 6, 2023
62a0ab1
fixing QueryDownloadControllerTest
Feb 6, 2023
62212b5
adding back getDatastoreService
Feb 6, 2023
edd4f90
making getDatastoreService private
Feb 6, 2023
44fa554
removing getDatastoreService from test
Feb 6, 2023
463d2ce
fixing test error
Feb 6, 2023
a3d9a19
returning the code back to non private function
Feb 7, 2023
2c03b18
Merge branch '2.x' into WCMS-12139
Feb 7, 2023
002234d
updating QueryDownloadControllerTest
Feb 28, 2023
7da506e
Forgot to add updated csv files
Feb 28, 2023
0c24320
resetting test data
Mar 1, 2023
7a47a12
resestting the QueryDownloadControllerTest file and updating the Sele…
Mar 1, 2023
2c6792b
updating the array created for DD metadata
Mar 1, 2023
44f041c
updating the array created for DD metadata again
Mar 1, 2023
31b9230
updating the array created for DD metadata again
Mar 1, 2023
f9d3bc8
updating the array created for DD metadata again
Mar 1, 2023
8ddf965
updating the array created for DD metadata again
Mar 1, 2023
c91fe3a
updating the array created for DD metadata again
Mar 1, 2023
914f4cf
adding some additional logic to QueryDownloadControllerTest
Mar 1, 2023
cc8e699
updating the testing for QueryDownloadControllerTest
Mar 2, 2023
239c748
updating the testing for QueryDownloadControllerTest
Mar 2, 2023
da4b69d
updating the testing for QueryDownloadControllerTest
Mar 2, 2023
7bcd4dd
updating the testing for QueryDownloadControllerTest
Mar 2, 2023
83c13ce
updating the testing for QueryDownloadControllerTest
Mar 2, 2023
1a3876c
Fix data dictionary fields test
dafeder Mar 3, 2023
05471f4
Merge branch '2.x' into WCMS-12139
Mar 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ commands:
name: Install DDev
command: |
set -e
sudo rm -rf /etc/apt/sources.list.d/heroku.list
sudo apt-get update
sudo apt-get install ca-certificates
curl https://apt.fury.io/drud/gpg.key | sudo apt-key add -
Expand Down
8 changes: 8 additions & 0 deletions modules/common/src/Storage/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ class Query implements
OffsetterInterface,
LimiterInterface {

/**
* The collection of records (usually, a database table) to query against.
*
* @var array
*/
public $dataDictionaryFields;


/**
* The collection of records (usually, a database table) to query against.
*
Expand Down
25 changes: 22 additions & 3 deletions modules/common/src/Storage/SelectFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,19 @@ public function __construct(Connection $connection, string $alias = 't') {
* DKAN Query object.
*/
public function create(Query $query): Select {
$this->dbQuery = $this->connection->select($query->collection, $this->alias);

$this->dbQuery = $this->connection->select($query->collection, $this->alias);
$this->setQueryProperties($query);
$this->setQueryConditions($query);
$this->setQueryGroupBy($query);
$this->setQueryOrderBy($query);
$this->setQueryLimitAndOffset($query);
$this->setQueryJoins($query);

if (!empty($query->dataDictionaryFields)) {
$meta_data = $query->dataDictionaryFields;
$fields = $this->dbQuery->getFields();
$this->addDateExpressions($this->dbQuery, $fields, $meta_data);
}
// $string = $this->dbQuery->__toString();
if ($query->count) {
$this->dbQuery = $this->dbQuery->countQuery();
Expand All @@ -84,21 +88,36 @@ private function setQueryProperties(Query $query) {
// If properties is empty, just get all from base collection.
if (empty($query->properties)) {
$this->dbQuery->fields($this->alias);

return;
}

foreach ($query->properties as $p) {
$this->setQueryProperty($p);
}
}

/**
* Reformatting date fields.
*
* {@inheritdoc}
*/
private function addDateExpressions($db_query, $fields, $meta_data) {
foreach ($meta_data as $definition) {
// Confirm definition name is in the fields list.
if ($fields[$definition['name']]['field'] ?? FALSE && $definition['type'] == 'date') {
$db_query->addExpression("DATE_FORMAT(" . $definition['name'] . ", '" . $definition['format'] . "')", $definition['name']);
}
}
}

/**
* Set a single property.
*
* @param mixed $property
* One property from a query properties array.
*/
private function setQueryProperty($property) {

if (isset($property->expression)) {
$expressionStr = $this->expressionToString($property->expression);
$this->dbQuery->addExpression($expressionStr, $property->alias);
Expand Down
18 changes: 18 additions & 0 deletions modules/common/tests/src/Unit/Storage/SelectFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function testQuery(Query $query, string $sql, string $message, array $val
*/
public function testConditionByIsEqualTo() {
$query = new Query();
$query->properties = ["field1", "field2"];
$query->conditionByIsEqualTo('prop1', 'value1');
$db_query = $this->selectFactory->create($query);
$this->assertStringContainsString('t.prop1 LIKE :db_condition_placeholder_0', $this->selectToString($db_query));
Expand All @@ -59,6 +60,23 @@ public function testConditionByIsEqualToCaseInsensitive() {
$this->assertStringContainsString('t.prop1 LIKE BINARY :db_condition_placeholder_0', $this->selectToString($db_query));
}

/**
* Test two variations of Query::testConditionByIsEqualTo()
*/
public function testAddDateExpressions() {
$query = new Query();
$query->dataDictionaryFields = [
[
'name' => 'date',
'type' => 'date',
'format'=>'%m/%d/%Y',
]
];
$query->properties = ["date", "field2"];
$db_query = $this->selectFactory->create($query);
$this->assertStringContainsString("DATE_FORMAT(date, '%m/%d/%Y') AS date", $this->selectToString($db_query));
}

/**
*
*/
Expand Down
1 change: 1 addition & 0 deletions modules/datastore/datastore.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ services:
- '@queue'
- '@dkan.common.job_store'
- '@dkan.datastore.import_info_list'
- '@dkan.datastore.service.resource_processor.dictionary_enforcer'

dkan.datastore.query:
class: \Drupal\datastore\Service\Query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ protected function streamCsvResponse(DatastoreQuery $datastoreQuery, RootedJsonD
$this->sendRow($handle, $this->getHeaderRow($result));

// Get the result pointer and send each row to the stream one by one.
$result = $this->queryService->runResultsQuery($datastoreQuery, FALSE);
$result = $this->queryService->runResultsQuery($datastoreQuery, FALSE, TRUE);
while ($row = $result->fetchAssoc()) {
$this->sendRow($handle, array_values($row));
}
Expand Down
22 changes: 21 additions & 1 deletion modules/datastore/src/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Drupal\datastore\Service\Factory\ImportFactoryInterface;
use Drupal\datastore\Service\Info\ImportInfoList;
use FileFetcher\FileFetcher;
use Drupal\datastore\Service\ResourceProcessor\DictionaryEnforcer;

/**
* Main services for the datastore.
Expand Down Expand Up @@ -47,6 +48,13 @@ class Service implements ContainerInjectionInterface {
*/
private $jobStoreFactory;

/**
* Datastore Query object for conversion.
*
* @var Drupal\datastore\Service\ResourceProcessor\DictionaryEnforcer
*/
private $dictionaryEnforcer;

/**
* {@inheritdoc}
*/
Expand All @@ -57,6 +65,7 @@ public static function create(ContainerInterface $container) {
$container->get('queue'),
$container->get('dkan.common.job_store'),
$container->get('dkan.datastore.import_info_list'),
$container->get('dkan.datastore.service.resource_processor.dictionary_enforcer')
);
}

Expand All @@ -73,19 +82,23 @@ public static function create(ContainerInterface $container) {
* Jobstore factory service.
* @param \Drupal\datastore\Service\Info\ImportInfoList $importInfoList
* Import info list service.
* @param Drupal\datastore\Service\ResourceProcessor\DictionaryEnforcer $dictionaryEnforcer
* Dictionary Enforcer object.
*/
public function __construct(
ResourceLocalizer $resourceLocalizer,
ImportFactoryInterface $importServiceFactory,
QueueFactory $queue,
JobStoreFactory $jobStoreFactory,
ImportInfoList $importInfoList
ImportInfoList $importInfoList,
DictionaryEnforcer $dictionaryEnforcer
) {
$this->queue = $queue;
$this->resourceLocalizer = $resourceLocalizer;
$this->importServiceFactory = $importServiceFactory;
$this->jobStoreFactory = $jobStoreFactory;
$this->importInfoList = $importInfoList;
$this->dictionaryEnforcer = $dictionaryEnforcer;
}

/**
Expand Down Expand Up @@ -180,6 +193,13 @@ public function getImportService(DataResource $resource) {
return $this->importServiceFactory->getInstance($resource->getUniqueIdentifier(), ['resource' => $resource]);
}

/**
* Returns the Data Dictionary fields.
*/
public function getDataDictionaryFields() {
return $this->dictionaryEnforcer->returnDataDictionaryFields();
}

/**
* Drop a resources datastore.
*
Expand Down
22 changes: 18 additions & 4 deletions modules/datastore/src/Service/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Query implements ContainerInjectionInterface {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('dkan.datastore.service')
$container->get('dkan.datastore.service'),
);
}

Expand Down Expand Up @@ -119,16 +119,17 @@ public function getQueryStorageMap(DatastoreQuery $datastoreQuery) {
* DatastoreQuery object.
* @param bool $fetch
* Perform fetchAll and return array if true, else just statement (cursor).
* @param bool $csv
* Flag for csv downloads.
*
* @return array|\Drupal\Core\Database\StatementInterface
* Array of result objects or result statement of $fetch is false.
*/
public function runResultsQuery(DatastoreQuery $datastoreQuery, $fetch = TRUE) {
public function runResultsQuery(DatastoreQuery $datastoreQuery, $fetch = TRUE, $csv = FALSE) {
$primaryAlias = $datastoreQuery->{"$.resources[0].alias"};
if (!$primaryAlias) {
return [];
}

$storageMap = $this->getQueryStorageMap($datastoreQuery);

$storage = $storageMap[$primaryAlias];
Expand All @@ -137,8 +138,11 @@ public function runResultsQuery(DatastoreQuery $datastoreQuery, $fetch = TRUE) {
$schema = $this->filterSchemaFields($storage->getSchema(), $storage->primaryKey());
$datastoreQuery->{"$.properties"} = array_keys($schema['fields']);
}

$query = QueryFactory::create($datastoreQuery, $storageMap);
// Get data dictionary fields.
$meta_data = $csv != FALSE ? $this->getDatastoreService()->getDataDictionaryFields() : NULL;
// Pass the data dictionary metadata to the query.
$query->dataDictionaryFields = $csv && $meta_data ? $meta_data : NULL;

$result = $storageMap[$primaryAlias]->query($query, $primaryAlias, $fetch);

Expand All @@ -149,6 +153,16 @@ public function runResultsQuery(DatastoreQuery $datastoreQuery, $fetch = TRUE) {

}

/**
* Return the datastore service.
*
* @return \Drupal\datastore\Service
* Datastore Service.
*/
protected function getDatastoreService() {
return $this->datastore;
}

/**
* Remove the primary key from the schema field list.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,20 @@ public function applyDictionary(RootedJsonData $dictionary, string $datastore_ta
->execute();
}

/**
* Returning data dictionary fields from schema.
*
* {@inheritdoc}
*/
public function returnDataDictionaryFields() {
// Get DD is mode.
$dd_mode = $this->dataDictionaryDiscovery->getDataDictionaryMode();
// Get data dictionary info.
if ($dd_mode == "sitewide") {
$dict_id = $this->dataDictionaryDiscovery->getSitewideDictionaryId();
$metaData = $this->metastore->get('data-dictionary', $dict_id)->{"$.data.fields"};
return $metaData;
}
}

}
2 changes: 1 addition & 1 deletion modules/datastore/src/Storage/QueryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function __construct(DatastoreQuery $datastoreQuery, array $storageMap) {
* @param array $storageMap
* Storage map array.
*
* @return Drupal\common\Storage\Query
* @return \Drupal\common\Storage\Query
* DKAN query object.
*/
public static function create(DatastoreQuery $datastoreQuery, array $storageMap): Query {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
use Drupal\metastore\Storage\DataFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\common\Storage\SelectFactory;
use Drupal\Core\Database\Query\Select;
use Drupal\Tests\common\Unit\Connection;

/**
*
Expand All @@ -43,6 +46,8 @@ protected function setUp(): void {
->add(ContainerInterface::class, 'get', $options)
->add(CacheContextsManager::class, 'assertValidTokens', TRUE);
\Drupal::setContainer($chain->getMock());
$this->selectFactory = $this->getSelectFactory();

}

protected function tearDown(): void {
Expand All @@ -55,14 +60,19 @@ protected function tearDown(): void {
*/
private function queryResultCompare($data, $resource = NULL) {
$request = $this->mockRequest($data);

$dataDictionaryFields = [
'name' => 'date',
'type' => 'date',
'format '=>'%m/%d/%Y'
];
$qController = QueryController::create($this->getQueryContainer(500));
$response = $resource ? $qController->queryResource($resource, $request) : $qController->query($request);
$csv = $response->getContent();

$dController = QueryDownloadController::create($this->getQueryContainer(25));
ob_start(['self', 'getBuffer']);
$streamResponse = $resource ? $dController->queryResource($resource, $request) : $dController->query($request);
$streamResponse->dataDictionaryFields = $dataDictionaryFields;
$streamResponse->sendContent();
$streamedCsv = $this->buffer;
ob_get_clean();
Expand All @@ -88,6 +98,48 @@ public function testStreamedQueryCsv() {
$this->queryResultCompare($data);
}

public function queryResultReformatted($data){
$request = $this->mockRequest($data);
$dataDictionaryFields = [
'name' => 'date',
'type' => 'date',
'format '=>'%m/%d/%Y'
];
$qController = QueryController::create($this->getQueryContainer(500));
$response = $qController->query($request);
$csv = $response->getContent();

$dController = QueryDownloadController::create($this->getQueryContainer(25));
ob_start(['self', 'getBuffer']);
$streamResponse = $dController->query($request);
$streamResponse->dataDictionaryFields = $dataDictionaryFields;
//$streamResponse->sendContent();
$this->selectFactory->create($streamResponse);

$this->assertEquals(count(explode("\n", $csv)), count(explode("\n", $streamedCsv)));
$this->assertEquals($csv, $streamedCsv);
}

/**
*
*/
private function getSelectFactory() {
return new SelectFactory($this->getConnection());
}

/**
*
*/
private function getConnection() {
return (new Chain($this))
->add(
Connection::class,
"select",
new Select(new Connection(new \PDO('sqlite::memory:'), []), "table", "t")
)
->getMock();
}

/**
* Test streaming of a CSV file from database.
*/
Expand Down Expand Up @@ -382,6 +434,8 @@ private function getQueryContainer(int $rowLimit) {
->add(Data::class, 'getCacheMaxAge', 0)
->add(ConfigFactoryInterface::class, 'get', ImmutableConfig::class)
->add(Query::class, "getQueryStorageMap", $storageMap)
->add(Query::class, 'getDatastoreService', Service::class)
->add(Service::class, 'getDataDictionaryFields', NULL)
->add(ImmutableConfig::class, 'get', $rowLimit);

return $chain->getMock();
Expand Down
Loading