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

Data source for the Analytics App #2195

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/phpunit-mariadb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
with:
path: apps/${{ env.APP_NAME }}

- name: Checkout circles dependency
- name: Checkout teams dependency
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: nextcloud/circles
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/phpunit-mysql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
with:
path: apps/${{ env.APP_NAME }}

- name: Checkout circles dependency
- name: Checkout teams dependency
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: nextcloud/circles
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/phpunit-oci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:
with:
path: apps/${{ env.APP_NAME }}

- name: Checkout circles dependency
- name: Checkout teams dependency
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: nextcloud/circles
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/phpunit-pgsql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
with:
path: apps/${{ env.APP_NAME }}

- name: Checkout circles dependency
- name: Checkout teams dependency
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: nextcloud/circles
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/phpunit-sqlite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,20 @@ jobs:
with:
path: apps/${{ env.APP_NAME }}

- name: Checkout circles dependency
- name: Checkout teams app
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
repository: nextcloud/circles
ref: ${{ matrix.server-versions }}
path: apps/circles

- name: Checkout analytics app
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
repository: rello/analytics
ref: master
path: apps/analytics

- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b # v2
with:
Expand Down
154 changes: 154 additions & 0 deletions lib/Analytics/AnalyticsDatasource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php
/**
* Analytics data source
* Report Table App data with the Analytics App
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the LICENSE.md file.
*
* @author Marcel Scherello <analytics@scherello.de>
*/

namespace OCA\Forms\Analytics;

/** @psalm-suppress UndefinedClass */
use OCA\Analytics\Datasource\IDatasource;
use OCA\Forms\Db\FormMapper;
use OCA\Forms\Service\FormsService;
use OCA\Forms\Service\SubmissionService;
use OCP\IL10N;
use Psr\Log\LoggerInterface;

class AnalyticsDatasource implements IDatasource {

public function __construct(

Check warning on line 24 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L24

Added line #L24 was not covered by tests
protected ?string $userId,
private IL10N $l10n,
private LoggerInterface $logger,
private FormMapper $formMapper,
private FormsService $formsService,
private SubmissionService $submissionService,
) {
}

/**
* @return string Display Name of the datasource
*/
public function getName(): string {
return $this->l10n->t('Nextcloud Forms');

Check warning on line 38 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L37-L38

Added lines #L37 - L38 were not covered by tests
}

/**
* @return int 2 digit unique datasource id
*/
public function getId(): int {
return 66;

Check warning on line 45 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L44-L45

Added lines #L44 - L45 were not covered by tests
}

/**
* available options of the data source
*
* return needs to be an array and can consist of many fields.
* every field needs to provide the following format
* id *mandatory* = name of the option for the readData
* name *mandatory* = displayed name of the input field in the UI
* type *optional* = 'tf' to create a dropdown. Values need to be provided in the placeholder separated with "/".
* placeholder *mandatory* = help text for the input field in the UI
* for type=tf:
* e.g. "true/false"
* if value/text pairs are required for the dropdown/option, the values need to be separated with "-" in addition.
* e.g. "eq-equal/gt-greater"
* to avoid translation of the technical strings, separate them
* 'true-' - $this->l10n->t('Yes').'/false-'.$this->l10n->t('No')
*
* example:
* {['id' => 'datatype', 'name' => 'Type of Data', 'type' => 'tf', 'placeholder' => 'adaptation/absolute']}
*
* @return array
*/
public function getTemplate(): array {
$formsString = '';
$questionString = '';
$template = [];

Check warning on line 72 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L69-L72

Added lines #L69 - L72 were not covered by tests

$forms = $this->formMapper->findAllByOwnerId($this->userId);
foreach ($forms as $form) {
$formsString = $formsString . $form->getId() . '-' . $form->getTitle() . '/';

Check warning on line 76 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L74-L76

Added lines #L74 - L76 were not covered by tests
/* Questions are not yet required
$questions = $this->formsService->getQuestions($form->getId());
foreach ($questions as $question) {
$questionString = $questionString . $question['id'] . '-' . $question['text'] . '/';
}*/
}

// add the tables to a dropdown in the data source settings
$template[] = ['id' => 'formId', 'name' => $this->l10n->t('Select form'), 'type' => 'tf', 'placeholder' => $formsString];
$template[] = ['id' => 'timestamp', 'name' => $this->l10n->t('Timestamp of data load'), 'placeholder' => 'false-' . $this->l10n->t('No') . '/true-' . $this->l10n->t('Yes'), 'type' => 'tf'];
return $template;

Check warning on line 87 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L85-L87

Added lines #L85 - L87 were not covered by tests
}

/**
* Read the Data
*
* return needs to be an array
* [
* 'header' => $header, //array('column header 1', 'column header 2','column header 3')
* 'dimensions' => array_slice($header, 0, count($header) - 1),
* 'data' => $data,
* 'error' => 0, // INT 0 = no error
* ]
*
* @param array $option
* @return array
*/
public function readData($option): array {
$questionMap = [];
$answerCounts = [];

Check warning on line 106 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L104-L106

Added lines #L104 - L106 were not covered by tests

$formId = $option['formId'];

Check warning on line 108 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L108

Added line #L108 was not covered by tests

$questions = $this->formsService->getQuestions($formId);
foreach ($questions as $question) {
$questionMap[$question['id']] = $question['text'];

Check warning on line 112 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L110-L112

Added lines #L110 - L112 were not covered by tests
}

$submissions = $this->submissionService->getSubmissions($formId);
foreach ($submissions as $submission) {
foreach ($submission['answers'] as $answer) {
$questionText = $questionMap[$answer['questionId']];
$key = $questionText . '|' . $answer['text'];
if (isset($answerCounts[$key])) {
$answerCounts[$key]++;

Check warning on line 121 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L115-L121

Added lines #L115 - L121 were not covered by tests
} else {
$answerCounts[$key] = 1;

Check warning on line 123 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L123

Added line #L123 was not covered by tests
}
}
}

foreach ($answerCounts as $key => $count) {
[$questionText, $text] = explode('|', $key);
$results[] = [$questionText, $text, $count];

Check warning on line 130 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L128-L130

Added lines #L128 - L130 were not covered by tests
}

// Sort by questionText ascending and count descending
usort($results, function ($a, $b) {
if ($a[0] === $b[0]) {
return $b[2] <=> $a[2];

Check warning on line 136 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L134-L136

Added lines #L134 - L136 were not covered by tests
}
return $a[0] <=> $b[0];
});

Check warning on line 139 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L138-L139

Added lines #L138 - L139 were not covered by tests

$header = [];
$header[0] = $this->l10n->t('Question');
$header[1] = $this->l10n->t('Answer');
$header[2] = $this->l10n->t('Count');

Check warning on line 144 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L141-L144

Added lines #L141 - L144 were not covered by tests

return [
'header' => $header,
'dimensions' => array_slice($header, 0, count($header) - 1),
'data' => $results,

Check warning on line 149 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L146-L149

Added lines #L146 - L149 were not covered by tests
//'rawdata' => $data,
'error' => 0,
];

Check warning on line 152 in lib/Analytics/AnalyticsDatasource.php

View check run for this annotation

Codecov / codecov/patch

lib/Analytics/AnalyticsDatasource.php#L151-L152

Added lines #L151 - L152 were not covered by tests
}
}
3 changes: 3 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@

