Compare commits

..

19 Commits

Author SHA1 Message Date
fdf00d5c95 fixed the unit test 2022-05-27 11:24:04 +02:00
a4aa8444e3 changed timebasedfieldupdated back 2022-05-27 09:52:56 +01:00
a228ea5554 removed unused code 2022-05-27 09:49:23 +01:00
9862e65ea9 Merge branch 'master' of ssh://git.autonomic.zone:2222/autonomic-cooperative/opencase 2022-05-19 10:46:44 +01:00
2e071af1b7 added static/dynamic divs to actor 2022-05-19 10:46:22 +01:00
12788e7965 deleted "no_cases" module 2022-05-19 10:23:53 +02:00
a5132bbcfc added update hook for total cases field 2022-05-19 09:12:31 +01:00
f671580ed7 activity provider field now uses case_providers view 2022-05-19 07:46:34 +01:00
9351768b25 Refactor 2022-05-18 13:54:06 +01:00
1c61f2f0a4 case provisions are deleted when case is deleted. 2022-05-18 13:40:03 +01:00
13fb920e69 total cases field is working. 2022-05-18 13:27:14 +01:00
cfec9be05c div around fields and static fields at top, for orgs and cases 2022-05-16 20:18:49 +01:00
d483b3f47e refactor 2022-05-16 17:25:58 +01:00
f6792e5053 addConditionsToQuery adds "=" by default 2022-05-16 10:01:16 +01:00
804694c0cc typo 2022-05-15 19:26:54 +01:00
f1965ff3c1 Added superficial tests for addConditionsToQuery 2022-05-15 19:25:35 +01:00
b000e9414b tests passing 2022-05-15 18:52:00 +01:00
107d0d6a8c Merge branch 'master' of ssh://git.autonomic.zone:2222/autonomic-cooperative/opencase 2022-05-15 18:49:02 +01:00
6e91a54dc4 aaded some tests, which are now passing 2022-05-15 16:13:53 +01:00
23 changed files with 254 additions and 688 deletions

View File

@ -8,6 +8,7 @@
*/
use Drupal\Core\Render\Element;
use Drupal\opencase;
/**
* Prepares variables for Case templates.
@ -20,18 +21,6 @@ use Drupal\Core\Render\Element;
* - attributes: HTML attributes for the containing element.
*/
function template_preprocess_oc_case(array &$variables) {
// Separate the fields into two sections to be displayed in two columns.
// Remove the name (title) field as this is displayed anyway.
$variables['id'] = $variables['elements']['#oc_case']->get('id')[0]->get('value')->getValue();
$variables['base_fields'] = array();
$variables['other_fields'] = array();
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
if (in_array($key, ['created', 'changed', 'files', 'actors_involved', 'status', 'user_id'])) {
$variables['base_fields'][$key] = $variables['elements'][$key];
} else {
$variables['other_fields'][$key] = $variables['elements'][$key];
unset($variables['other_fields']['name']);
}
}
_template_preprocess_entity($variables);
}

View File

