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

Add "Create Documents" SearchKit action #53

Merged
merged 12 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
42 changes: 42 additions & 0 deletions .github/workflows/phpcs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: PHP_CodeSniffer

on:
pull_request:
paths:
- '**.php'
- tools/phpcs/composer.json
- phpcs.xml.dist

jobs:
phpcs:
runs-on: ubuntu-latest
name: PHP_CodeSniffer

steps:
- uses: actions/checkout@v3

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
coverage: none
tools: cs2pr
env:
fail-fast: true

- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('tools/phpcs/composer.json') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install dependencies
run: composer composer-phpcs -- update --no-progress --prefer-dist

- name: Run PHP_CodeSniffer
run: composer phpcs -- -q --report=checkstyle | cs2pr
52 changes: 52 additions & 0 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: PHPStan

on:
pull_request:
paths:
- '**.php'
- composer.json
- tools/phpstan/composer.json
- ci/composer.json
- phpstan.ci.neon
- phpstan.neon.dist

jobs:
phpstan:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ['7.4', '8.0', '8.1']
prefer: ['prefer-stable', 'prefer-lowest']
name: PHPStan with PHP ${{ matrix.php-versions }} ${{ matrix.prefer }}

steps:
- uses: actions/checkout@v3

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none
env:
fail-fast: true

- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.prefer }}-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-${{ matrix.prefer }}-

- name: Install dependencies
run: |
composer update --no-progress --prefer-dist --${{ matrix.prefer }} &&
composer composer-phpunit -- update --no-progress --prefer-dist &&
composer composer-phpstan -- update --no-progress --prefer-dist --optimize-autoloader &&
composer --working-dir=ci update --no-progress --prefer-dist --${{ matrix.prefer }} --optimize-autoloader --ignore-platform-req=ext-gd

- name: Run PHPStan
run: composer phpstan -- analyse -c phpstan.ci.neon
36 changes: 36 additions & 0 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: PHPUnit

on:
pull_request:
paths:
- '**.php'
- composer.json
- tools/phpunit/composer.json
- phpunit.xml.dist

env:
# On github CI machine creating the "/vendor" volume fails otherwise with: read-only file system: unknown
BIND_VOLUME_PERMISSIONS: rw

jobs:
phpunit:
runs-on: ubuntu-latest
strategy:
matrix:
civicrm-image-tags: [ '5-drupal', '5-drupal-php7.4', '5.44-drupal-php7.4' ]
name: PHPUnit with Docker image michaelmcandrew/civicrm:${{ matrix.civicrm-image-tags }}
env:
CIVICRM_IMAGE_TAG: ${{ matrix.civicrm-image-tags }}

steps:
- uses: actions/checkout@v3
- name: Pull images
run: docker compose -f tests/docker-compose.yml pull --quiet
- name: Start containers
run: docker compose -f tests/docker-compose.yml up -d
- name: Prepare environment
run: docker compose -f tests/docker-compose.yml exec civicrm sites/default/files/civicrm/ext/de.systopia.civioffice/tests/docker-prepare.sh
- name: Run PHPUnit
run: docker compose -f tests/docker-compose.yml exec civicrm sites/default/files/civicrm/ext/de.systopia.civioffice/tests/docker-phpunit.sh
- name: Remove containers
run: docker compose -f tests/docker-compose.yml down -v
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
/vendor/
/.idea/
composer.lock
/.phpcs.cache
/.phpunit.result.cache
/.phpstan/
/ci/composer.lock
/ci/vendor/
/composer.lock
/phpstan.neon
/tools/*/vendor/
/tools/*/composer.lock
/vendor/
16 changes: 14 additions & 2 deletions CRM/Civioffice/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,19 @@ public function getDocumentRenderer(string $document_renderer_uri)
return null; // not found
}

public function getDocuments($select2 = false)
/**
* @phpstan-type documentListT array<string, array<string, \CRM_Civioffice_Document>>
* Document store URI and document URI are the keys.
*
* @phpstan-type select2OptionsT list<array{
* text: string,
* children: list<array{id: string, text: string}>,
* }>
* To be used in a Select2 field.
*
* @phpstan-return documentListT|select2OptionsT
*/
public function getDocuments(bool $select2 = false): array
{
$document_list = [];
// todo: only show supported source MIME types
Expand Down Expand Up @@ -318,4 +330,4 @@ public static function getHomeFolder(): string
Civi::log()->warning("CiviOffice: Couldn't determine web user's home folder.");
return '~';
}
}
}
16 changes: 8 additions & 8 deletions CRM/Civioffice/ConversionJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class CRM_Civioffice_ConversionJob

/**
* @var string $entity_type
* Type of entity (like 'contact' ID)
* Type of entity (e.g. 'Contact')
*/
protected $entity_type;

Expand Down Expand Up @@ -119,31 +119,31 @@ public function run(): bool
foreach ($this->entity_IDs as $entity_id) {
$contact_id = NULL;
switch ($this->entity_type) {
case 'contact':
case 'Contact':
$contact_id = $entity_id;
break;
case 'contribution':
case 'Contribution':
$contact_id = \Civi\Api4\Contribution::get()
->addSelect('contact_id')
->addWhere('id', '=', $entity_id)
->execute()
->single()['contact_id'];
break;
case 'participant':
case 'Participant':
$contact_id = \Civi\Api4\Participant::get()
->addSelect('contact_id')
->addWhere('id', '=', $entity_id)
->execute()
->single()['contact_id'];
break;
case 'membership':
case 'Membership':
$contact_id = \Civi\Api4\Membership::get()
->addSelect('contact_id')
->addWhere('id', '=', $entity_id)
->execute()
->single()['contact_id'];
break;
case 'activity':
case 'Activity':
$contact_id = \Civi\Api4\ActivityContact::get()
->addSelect('contact_id')
->addWhere('activity_id', '=', $entity_id)
Expand All @@ -152,7 +152,7 @@ public function run(): bool
// Use the first record, if any, as there might be more than one.
->first()['contact_id'] ?? null;
break;
case 'case':
case 'Case':
$contact_id = \Civi\Api4\CaseContact::get()
->addSelect('contact_id')
->addWhere('case_id', '=', $entity_id)
Expand Down Expand Up @@ -196,4 +196,4 @@ private function removeFilesAndFolder(string $folder_path): void
}
rmdir($folder_path);
}
}
}
133 changes: 9 additions & 124 deletions CRM/Civioffice/DocumentRendererType.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
| written permission from the original author(s). |
+-------------------------------------------------------*/

