Skip to content

Commit 0af7f9c

Browse files
authored
Merge pull request #174 from Chloe070196/25.02.00_newsletter_consent_koha_integration
25.02.00 newsletter consent koha integration
2 parents a01dafd + 84cd79a commit 0af7f9c

File tree

10 files changed

+155
-47
lines changed

10 files changed

+155
-47
lines changed

code/web/CatalogConnection.php

+4
Original file line numberDiff line numberDiff line change
@@ -1923,4 +1923,8 @@ public function submitLocalIllRequest(User $patron, LocalIllForm $localIllForm):
19231923
];
19241924
}
19251925
}
1926+
1927+
public function hasIlsConsentSupport(): bool {
1928+
return $this->driver->hasIlsConsentSupport();
1929+
}
19261930
}

code/web/Drivers/AbstractIlsDriver.php

+4
Original file line numberDiff line numberDiff line change
@@ -917,4 +917,8 @@ public function loadLibraries() : array {
917917
'message' => 'This functionality has not been implemented for this ILS',
918918
];
919919
}
920+
921+
public function hasIlsConsentSupport(): bool {
922+
return false;
923+
}
920924
}

code/web/Drivers/Koha.php

+67-14
Original file line numberDiff line numberDiff line change
@@ -4122,7 +4122,7 @@ function getSelfRegistrationFields($type = 'selfReg') {
41224122
}
41234123
}
41244124