@ -1,6 +1,17 @@
<?php
use \Drupal\Core\Field\BaseFieldDefinition;
function opencase_cases_update_90005() {
$field_storage_definition = BaseFieldDefinition::create('integer')
->setLabel(t('Number of Cases'))
->setRevisionable(TRUE)
->setDisplayConfigurable('view', true);
\Drupal::entityDefinitionUpdateManager()
->installFieldStorageDefinition('total_cases', 'oc_actor', 'opencase_cases', $field_storage_definition);
}
function opencase_cases_update_90004() {
$field_storage_definition = BaseFieldDefinition::create('string_long')
->setRevisionable(TRUE)

View File

@ -68,19 +68,6 @@ function opencase_cases_theme() {
];
}
/**
* @return Drupal\opencase_cases\entity\OCActivity[]
*/
function opencase_cases_get_activities(Drupal\opencase_cases\entity\OCCase $case): array {
$query = \Drupal::entityQuery('oc_activity')
->condition('oc_case.target_id', $case->id());
$activity_ids = $query->execute();
$activities = [];
foreach($activity_ids as $id) {
$activities[] = Drupal\opencase_entities\Entity\OCActivity::load($id);
}
return $activities;
}
function opencase_cases_oc_case_fee_update(Drupal\opencase_cases\entity\OCCaseFee $case_fee): void {
$case = $case_fee->getCase();
@ -119,13 +106,6 @@ function opencase_cases_entity_base_field_info($entity_type) {
return $fields;
}
// When deleting a case, delete the activities associated with it
function opencase_cases_oc_case_delete(Drupal\opencase_cases\Entity\OCCase $case): void {
$activities = opencase_cases_get_activities($case);
foreach ($activities as $activity) {
$activity->delete();
}
}
/**

View File

@ -91,6 +91,24 @@ class OCCase extends RevisionableContentEntityBase implements OCCaseInterface
];
}
public function deleteCaseProvisions(): void {
$this->deleteChildren('oc_case_provision');
}
public function deleteActivities(): void {
$this->deleteChildren('oc_activity');
}
public function deleteChildren($child_entity_type):void {
$query = \Drupal::entityQuery($child_entity_type)
->condition('oc_case.target_id', $this->id());
$ids = $query->execute();
foreach($ids as $id) {
\Drupal::entityTypeManager()
->getStorage($child_entity_type)
->load($id)->delete();
}
}
public static function defaultTarget()
{

View File

@ -16,7 +16,10 @@
*/
#}
<div{{ attributes.addClass('oc_case') }}>
{% if content %}
{{- content -}}
{% if normal_fields %}
<div id='static_data'>{{- normal_fields -}}</div>
{% endif %}
{% if extra_fields %}
<div id='dynamic_data'>{{- extra_fields -}}</div>
{% endif %}
</div>

View File

@ -1,46 +0,0 @@
<?php
namespace Drupal\Tests\opencase_defaults\Functional;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
/**
* Simple test to ensure that main page loads with module enabled.
*
* @group opencase_defaults
*/
class LoadTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['opencase_defaults'];
/**
* A user with permission to administer site configuration.
*
* @var \Drupal\user\UserInterface
*/
protected $user;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->user = $this->drupalCreateUser(['administer site configuration']);
$this->drupalLogin($this->user);
}
/**
* Tests that the home page loads with a 200 response.
*/
public function testLoad() {
$this->drupalGet(Url::fromRoute('<front>'));
$this->assertSession()->statusCodeEquals(200);
}
}

View File

@ -20,17 +20,5 @@ use Drupal\Core\Render\Element;
* - attributes: HTML attributes for the containing element.
*/
function template_preprocess_oc_actor(array &$variables) {
// Make the id available to the template and also separate the fields
// into two sections to be displayed in two columns.
$variables['id'] = $variables['elements']['#oc_actor']->get('id')[0]->get('value')->getValue();
$variables['contact_details'] = array();
$variables['fields_other_than_contact_details'] = array();
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
if (in_array($key, ['email', 'phone', 'phone2', 'postal_address', 'post_code'])) {
$variables['contact_details'][$key] = $variables['elements'][$key];
} else {
$variables['fields_other_than_contact_details'][$key] = $variables['elements'][$key];
}
}
_template_preprocess_entity($variables);
}

View File

@ -20,11 +20,5 @@ use Drupal\Core\Render\Element;
* - attributes: HTML attributes for the containing element.
*/
function template_preprocess_oc_organisation(array &$variables) {
// Fetch OCOrganisation Entity Object.
$oc_organisation = $variables['elements']['#oc_organisation'];
// Helpful $content variable for templates.
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
_template_preprocess_entity($variables);
}

View File