namespace OCA\Forms\AppInfo;

use OCA\Analytics\Datasource\DatasourceEvent;
use OCA\Forms\Capabilities;
use OCA\Forms\FormsMigrator;
use OCA\Forms\Listener\AnalyticsDatasourceListener;
use OCA\Forms\Listener\UserDeletedListener;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
Expand Down Expand Up @@ -58,6 +60,7 @@

$context->registerCapability(Capabilities::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
$context->registerEventListener(DatasourceEvent::class, AnalyticsDatasourceListener::class);

Check warning on line 63 in lib/AppInfo/Application.php

View check run for this annotation

Codecov / codecov/patch

lib/AppInfo/Application.php#L63

Added line #L63 was not covered by tests
$context->registerUserMigrator(FormsMigrator::class);
}

Expand Down
31 changes: 31 additions & 0 deletions lib/Listener/AnalyticsDatasourceListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* Analytics data source
* Report Table App data with the Analytics App
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the LICENSE.md file.
*
* @author Marcel Scherello <analytics@scherello.de>
*/
declare(strict_types=1);

namespace OCA\Forms\Listener;

use OCA\Analytics\Datasource\DatasourceEvent;
use OCA\Forms\Analytics\AnalyticsDatasource;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;

/**
* @template-implements IEventListener<DatasourceEvent>
*/
class AnalyticsDatasourceListener implements IEventListener {
public function handle(Event $event): void {
if (!($event instanceof DatasourceEvent)) {

Check warning on line 25 in lib/Listener/AnalyticsDatasourceListener.php

View check run for this annotation

Codecov / codecov/patch

lib/Listener/AnalyticsDatasourceListener.php#L24-L25

Added lines #L24 - L25 were not covered by tests
// Unrelated
return;

Check warning on line 27 in lib/Listener/AnalyticsDatasourceListener.php

View check run for this annotation

Codecov / codecov/patch

lib/Listener/AnalyticsDatasourceListener.php#L27

Added line #L27 was not covered by tests
}
$event->registerDatasource(AnalyticsDatasource::class);

Check warning on line 29 in lib/Listener/AnalyticsDatasourceListener.php

View check run for this annotation

Codecov / codecov/patch

lib/Listener/AnalyticsDatasourceListener.php#L29

Added line #L29 was not covered by tests
}
}
4 changes: 4 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
<referencedClass name="OCA\Circles\CirclesManager" />
<referencedClass name="OCA\Circles\Model\Circle" />
<referencedClass name="OCA\Circles\Model\Member" />
<referencedClass name="OCA\Analytics\Datasource\IDatasource" />
<referencedClass name="OCA\Analytics\Datasource\DatasourceEvent" />
</errorLevel>
</UndefinedClass>
<UndefinedDocblockClass>
Expand All @@ -35,10 +37,12 @@
<referencedClass name="Doctrine\DBAL\Schema\SchemaException" />
<referencedClass name="Doctrine\DBAL\Driver\Statement" />
<referencedClass name="Doctrine\DBAL\Schema\Table" />
<referencedClass name="OCA\Analytics\Datasource\DatasourceEvent" />
</errorLevel>
</UndefinedDocblockClass>
</issueHandlers>
<stubs>
<file name="tests/stubs/oc_hooks_emitter.php" />
<file name="tests/stubs/oca-analytics-idatasource.php" />
</stubs>
</psalm>
Loading
Loading