use Civi\Core\Event\GenericHookEvent;
use Civi\Token\TokenProcessor;
use Civi\Api4;
use CRM_Civioffice_ExtensionUtil as E;
Expand Down Expand Up @@ -109,7 +110,7 @@ public abstract function render(
array $entity_ids,
CRM_Civioffice_DocumentStore_LocalTemp $temp_store,
string $target_mime_type,
string $entity_type = 'contact',
string $entity_type = 'Contact',
array $live_snippets = []
): array;

Expand All @@ -131,132 +132,16 @@ public abstract function render(
*/
public function processTokenContext(string $entity_type, int $entity_id): \Civi\Token\TokenRow
{
$entities = [
$entity_type => ['entity_id' => $entity_id],
];

// Add implicit contact token context for contributions.
if (
array_key_exists('contribution', $entities)
&& !array_key_exists('contact', $entities)
) {
$contribution = Api4\Contribution::get()
->addWhere('id', '=', $entities['contribution']['entity_id'])
->execute()
->single();
$entities['contact'] = ['entity_id' => $contribution['contact_id']];
}

// Add implicit contact and event token contexts for participants.
if (array_key_exists('participant', $entities)) {
$participant = Api4\Participant::get()
->addWhere('id', '=', $entities['participant']['entity_id'])
->execute()
->single();
if (!array_key_exists('contact', $entities)) {
$entities['contact'] = ['entity_id' => $participant['contact_id']];
}
if (!array_key_exists('event', $entities)) {
$entities['event'] = ['entity_id' => $participant['event_id']];
}
if (!array_key_exists('contribution', $entities)) {
try {
$participant_payment = civicrm_api3(
'ParticipantPayment',
'getsingle',
['participant_id' => $participant['id']]
);
$entities['contribution'] = ['entity_id' => $participant_payment['contribution_id']];
} catch (Exception $exception) {
// No participant payment, nothing to do.
}
}
}

// Add implicit contact token context for memberships.
if (
array_key_exists('membership', $entities)
&& !array_key_exists('contact', $entities)
) {
$membership = Api4\Membership::get()
->addWhere('id', '=', $entities['membership']['entity_id'])
->execute()
->single();
$entities['contact'] = ['entity_id' => $membership['contact_id']];
}

// Add implicit contact and case token context for activities.
if (
array_key_exists('activity', $entities)
) {
if (!array_key_exists('contact', $entities)) {
if (
$activityContact = Api4\ActivityContact::get()
->addSelect('contact_id')
->addWhere('activity_id', '=', $entities['activity']['entity_id'])
->addWhere('record_type_id:name', '=', 'Activity Source')
->execute()
// Use the first record, as there might be more than one.
->first()
) {
$entities['contact'] = ['entity_id' => $activityContact['contact_id']];
}
}
if (!array_key_exists('case', $entities)) {
$activity = Api4\Activity::get()
->addSelect('case_id')
->addWhere('id', '=', $entities['activity']['entity_id'])
->addWhere('case_id', 'IS NOT EMPTY')
->execute()
->single();
$entities['case'] = ['entity_id' => $activity['case_id']];
}
}

// Add implicit contact token context for cases.
if (
array_key_exists('case', $entities)
&& !array_key_exists('contact', $entities)
) {
if (
$caseContact = Api4\CaseContact::get()
->addSelect('contact_id')
->addWhere('case_id', '=', $entities['case']['entity_id'])
->execute()
// Use the first record, as there might be more than one.
->first()
) {
$entities['contact'] = ['entity_id' => $caseContact['contact_id']];
}
}

// Translate entity types into token contexts known to CiviOffice.
$entity_token_contexts = [
'contact' => 'contactId',
'contribution' => 'contributionId',
'participant' => 'participantId',
'event' => 'eventId',
'membership' => 'membershipId',
'activity' => 'activityId',
'case' => 'caseId',
];
$context = [];
foreach ($entities as $entity_type => $contextId) {
if (isset($entity_token_contexts[$entity_type])) {
$context[$entity_token_contexts[$entity_type]] = $contextId['entity_id'];
}
}

// Let other extensions define additional token contexts, for the given entity or generically.
// Let the token contexts be defined, for the given entity or generically.
Civi::dispatcher()->dispatch(
'civi.civioffice.tokenContext',
\Civi\Core\Event\GenericHookEvent::create(
[
'context' => &$context,
'entity_type' => $entity_type,
'entity_id' => $entity_id,
]
)
GenericHookEvent::create([
'context' => &$context,
'entity_type' => $entity_type,
'entity_id' => $entity_id,
])
);

// Reset (re-instantiate) the token processor per document for not evaluating with previous token rows.
Expand Down Expand Up @@ -330,4 +215,4 @@ public function checkConfigurationSupported($configurationItem) {
);
}
}
}
}
Loading
Loading