@ -247,7 +247,12 @@ class OCActivity extends RevisionableContentEntityBase implements OCActivityInte
->setLabel(t('Provider'))
->setRevisionable(TRUE)
->setSetting('target_type', 'oc_actor')
->setSetting('handler', 'default')
->setSetting('handler', 'views')
->setSetting('handler_settings', [
'view' => [
'view_name' => 'case_providers',
'display_name' => 'entity_reference_1'
]])
->setDefaultValueCallback('\Drupal\opencase_entities\Entity\OCActivity::loggedInActorId')
->setDisplayConfigurable('form', true)
->setDisplayConfigurable('view', true);

View File

@ -208,15 +208,17 @@ class OCActor extends RevisionableContentEntityBase implements OCActorInterface
}
public function getCountOfCaseProvisions(array $conditions = []): int {
public function getCountOfCaseProvisions(array $conditionsToApplyToCaseProvisionQuery = []): int {
$query = \Drupal::entityQuery('oc_case_provision');
$query->condition('oc_provider', $this->id());
// foreach($conditions as $condition) {
// $query->condition($condition);
// }
return count($query->execute());
}
public function calculateTotalCases(): void {
$this->set('total_cases', $this->getCountOfCaseProvisions());
$this->save();
}
/**
* {@inheritdoc}
*/

View File

@ -16,7 +16,10 @@
*/
#}
<div{{ attributes.addClass('oc_actor') }}>
{% if content %}
{{- content -}}
{% if normal_fields %}
<div id='static_data'>{{- normal_fields -}}</div>
{% endif %}
{% if extra_fields %}
<div id='dynamic_data'>{{- extra_fields -}}</div>
{% endif %}
</div>

View File

@ -16,7 +16,10 @@
*/
#}
<div{{ attributes.addClass('oc_organisation') }}>
{% if content %}
{{- content -}}
{% if normal_fields %}
<div id='static_data'>{{- normal_fields -}}</div>
{% endif %}
{% if extra_fields %}
<div id='dynamic_data'>{{- extra_fields -}}</div>
{% endif %}
</div>

View File

@ -1,46 +0,0 @@
<?php
namespace Drupal\Tests\opencase_entities\Functional;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
/**
* Simple test to ensure that main page loads with module enabled.
*
* @group opencase_entities
*/
class LoadTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['opencase_entities'];
/**
* A user with permission to administer site configuration.
*
* @var \Drupal\user\UserInterface
*/
protected $user;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->user = $this->drupalCreateUser(['administer site configuration']);
$this->drupalLogin($this->user);
}
/**
* Tests that the home page loads with a 200 response.
*/
public function testLoad() {
$this->drupalGet(Url::fromRoute('<front>'));
$this->assertSession()->statusCodeEquals(200);
}
}

View File

@ -1,30 +0,0 @@
langcode: en
status: true
dependencies:
config:
- views.view.activities
module:
- route_condition
- views
theme:
- bartik
id: views_block__activities_block_1
theme: bartik
region: content
weight: 0
provider: null
plugin: 'views_block:activities-block_1'
settings:
id: 'views_block:activities-block_1'
label: ''
provider: views
label_display: visible
views_label: ''
items_per_page: none
context_mapping: { }
visibility:
route:
id: route
routes: entity.oc_actor.canonical
negate: false
context_mapping: { }

View File