4125-
if($library->ilsConsentEnabled) {
4125+
if($library->ilsConsentEnabled && $this->areAnyConsentPluginsEnabled()) {
41264126
$fields['privacySection'] = $this->getSelfRegistrationFormPrivacySection();
41274127
}
41284128

@@ -4507,19 +4507,25 @@ function selfRegister(): array {
45074507

45084508
$result = $this->postSelfRegistrationToKoha($postVariables);
45094509

4510-
if ($result) {
4511-
$consentTypes = $this->getConsentTypes();
4512-
if (!empty($consentTypes)) {
4513-
foreach ($consentTypes as $key => $consentType) {
4514-
if (strtolower($key) == 'gdpr_processing') {
4515-
continue;
4516-
}
4517-
$this->updatePatronConsent($result['patronId'], strtolower($key), isset($_REQUEST['privacy_consent_' . strtolower($key)]));
4510+
if (!$library->ilsConsentEnabled) {
4511+
return $result;
4512+
}
4513+
4514+
if (!$this->areAnyConsentPluginsEnabled()) {
4515+
return $result;
4516+
}
4517+
4518+
$consentTypes = $this->getConsentTypes();
4519+
if (!empty($consentTypes)) {
4520+
foreach ($consentTypes as $key => $consentType) {
4521+
if (strtolower($key) == 'gdpr_processing') {
4522+
continue;
45184523
}
4524+
$this->updatePatronConsent($result['patronId'], strtolower($key), isset($_REQUEST['privacy_consent_' . strtolower($key)]));
45194525
}
45204526
}
4521-
45224527
}
4528+
45234529
return $result;
45244530
}
45254531

@@ -6786,6 +6792,10 @@ public function getPluginStatus(string $pluginName) {
67866792
/** @noinspection SqlResolve */
67876793
$sql = "SELECT * FROM plugin_data WHERE plugin_class LIKE '%$pluginName';";
67886794
$results = mysqli_query($this->dbConnection, $sql);
6795+
$plugin = [
6796+
'installed' => 0,
6797+
'enabled' => 0,
6798+
];
67896799

67906800
if ($results !== false) {
67916801
while ($curRow = $results->fetch_assoc()) {
@@ -8396,6 +8406,44 @@ protected function getUserMessageTranslation($code, User $patron): array {
83968406
return $result;
83978407
}
83988408

8409+
public function areAnyConsentPluginsEnabled(): bool {
8410+
global $library;
8411+
$anyConsentPluginsEnabled = true;
8412+
$consentPluginNames = $this->getPluginNamesByMethodName('patron_consent_type');
8413+
foreach($consentPluginNames as $pluginName) {
8414+
$pluginStatus = $this->getPluginStatus($pluginName);
8415+
if ($library->ilsConsentEnabled && !$pluginStatus['enabled']) {
8416+
global $logger;
8417+
$statusDescription = $pluginStatus['installed'] ? 'disabled' : 'not installed';
8418+
$logger->log("Consent options could not be presented or recorded because the $pluginName plugin is $statusDescription", Logger::LOG_ERROR);
8419+
$anyConsentPluginsEnabled = false;
8420+
break;
8421+
}
8422+
}
8423+
return $anyConsentPluginsEnabled;
8424+
}
8425+
8426+
public function getPluginNamesByMethodName(string $methodName): array|bool {
8427+
$this->initDatabaseConnection();
8428+
/** @noinspection SqlResolve */
8429+
$sql = 'SELECT plugin_class FROM plugin_methods WHERE plugin_method = "' . $methodName . '"';
8430+
$results = mysqli_query($this->dbConnection, $sql);
8431+
$pluginNames = [];
8432+
8433+
if ($results === false) {
8434+
global $logger;
8435+
$logger->log("Error loading plugins " . mysqli_error($this->dbConnection), Logger::LOG_ERROR);
8436+
return false;
8437+
}
8438+
while ($curRow = $results->fetch_assoc()) {
8439+
$pluginNames[] = $curRow['plugin_class'];
8440+
}
8441+
$results->close();
8442+
8443+
return $pluginNames;
8444+
}
8445+
8446+
83998447
public function getFormattedConsentTypes(): array {
84008448
$consentTypes = $this->getConsentTypes();
84018449
if (empty($consentTypes)) {
@@ -8412,6 +8460,7 @@ public function getFormattedConsentTypes(): array {
84128460
'allCapsCode' => $key,
84138461
'label' => $consentType['title']['en'],
84148462
'description' => $consentType['description']['en'],
8463+
'actionConsentedTo' => $consentType['title']['en'] == 'Newsletter' ? "receiving our Newsletter" : $consentType['title']['en'],
84158464
];
84168465
}
84178466
return $formattedConsentTypes;
@@ -8453,13 +8502,13 @@ public function getSelfRegistrationFormPrivacySection(): array {
84538502
return $privacySection;
84548503
}
84558504

8456-
public function updatePatronConsent(int $patronIlsId, string $consentType, $consentEnabled = false) {
8505+
public function updatePatronConsent(int $patronIlsId, string $consentType, $consentEnabled = false): array {
84578506
$result = ['success' => false,];
84588507

84598508
$oauthToken = $this->getOAuthToken();
84608509
if (!$oauthToken) {
84618510
$result['message'] = translate([
8462-
'text' => 'Unable to authenticate with the ILS. Please try again later or contact the library.',
8511+
'text' => 'Unable to authenticate with the ILS. Please try again later or contact the library.',
84638512
'isPublicFacing' => true,
84648513
]);
84658514
return $result;
@@ -8502,7 +8551,7 @@ public function updatePatronConsent(int $patronIlsId, string $consentType, $cons
85028551
return $result;
85038552
}
85048553

8505-
public function getPatronConsents($patron) {
8554+
public function getPatronConsents($patron): array {
85068555
$oauthToken = $this->getOAuthToken();
85078556
if (!$oauthToken) {
85088557
$result['message'] = translate([
@@ -8545,7 +8594,7 @@ public function getPatronConsents($patron) {
85458594

85468595
}
85478596

8548-
private function getConsentTypes() {
8597+
private function getConsentTypes(): array {
85498598
$oauthToken = $this->getOAuthToken();
85508599
if (!$oauthToken) {
85518600
return translate([
@@ -8585,4 +8634,8 @@ private function getConsentTypes() {
85858634
]);
85868635
}
85878636
}
8637+
8638+
public function hasIlsConsentSupport(): bool {
8639+
return true;
8640+
}
85888641
}

code/web/interface/themes/responsive/MyAccount/myPrivacySettings.tpl

+2-1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
<input type="hidden" name="patronId" value={$profile->id|escape}>
120120
{foreach $consentTypes as $consentType}
121121
<section id="{$consentType['lowercaseCode']}ConsentSection">
122+
<input type="hidden" name="updateScopeSection" value="{$consentType['lowercaseCode']}">
122123
{$consentCode = $consentType['capitalisedCode']}
123124
<h2>{translate text={$consentType['label']} isPublicFacing=true}</h2>
124125
<div class="form-group #propertyRow" style="margin-bottom:10px;">
@@ -133,7 +134,7 @@
133134
</div>
134135
</div>
135136
<div id="my{$consentCode}ConsentExplanation" style="display:none; margin-top: 10px;">
136-
{translate text="By checking this box you are giving your consent to our {$consentType['label']}. Aspen Discovery will send your consent information to Koha, where it will be stored. You can return to this page to update your consent at any point."}
137+
{translate text="By checking this box you are giving your consent to {$consentType['actionConsentedTo']}. You can return to this page to update your consent at any point."}
137138
</div>
138139
</section>
139140
{/foreach}

code/web/release_notes/25.02.00.MD

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@
2525

2626
- For libraries that use Koha as their ILS, and use the koha-plugin-newsletter-consent plugin
2727
- Administrator with the permission to edit library settings will be able to toggle on/off the 'Enable ILS-issued consents' setting under the 'Data Protection Regulations' section. (*CZ*)
28+
- if the Koha plugin has not been installed and enabled in Koha, then the 'Enable ILS-issued consents' setting will not appear as it requires the plugin to be installed and enabled. (*CZ*)
29+
- if the Koha plugin is uninstalled or disabled in Koha while 'Enable ILS-issued consents' is toggled on, 'Enable ILS-issued consents' will still display. (*CZ*)
2830
- If 'Enable ILS-issued consents' is enabled:
2931
- the 'Privacy Settings' options will appear in patron side menus. (*CZ*)
3032
- In the self-registration form, under a ‘Privacy’ section, patrons need to see information about the consent types set by their library in Koha. For example, they may be given the opportunity to receive the library’s newsletter. (*CZ*)
3133
- Patrons will be able to choose to opt in, which implies that consent is not assumed by default. (*CZ*)
3234
- Patrons will be able to submit their consent along with their registration form. (*CZ*)
3335
- Patrons will be sent to Koha, where it is stored. (*CZ*)
3436
- Patrons will be able to view and change their consent information (as retrieved from Koha) at any point through the ‘Your Account > Privacy Settings ’ section. (*CZ*)
35-
37+
- If ILS consent is enabled in the Aspen settings, but the Koha plugin is disabled or uninstalled, patron will see an informative message in 'Privacy Settings'. (*CZ*)
3638
//pedro
3739

3840
// lucas

code/web/services/Admin/Libraries.php

+22
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ function getObjectStructure($context = ''): array {
7070
if (!UserAccount::userHasPermission('Administer All Libraries')) {
7171
unset($objectStructure['isDefault']);
7272
}
73+
global $library;
74+
$accountProfile = $library->getAccountProfile();
75+
if (!$accountProfile || empty($accountProfile) || !isset($accountProfile->driver)) {
76+
return $objectStructure;
77+
}
78+
79+
// if 'Enable ILS-issued consents' is not already toggled on, prevent administrators from seeing it (and toggling it on) if no consent plugins are installed and enabled in Koha
80+
$catalogDriver = CatalogFactory::getCatalogConnectionInstance(trim($accountProfile->driver), $accountProfile);
81+
$consentPluginNames = $catalogDriver->getPluginNamesByMethodName('patron_consent_type');
82+
$anyConsentPluginsEnabled = false;
83+
foreach($consentPluginNames as $pluginName) {
84+
$pluginStatus = $catalogDriver->getPluginStatus($pluginName);
85+
if ($pluginStatus['enabled']) {
86+
$anyConsentPluginsEnabled = true;
87+
break;
88+
}
89+
}
90+
91+
if($catalogDriver->hasIlsConsentSupport() && !$anyConsentPluginsEnabled && $library->ilsConsentEnabled == 0) {
92+
unset($objectStructure['dataProtectionRegulations']['properties']['ilsConsentEnabled']);
93+
}
94+
7395
return $objectStructure;
7496
}
7597

code/web/services/MyAccount/MyPrivacySettings.php

+46-15
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,48 @@
33
require_once ROOT_DIR . '/services/MyAccount/MyAccount.php';
44

55
class MyAccount_MyPrivacySettings extends MyAccount {
6-
function launch() {
6+
function launch(): void {
77
global $interface;
88
global $library;
99

1010
if (!UserAccount::isLoggedIn()) {
1111
$interface->assign('error', 'You must be logged in to access the Administration Interface');
12-
}
12+
}
1313

14-
// Do not lauch this page if there is nothing to show
14+
// Handles patrons attempting to access the page directly through the URL when the 'Privacy Settings' link is disabled and does not show
1515
if (!$library->ilsConsentEnabled && !$library->cookieStorageConsent) {
1616
header("Location: " . '/MyAccount');
1717
}
18+
19+
$user = UserAccount::getLoggedInUser();
20+
$linkedUsers = $user->getLinkedUsers();
21+
$driver = $user->getCatalogDriver();
22+
23+
$consentPluginNames = $driver->getPluginNamesByMethodName('patron_consent_type');
24+
$anyConsentPluginsEnabled = false;
25+
26+
foreach($consentPluginNames as $pluginName) {
27+
$pluginStatus = $driver->getPluginStatus($pluginName);
28+
if ($library->ilsConsentEnabled && !$pluginStatus['enabled']) {
29+
global $logger;
30+
$statusDescription = $pluginStatus['installed'] ? 'disabled' : 'not installed';
31+
$logger->log("Patrons Privacy Settings: Patrons cannot view and update their consents as the $pluginName plugin is $statusDescription", Logger::LOG_ERROR);
32+
33+
$messages = [];
34+
$messages[] = [
35+
'message' => 'Other consent options are enabled but cannot be shown here due to a technical issue. Please contact your library.',
36+
'messageStyle' => 'info',
37+
];
38+
$interface->assign('ilsMessages', $messages);
39+
continue;
40+
}
41+
$anyConsentPluginsEnabled = true;
42+
}
1843

19-
$interface->assign('ilsConsentEnabled', $library->ilsConsentEnabled);
44+
$interface->assign('ilsConsentEnabled', $library->ilsConsentEnabled && $anyConsentPluginsEnabled);
2045
$interface->assign('cookieConsentEnabled', $library->cookieStorageConsent);
2146

2247
//Determine which user we are showing/updating settings for
23-
$user = UserAccount::getLoggedInUser();
24-
$linkedUsers = $user->getLinkedUsers();
2548
$patronId = isset($_REQUEST['patronId']) ? $_REQUEST['patronId'] : $user->id;
2649
/** @var $patron */
2750
$patronRefferedTo = $user->getUserReferredTo($patronId);
@@ -40,11 +63,10 @@ function launch() {
4063
}
4164

4265
$action = $this->assignAction();
43-
$driver = $user->getCatalogDriver();
44-
$consentTypes = $library->ilsConsentEnabled ? $driver->getFormattedConsentTypes() : null;
66+
$consentTypes = $library->ilsConsentEnabled && $anyConsentPluginsEnabled ? $driver->getFormattedConsentTypes() : null;
4567

4668
if ($action == 'save') {
47-
$this->updatePrivacySettings($user, $patronRefferedTo, $driver, $library->ilsConsentEnabled, $consentTypes);
69+
$this->updatePrivacySettings($user, $patronRefferedTo, $driver, $anyConsentPluginsEnabled, $consentTypes);
4870
session_write_close();
4971
$actionUrl = '/MyAccount/MyPrivacySettings' . ($patronRefferedTo->id == $user->id ? '': '?patronId=' . $patronId);
5072
header("Location: " . $actionUrl);
@@ -60,7 +82,7 @@ function launch() {
6082
$user->updateMessageIsError = 0;
6183
}
6284

63-
if (!$library->ilsConsentEnabled) {
85+
if (!$library->ilsConsentEnabled || !$anyConsentPluginsEnabled) {
6486
$this->display('myPrivacySettings.tpl', 'My Privacy Settings');
6587
return;
6688
}
@@ -93,7 +115,7 @@ private function assignAction(): string {
93115
return "";
94116
}
95117

96-
private function updatePrivacySettings($user, $patronRefferedTo, $driver, $ilsConsentEnabled = null, $consentTypes = null): void {
118+
private function updatePrivacySettings($user, $patronRefferedTo, $driver, $anyConsentPluginsEnabled = null, $consentTypes = null): void {
97119
if ($_REQUEST['patronId'] != $user->id) {
98120
$user->updateMessage = translate([
99121
'text' => 'Wrong account credentials, please try again.',
@@ -111,10 +133,19 @@ private function updatePrivacySettings($user, $patronRefferedTo, $driver, $ilsCo
111133
}
112134

113135
if ($_POST['updateScope'] === 'userILSIssuedConsent') {
114-
if ($ilsConsentEnabled) {
115-
foreach ($consentTypes as $consentType) {
116-
$result = $driver->updatePatronConsent($patronRefferedTo->unique_ils_id, $consentType['allCapsCode'], isset($_POST['userNewsletter']));
117-
}
136+
$consentTypeName = $_REQUEST['updateScopeSection'];
137+
if (!$anyConsentPluginsEnabled) {
138+
global $logger;
139+
$logger->log("Patrons Privacy Settings: Patron with id $patronRefferedTo->id could not update their $consentTypeName consent", Logger::LOG_ERROR);
140+
141+
$user->updateMessage = translate([
142+
'text' => 'Could not update consent due to a technical issue. Please contact your library',
143+
'isPublicFacing' => true,
144+
]);
145+
$user->updateMessageIsError = true;
146+
}
147+
foreach ($consentTypes as $consentType) {
148+
$result = $driver->updatePatronConsent($patronRefferedTo->unique_ils_id, $consentType['allCapsCode'], isset($_POST['userNewsletter']));
118149
}
119150
}
120151
if (isset($result['message'])) {

code/web/sys/DBMaintenance/version_updates/25.02.00.php

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ function getUpdates25_02_00(): array {
2424
//alexander - PTFS-Europe
2525

2626
//chloe - PTFS-Europe
27+
'save_library_ils_consent_feature_toggle_value' => [
28+
'title' => 'Save Library ILS Consent Feature Toggle Value',
29+
'description' => 'Allows to record whether a library has enabled the ILS Consent feature or not',
30+
'continueOnError' => false,
31+
'sql' => ['ALTER TABLE library ADD COLUMN ilsConsentEnabled tinyint(1) DEFAULT 0'],
32+
], //'save_library_ils_consent_feature_toggle_value'
2733

2834
//James Staub - Nashville Public Library
2935

code/web/sys/LibraryLocation/Library.php

+1-15
Original file line numberDiff line numberDiff line change
@@ -912,20 +912,6 @@ static function getObjectStructure($context = ''): array {
912912
$validCardRenewalOptions[3] = 'Quipu eRenewal';
913913
}
914914

915-
// prevent administrators from enabling the ILS consent integration if their ILS does not allow for it
916-
$driverAllowsForIlsConsentTypes = true;
917-
if (
918-
$catalog == null ||
919-
$catalog->driver == null ||
920-
!method_exists($catalog->driver, 'getConsentTypes') ||
921-
!method_exists($catalog->driver, 'getFormattedConsentTypes') ||
922-
!method_exists($catalog->driver, 'getPatronConsents') ||
923-
!method_exists($catalog->driver, 'getSelfRegistrationFormPrivacySection') ||
924-
!method_exists($catalog->driver, 'updatePatronConsent')
925-
) {
926-
$driverAllowsForIlsConsentTypes = false;
927-
}
928-
929915
/** @noinspection HtmlRequiredAltAttribute */
930916
/** @noinspection RequiredAttributes */
931917
$structure = [
@@ -4183,7 +4169,7 @@ static function getObjectStructure($context = ''): array {
41834169
if (!array_key_exists('Single sign-on', $enabledModules)) {
41844170
unset($structure['ssoSection']);
41854171
}
4186-
if (!$driverAllowsForIlsConsentTypes) {
4172+
if (!$catalog->hasIlsConsentSupport()) {
41874173
unset($structure['dataProtectionRegulations']['properties']['ilsConsentEnabled']);
41884174
}
41894175

install/aspen.sql

-1
Original file line numberDiff line numberDiff line change
@@ -2779,7 +2779,6 @@ CREATE TABLE `library` (
27792779
`eCommerceFee` varchar(11) DEFAULT '0',
27802780
`eCommerceTerms` mediumtext DEFAULT NULL,
27812781
`cookieStorageConsent` tinyint(1) DEFAULT 0,
2782-
`ilsConsentEnabled` tinyint(1) DEFAULT 0,
27832782
`cookiePolicyHTML` text DEFAULT NULL,
27842783
`openArchivesFacetSettingId` int(11) DEFAULT 1,
27852784
`websiteIndexingFacetSettingId` int(11) DEFAULT 1,

0 commit comments

Comments
 (0)