@ -1,318 +0,0 @@
langcode: en
status: true
dependencies:
module:
- datetime
- opencase_entities
id: activities
label: Activities
module: views
description: ''
tag: ''
base_table: oc_activity_field_data
base_field: id
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
options: { }
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: none
options:
items_per_page: null
offset: 0
style:
type: table
row:
type: fields
fields:
name:
id: name
table: oc_activity_field_data
field: name
relationship: none
group_type: group
admin_label: ''
label: Subject
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: value
type: string
settings:
link_to_entity: true
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
entity_type: null
entity_field: name
plugin_id: field
activity_date_time:
id: activity_date_time
table: oc_activity_field_data
field: activity_date_time
relationship: none
group_type: group
admin_label: ''
label: 'Date and time'
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: value
type: datetime_default
settings:
timezone_override: ''
format_type: medium
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
entity_type: oc_activity
entity_field: activity_date_time
plugin_id: field
actors_involved_target_id:
id: actors_involved_target_id
table: oc_activity__actors_involved
field: actors_involved_target_id
relationship: none
group_type: group
admin_label: ''
label: Participants
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: target_id
type: entity_reference_label
settings:
link: true
group_column: target_id
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
entity_type: oc_activity
entity_field: actors_involved
plugin_id: field
filters: { }
sorts: { }
title: Activities
header: { }
footer: { }
empty: { }
relationships: { }
arguments:
actors_involved_target_id:
id: actors_involved_target_id
table: oc_activity__actors_involved
field: actors_involved_target_id
relationship: none
group_type: group
admin_label: ''
default_action: default
exception:
value: all
title_enable: false
title: All
title_enable: false
title: ''
default_argument_type: raw
default_argument_options:
index: 2
use_alias: false
default_argument_skip_url: false
summary_options:
base_path: ''
count: true
items_per_page: 25
override: false
summary:
sort_order: asc
number_of_records: 0
format: default_summary
specify_validation: false
validate:
type: none
fail: 'not found'
validate_options: { }
break_phrase: false
not: false
entity_type: oc_activity
entity_field: actors_involved
plugin_id: numeric
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
tags: { }
block_1:
display_plugin: block
id: block_1
display_title: Block
position: 1
display_options:
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
tags: { }

View File

@ -1,8 +0,0 @@
name: 'OpenCase No Cases'
type: module
description: 'Enable EITHER this OR "OpenCase Cases". This one links activities directly to people, which is simpler and therefore what some orgs prefer.'
core: 8.x
package: 'OpenCase'
dependencies:
- opencase_entities
- route_condition

View File

@ -1,105 +0,0 @@
<?php
/**
* @file
* Contains opencase_no_cases.module.
*/
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Field\BaseFieldDefinition;
/**
* Implements hook_help().
*/
function opencase_no_cases_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the opencase_no_cases module.
case 'help.page.opencase_no_cases':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Enable EITHER this OR &quot;OpenCase Cases&quot;. This one links activities directly to people, which is simpler and therefore what some orgs prefer.') . '</p>';
return $output;
default:
}
}
function opencase_no_cases_entity_base_field_info($entity_type) {
if ($entity_type->id() === 'oc_activity') {
$fields = array();
$fields['actors_involved'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Participants'))
->setDescription(t('People involved in this activity. To add one, start typing their name.'))
->setSetting('target_type', 'oc_actor')
->setSetting('handler', 'default')
->setTranslatable(TRUE)
->setCardinality(-1)
->setDisplayOptions('form', [
'label' => 'above',
'type' => 'hidden',
'weight' => -100,
'settings' => [
'match_operator' => 'CONTAINS',
'size' => '60',
'autocomplete_type' => 'tags',
'placeholder' => '',
],
])
->setDisplayOptions('view', [
'label' => 'above',
'weight' => -100,
])
->setDefaultValueCallback('opencase_no_cases_actors_involved_callback')
->setRequired(TRUE);
}
return $fields;
}
/**
* When creating an activity, it sets the first involved party to the actor
* id from the URL, and the second to the author's linked actor
* (if it exists and is different)
*/
function opencase_no_cases_actors_involved_callback() {
$author_linked_actor_id = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id())->get('field_linked_opencase_actor')->target_id;
$currently_viewed_actor_id = \Drupal::request()->query->get('actor_id');
return array_unique([$currently_viewed_actor_id, $author_linked_actor_id]);
}
/**
* Implementation of hook_form_alter()
* When deleting an activity go back to the page of the first listed involved party (as this is likely to be the "target" of the activity).
*/
function opencase_form_alter(&$form, &$form_state, $form_id) {
if (preg_match('/oc_actor_.*_delete_form/', $form_id) or (preg_match('/oc_organisation_.*_delete_form/', $form_id))) {
$form['actions']['submit']['#submit'][] = '_opencase_no_cases_redirect_to_home';
$form['actions']['cancel']['#url'] = $form_state->getFormObject()->getEntity()->toUrl();
}
if (preg_match('/oc_activity_.*_delete_form/', $form_id)) {
$form['actions']['submit']['#submit'][] = '_opencase_no_cases_delete_activity_redirect';
$form['actions']['cancel']['#url'] = $form_state->getFormObject()->getEntity()->toUrl();
}
}
function _opencase_no_cases_redirect_to_home($form, &$form_state) {
$form_state->setRedirect('<front>');
}
function _opencase_no_cases_delete_activity_redirect($form, &$form_state) {
$actor_id = $form_state->getFormObject()->getEntity()->actors_involved[0]->target_id;
$form_state->setRedirect('entity.oc_actor.canonical', ['oc_actor' => $actor_id]);
}
/**
* Implements hook_uninstall().
*/
function opencase_no_cases_uninstall() {
$dir = new DirectoryIterator(dirname(__FILE__) . "/config/install");
$configs = [];
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot()) {
$configs[] = str_replace('.yml', '', $fileinfo->getFilename());
}
}
foreach($configs as $config) {
Drupal::configFactory()->getEditable($config)->delete();
}
}

View File

@ -4,8 +4,11 @@
* Contains opencase.module.
*/
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Access\AccessResult;
use Drupal\opencase_cases\Entity\OCCase;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\opencase_cases\Entity\OCCaseProvision;
/**
* Implements hook_element_info_alter().
@ -14,6 +17,18 @@ function opencase_element_info_alter(array &$types) {
$types['datetime']['#process'][] = 'opencase_process_element';
}
function _template_preprocess_entity(&$variables) {
foreach (Element::children($variables['elements']) as $key) {
if (is_extra_field($variables['elements'][$key])) {
$variables['extra_fields'][$key] = $variables['elements'][$key];
} else {
$variables['normal_fields'][$key] = $variables['elements'][$key];
}
}
}
function is_extra_field($element){
return array_key_exists('#field', $element);
}
/**
* Element process callback for datetime fields. Removes the seconds part.
@ -31,6 +46,21 @@ function opencase_process_element($element) {
$element['time']['#attributes']['step'] = 60;
return $element;
}
function opencase_oc_case_provision_insert(OCCaseProvision $case_provision): void {
$case_provision->oc_provider->entity->calculateTotalCases();
}
function opencase_oc_case_provision_delete(OCCaseProvision $case_provision): void {
$case_provision->oc_provider->entity->calculateTotalCases();
}
function opencase_oc_case_provision_update(OCCaseProvision $case_provision): void {
$case_provision->oc_provider->entity->calculateTotalCases();
$case_provision->original->oc_provider->entity->calculateTotalCases();
}
function opencase_oc_case_delete(OCCase $case): void {
$case->deleteCaseProvisions();
$case->deleteActivities();
}
/**
* Implements hook_page_attachments

View File

@ -1,37 +1,49 @@
<?php declare(strict_types = 1);
namespace Drupal\opencase;
use Drupal;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\opencase\Utils;
final class TimeBasedFieldUpdater {
private string $date_field_to_compare;
private string $entity_type;
private array $where;
private string $date_format;
final public function __construct($entity_type, $where = [], $date_field_to_compare, $date_format = 'Y-m-d')
private EntityTypeManagerInterface $entityTypeManager;
private string $date_field;
private Utils $utils;
private string $entity_type;
private string $date_format;
private string $bundle;
final public function __construct(
EntityTypeManagerInterface $entityTypeManager,
Utils $utils,
string $entity_type, string $bundle, string $date_field, string $date_format = 'Y-m-d'
)
{
$this->date_field_to_compare = $date_field_to_compare;
$this->where = $where;
$this->entityTypeManager = $entityTypeManager;
$this->utils = $utils;
$this->date_field = $date_field;
$this->date_format = $date_format;
$this->entity_type = $entity_type;
$this->bundle = $bundle;
}
final public function update($time_elapsed, $old_values, $new_values): void {
$query = Drupal::entityQuery($this->entity_type);
foreach($this->where as $cond_field=>$cond_value) {
$query->condition($cond_field, $cond_value);
final public function update(array $conditions, string $time_elapsed, array $new_values): void {
$query = $this->entityTypeManager->getStorage($this->entity_type)->getQuery();
$conditions[] = [$this->date_field, date($this->date_format, strtotime('-'.$time_elapsed)), "<"];
$conditions[] = ['type', $this->bundle, '='];
foreach ($conditions as $condition) {
$query->condition($condition[0], $condition[1], $condition[2] ?? "=");
}
foreach($old_values as $old_field=>$old_value) {
$query->condition($old_field, $old_value);
}
$query->condition($this->date_field_to_compare, date($this->date_format, strtotime('-'.$time_elapsed)), "<");
foreach($query->execute() as $id) {
$entity = Drupal::entityTypeManager()->getStorage($this->entity_type)->load($id);
foreach($new_values as $new_field=>$new_value) {
$entity->set($new_field, $new_value);
}
$entity->save();
}
$this->updateEntity($id, $new_values);
}
}
}
private function updateEntity(int $entity_id, array $new_values): void {
$entity = $this->entityTypeManager->getStorage($this->entity_type)->load($entity_id);
foreach($new_values as $new_field=>$new_value) {
$entity->$new_field = $new_value;
}
$entity->save();
}
}

42
src/Utils.php Normal file
View File

@ -0,0 +1,42 @@
<?php declare(strict_types =1);
namespace Drupal\opencase;
use \Drupal;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
class Utils {
public function __construct(
EntityTypeManagerInterface $entityTypeManager = null
) {
if ($entityTypeManager == null) {
$entityTypeManager = Drupal::entityTypeManager();
}
$this->entityTypeManager = $entityTypeManager;
}
/**
* Utility: find term by name and vid.
*
* @param string $name
* Term name.
* @param string $vid
* Term vid.
* @return int
* Term id, or 0 if none.
*/
public function getTidByName(string $name, string $vid):int {
if (empty($name) || empty($vid)) {
return 0;
}
$properties = [
'name' => $name,
'vid' => $vid,
];
$terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadByProperties($properties);
$term = reset($terms);
return (int)(!empty($term) ? $term->id() : 0);
}
}

View File

@ -1,46 +0,0 @@
<?php
namespace Drupal\Tests\opencase\Functional;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
/**
* Simple test to ensure that main page loads with module enabled.
*
* @group opencase
*/
class LoadTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['opencase'];
/**
* A user with permission to administer site configuration.
*
* @var \Drupal\user\UserInterface
*/
protected $user;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->user = $this->drupalCreateUser(['administer site configuration']);
$this->drupalLogin($this->user);
}
/**
* Tests that the home page loads with a 200 response.
*/
public function testLoad() {
$this->drupalGet(Url::fromRoute('<front>'));
$this->assertSession()->statusCodeEquals(200);
}
}

View File

@ -0,0 +1,60 @@
<?php declare(strict_types = 1);
namespace Drupal\Tests\opencase\Unit;
use Drupal\Tests\UnitTestCase;
use Drupal\opencase\TimeBasedFieldUpdater;
class TimeBasedFieldUpdaterTest extends UnitTestCase{
function setUp():void {
/** @var \Drupal\opencase\Utils&\PHPUnit\Framework\MockObject\MockObject $utils */
$this->utils = $this->getMockBuilder('\\Drupal\\opencase\\Utils')->disableOriginalConstructor()->getMock();
/** @var \Drupal\core\Entity\EntityTypeManagerInterface&\PHPUnit\Framework\MockObject\MockObject $entityTypeManager */
$this->entityTypeManager = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityTypeManager')->disableOriginalConstructor()->getMock();
$this->storage = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityStorageInterface')->getMock();
$this->query = $this->getMockBuilder('\\Drupal\\Core\\Entity\\Query\\QueryInterface')->getMock();
$this->entityTypeManager->method('getStorage')->willReturn($this->storage);
$this->storage->method('getQuery')->willReturn($this->query);
$this->updater = new TimeBasedFieldUpdater($this->entityTypeManager, $this->utils, 'dummy_entity_type', 'dummy_bundle', 'dummy_date_field');
}
function testFieldIsUpdatedOnEntityReturnedByQuery():void {
$this->query->method('execute')->willReturn([1]);
$this->entity = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityBase')->disableOriginalConstructor()->getMock();
$this->storage->expects($this->once())->method('load')->with(1)->willReturn($this->entity);
$this->updater->update([], '3 months', ['dummy_field' => 4]);
$this->assertEquals($this->entity->dummy_field, 4);
}
function testFieldIsUpdatedOnAllEntitiesReturnedByQuery():void {
$this->query->method('execute')->willReturn([1, 2]);
$this->entity = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityBase')->disableOriginalConstructor()->getMock();
$this->entity2 = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityBase')->disableOriginalConstructor()->getMock();
$this->storage->method('load')->willReturnMap([[1, $this->entity], [2, $this-> entity2]]);
$this->updater->update([], '3 months', ['dummy_field' => 4]);
$this->assertEquals($this->entity->dummy_field, 4);
$this->assertEquals($this->entity2->dummy_field, 4);
}
function testMultipleFieldsAreUpdated(): void {
$this->query->method('execute')->willReturn([1]);
$this->entity = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityBase')->disableOriginalConstructor()->getMock();
$this->storage->expects($this->once())->method('load')->with(1)->willReturn($this->entity);
$this->updater->update([], '3 months', ['dummy_field' => 4, 'dummy_field_2' => 5]);
$this->assertEquals($this->entity->dummy_field, 4);
$this->assertEquals($this->entity->dummy_field_2, 5);
}
function testBundleAndDateAndExtraConditionsAreAllAddedAsQueryConditions(): void {
$this->query->method('execute')->willReturn([]);
$this->query->expects($this->exactly(4))->method('condition')->withConsecutive(
['dummy_field', 'dummy_value', '<'],
['dummy_field_2', 'dummy_value_2', '='],
['dummy_date_field', date('Y-m-d', strtotime('- 3 months')), "<"],
['type', 'dummy_bundle', '=']);
$this->updater->update([['dummy_field', 'dummy_value', '<'], ['dummy_field_2', 'dummy_value_2', '='] ], '3 months', ['dummy_field' => 4]);
}
}

View File

@ -0,0 +1,25 @@
<?php declare(strict_types = 1);
namespace Drupal\Tests\opencase\Unit;
use Drupal\Tests\UnitTestCase;
use Drupal\opencase\Utils;
class UtilsTest extends UnitTestCase{
public function setUp(): void {
/** @var \Drupal\core\Entity\EntityTypeManager&\PHPUnit\Framework\MockObject\MockObject $entityTypeManager */
$this->entityTypeManager = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityTypeManager')->disableOriginalConstructor()->getMock();
$this->utils = new Utils($this->entityTypeManager);
$this->storage = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityStorageInterface')->getMock();
$this->query = $this->getMockBuilder('\\Drupal\\Core\\Entity\\Query\\QueryInterface')->getMock();
$this->entityTypeManager->method('getStorage')->willReturn($this->storage);
}
public function testGetTidByNameGetsTid():void {
$term_entity = $this->getMockBuilder('\\Drupal\\Core\\Entity\\EntityBase')->disableOriginalConstructor()->getMock();
$term_entity->expects($this->once())->method('id')->willReturn('3');
$this->storage->expects($this->once())->method('loadByProperties')->with(['name' => 'foo', 'vid' => 'bar'])
->willReturn([$term_entity]);
$this->assertEquals($this->utils->getTidByName('foo', 'bar'), 3);
}
}