Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

use Civi\Core\Event\GenericHookEvent;
use Civi\Core\Service\AutoService;

/**
* Provides ability to prefill afform fields from encrypted token.
*
* @service goonjcustom.afform_prefill
*/
class CRM_Goonjcustom_AfformFieldPrefillService extends AutoService {

public static function preprocess(\Civi\Angular\Manager $angular) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid static methods for better testability

Static methods make unit testing difficult and violate dependency injection principles. Consider making this an instance method instead.

- public static function preprocess(\Civi\Angular\Manager $angular) {
+ public function preprocess(\Civi\Angular\Manager $angular) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static function preprocess(\Civi\Angular\Manager $angular) {
public function preprocess(\Civi\Angular\Manager $angular) {
🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/CRM/Goonjcustom/AfformFieldPrefillService.php
at line 13, the preprocess method is declared static, which hinders unit testing
and dependency injection. Change the method from static to an instance method by
removing the static keyword and update all calls to this method accordingly to
use an instance of the class instead of calling it statically.

Civi::log()->debug('[AfformPrefill] Preprocess started.');

$request = \CRM_Utils_Request::retrieve('token', 'String', CRM_Core_DAO::$_nullObject, FALSE, NULL, 'GET');

if (!$request) {
Civi::log()->warning('[AfformPrefill] No token found in URL.');
return;
}

try {
$decrypted = CRM_Utils_Crypt::decrypt($request);
$data = json_decode($decrypted, true);
Civi::log()->debug('[AfformPrefill] Token decrypted: ' . print_r($data, true));
} catch (\Exception $e) {
Civi::log()->error('[AfformPrefill] Token decryption failed: ' . $e->getMessage());
return;
}

if (!is_array($data)) {
Civi::log()->error('[AfformPrefill] Decrypted token is not valid JSON.');
return;
}

$changeSet = \Civi\Angular\ChangeSet::create('injectPrefillValues')
->alterHtml(';\\.aff\\.html$;', function ($doc, $path) use ($data) {
Civi::log()->debug("[AfformPrefill] Altering HTML template: {$path}");

foreach (pq('af-field', $doc) as $afField) {
$fieldName = $afField->getAttribute('name');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Sanitize field names to prevent potential attacks

Field names are used directly without validation, which could lead to security issues if malicious field names are processed.

$fieldName = $afField->getAttribute('name');

if (!$fieldName) {
  continue;
}

+// Validate field name format
+if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_\.]*$/', $fieldName)) {
+  Civi::log()->warning("[AfformPrefill] Invalid field name format: {$fieldName}");
+  continue;
+}

if (array_key_exists($fieldName, $data)) {

Also applies to: 48-48

🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/CRM/Goonjcustom/AfformFieldPrefillService.php
at lines 42 and 48, the field names retrieved from getAttribute('name') are used
without sanitization, posing a security risk. To fix this, sanitize the field
names by validating and cleaning the input to allow only expected characters
(e.g., alphanumeric and underscores) before using them. This prevents potential
injection or other attacks from malicious field names.


if (!$fieldName) {
continue;
}

if (array_key_exists($fieldName, $data)) {
$fieldDefn = self::getFieldDefinition($afField);

if (!$fieldDefn) {
Civi::log()->warning("[AfformPrefill] No field definition for: {$fieldName}");
continue;
}

$fieldDefn['afform_default'] = $data[$fieldName];
$fieldDefn['readonly'] = true;

pq($afField)->attr('defn', htmlspecialchars(\CRM_Utils_JS::writeObject($fieldDefn), ENT_COMPAT));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential XSS vulnerability in field definition handling

The field definition is serialized and inserted into HTML attributes without proper validation of the input data values, which could lead to XSS attacks.

+// Sanitize the field value before setting
+$sanitizedValue = is_string($data[$fieldName]) ? 
+  htmlspecialchars($data[$fieldName], ENT_QUOTES, 'UTF-8') : 
+  $data[$fieldName];
+
+$fieldDefn['afform_default'] = $sanitizedValue;
-$fieldDefn['afform_default'] = $data[$fieldName];
$fieldDefn['readonly'] = true;

pq($afField)->attr('defn', htmlspecialchars(\CRM_Utils_JS::writeObject($fieldDefn), ENT_COMPAT));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pq($afField)->attr('defn', htmlspecialchars(\CRM_Utils_JS::writeObject($fieldDefn), ENT_COMPAT));
// Sanitize the field value before setting
$sanitizedValue = is_string($data[$fieldName])
? htmlspecialchars($data[$fieldName], ENT_QUOTES, 'UTF-8')
: $data[$fieldName];
$fieldDefn['afform_default'] = $sanitizedValue;
$fieldDefn['readonly'] = true;
pq($afField)
->attr('defn', htmlspecialchars(\CRM_Utils_JS::writeObject($fieldDefn), ENT_COMPAT));
🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/CRM/Goonjcustom/AfformFieldPrefillService.php
at line 59, the field definition is serialized and inserted into an HTML
attribute without sufficient validation, risking XSS vulnerabilities. To fix
this, ensure that all data within $fieldDefn is properly sanitized or escaped
before serialization, and consider using a safer encoding method that prevents
injection of malicious scripts when outputting into HTML attributes.

Civi::log()->info("[AfformPrefill] Prefilled field '{$fieldName}' with value: " . json_encode($data[$fieldName]));
} else {
Civi::log()->debug("[AfformPrefill] Field '{$fieldName}' not in token data, skipping.");
}
}
});

$angular->add($changeSet);
Civi::log()->debug('[AfformPrefill] ChangeSet injected successfully.');
}
Comment on lines +37 to +69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Break down the monolithic preprocess method

This method violates the Single Responsibility Principle by handling token processing, template modification, and field updates all in one place. Consider extracting smaller, focused methods.

public function preprocess(\Civi\Angular\Manager $angular) {
-  // All the current logic here
+  $data = $this->processToken();
+  if (!$data) {
+    return;
+  }
+  
+  $changeSet = $this->createFieldPrefillChangeSet($data);
+  $angular->add($changeSet);
}

+private function processToken() {
+  // Token retrieval and decryption logic
+}

+private function createFieldPrefillChangeSet($data) {
+  // ChangeSet creation and field processing logic
+}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/CRM/Goonjcustom/AfformFieldPrefillService.php
between lines 37 and 69, the current method is handling multiple
responsibilities including token processing, HTML template modification, and
field updates, which violates the Single Responsibility Principle. Refactor by
extracting distinct smaller methods for each responsibility: one for processing
tokens and preparing data, another for modifying the HTML template, and a third
for updating individual fields. Then call these methods sequentially to keep the
main method clean and focused.


public static function getFieldDefinition($afField) {
$existingFieldDefn = trim(pq($afField)->attr('defn') ?: '');

if ($existingFieldDefn && $existingFieldDefn[0] !== '{') {
return NULL;
}

return $existingFieldDefn ? \CRM_Utils_JS::getRawProps($existingFieldDefn) : [];
}
Comment on lines +71 to +79

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for field definition parsing

The CRM_Utils_JS::getRawProps() call could throw exceptions that aren't handled, potentially breaking the entire prefill process.

-  return $existingFieldDefn ? \CRM_Utils_JS::getRawProps($existingFieldDefn) : [];
+  if (!$existingFieldDefn) {
+    return [];
+  }
+  
+  try {
+    return \CRM_Utils_JS::getRawProps($existingFieldDefn);
+  } catch (\Exception $e) {
+    Civi::log()->error('[AfformPrefill] Failed to parse field definition: ' . $e->getMessage());
+    return [];
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static function getFieldDefinition($afField) {
$existingFieldDefn = trim(pq($afField)->attr('defn') ?: '');
if ($existingFieldDefn && $existingFieldDefn[0] !== '{') {
return NULL;
}
return $existingFieldDefn ? \CRM_Utils_JS::getRawProps($existingFieldDefn) : [];
}
public static function getFieldDefinition($afField) {
$existingFieldDefn = trim(pq($afField)->attr('defn') ?: '');
if ($existingFieldDefn && $existingFieldDefn[0] !== '{') {
return NULL;
}
if (!$existingFieldDefn) {
return [];
}
try {
return \CRM_Utils_JS::getRawProps($existingFieldDefn);
} catch (\Exception $e) {
Civi::log()->error('[AfformPrefill] Failed to parse field definition: ' . $e->getMessage());
return [];
}
}
🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/CRM/Goonjcustom/AfformFieldPrefillService.php
around lines 71 to 79, the call to CRM_Utils_JS::getRawProps() may throw
exceptions that are currently unhandled. Wrap this call in a try-catch block to
catch any exceptions, and handle them gracefully by returning an empty array or
null to prevent the prefill process from breaking.

}
Original file line number Diff line number Diff line change
Expand Up @@ -95,36 +95,47 @@ public function setDefaultValues() {
*
* @return void
*/
public function generateLinks($contactId): void {
$organization = $this->_organization;
$contact = $this->_contact;

$nameOfInstitution = $organization['display_name'];
$address = $organization['address_primary.street_address'];
$pocEmail = $contact['email.email'];
$pocContactNumber = $contact['phone.phone'];

// Generate dropping center links.
$links = [
[
'label' => 'Vehicle Dispatch',
'url' => self::createUrl(
'/institution-dropping-center-vehicle-dispatch',
"Camp_Vehicle_Dispatch.Institution_Dropping_Center={$this->_institutionDroppingCenterId}" .
"&Eck_Collection_Camp1={$this->_institutionDroppingCenterId}" .
"&Camp_Vehicle_Dispatch.To_which_PU_Center_material_is_being_sent={$this->_processingCenterId}" .
"&Camp_Vehicle_Dispatch.Filled_by={$contactId}" .
"&Camp_Institution_Data.Name_of_the_institution={$nameOfInstitution}" .
"&Camp_Institution_Data.Address=" . urlencode($address) .
"&Camp_Institution_Data.Email={$pocEmail}" .
"&Camp_Institution_Data.Contact_Number={$pocContactNumber}",
$contactId
),
],
];

$this->assign('institutionDroppingCenterLinks', $links);
}
public function generateLinks($contactId): void {
$organization = $this->_organization;
$contact = $this->_contact;

$nameOfInstitution = $organization['display_name'];
$address = $organization['address_primary.street_address'];
$pocEmail = $contact['email.email'];
$pocContactNumber = $contact['phone.phone'];

// Create dispatch data array
$dispatchData = [
'Camp_Vehicle_Dispatch.Institution_Dropping_Center' => $this->_institutionDroppingCenterId,
'Camp_Vehicle_Dispatch.Filled_by' => $contactId,
'Camp_Vehicle_Dispatch.To_which_PU_Center_material_is_being_sent' => $this->_processingCenterId,
'Camp_Vehicle_Dispatch.Goonj_Office_Name' => '', // optional if needed
'Eck_Collection_Camp1' => $this->_institutionDroppingCenterId,
'id' => $this->_institutionDroppingCenterId,
'Camp_Institution_Data.Name_of_the_institution' => $nameOfInstitution,
'Camp_Institution_Data.Address' => $address,
'Camp_Institution_Data.Email' => $pocEmail,
'Camp_Institution_Data.Contact_Number' => $pocContactNumber,
];

// Encrypt token
$json = json_encode($dispatchData);
$encryptedToken = \CRM_Utils_Crypt::encrypt($json);
$tokenParam = 'token=' . urlencode($encryptedToken);

// Authenticated token
$authUrl = self::createUrl('/institution-dropping-center-vehicle-dispatch', $tokenParam, $contactId);

// Assign link
$links = [
[
'label' => 'Vehicle Dispatch',
'url' => $authUrl,
],
];

$this->assign('institutionDroppingCenterLinks', $links);
}

/**
* Generate an authenticated URL for viewing this form.
Expand Down Expand Up @@ -153,7 +164,7 @@ public static function createUrl($path, $params, $contactId): string {
$params = "{$params}&_authx={$bearerToken}&_authxSes=1";
// $url = \CRM_Utils_System::url($path, $params, TRUE, NULL, FALSE, TRUE);
$config = CRM_Core_Config::singleton();
$url = $config->userFrameworkBaseURL . $path . '#?' . $params;
$url = $config->userFrameworkBaseURL . $path . '?' . $params;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify URL construction change doesn't break CiviCRM Formbuilder

The URL construction was changed from hash fragment (#?) to standard query string (?). According to retrieved learnings, #? is an intentional method for passing values to CiviCRM's Formbuilder.

Please verify that this change doesn't break the form functionality. If the forms require the hash fragment format, consider reverting this change.


🏁 Script executed:

#!/bin/bash
# Search for other instances of URL construction for CiviCRM forms
rg -A 3 -B 3 "userFrameworkBaseURL.*\?" --type php

# Check for any documentation or comments about URL format requirements
rg -i "formbuilder.*url|url.*formbuilder|#\?" --type php

Length of output: 34790


Revert to using hash-fragment (#?) for CiviCRM Formbuilder links

The rest of our custom Form link generators consistently use #? to pass parameters into CiviCRM’s Formbuilder. Switching this one to a standard query (?) will almost certainly break the form loading logic in WordPress.

Please update:

• File:
wp-content/civi-extensions/goonjcustom/CRM/Goonjcustom/Form/InstitutionDroppingCenterLinks.php
Line: 167

• Change back from:

$url = $config->userFrameworkBaseURL . $path . '?' . $params;

to:

$url = $config->userFrameworkBaseURL . $path . '#?' . $params;

This will align it with all other …Links.php classes (e.g. UrbanVisitLinks, EventsLinks, CollectionCampLinks, etc.) and preserve the intended Formbuilder behavior.

🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/CRM/Goonjcustom/Form/InstitutionDroppingCenterLinks.php
at line 167, revert the URL construction to use a hash-fragment (#?) instead of
a query (?). Change the line from concatenating '?' before $params to
concatenating '#?' to ensure consistency with other Form link generators and
maintain proper Formbuilder functionality in WordPress.


return $url;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,32 +543,52 @@ public static function processDispatchEmail(string $op, string $objectName, $obj
*
*/
public static function sendDispatchEmail($email, $initiatorName, $droppingCenterId, $contactId, $goonjOffice, $goonjOfficeName) {
$homeUrl = \CRM_Utils_System::baseCMSURL();
$vehicleDispatchFormUrl = $homeUrl . '/vehicle-dispatch/#?Camp_Vehicle_Dispatch.Dropping_Center=' . $droppingCenterId . '&Camp_Vehicle_Dispatch.Filled_by=' . $contactId . '&Camp_Vehicle_Dispatch.To_which_PU_Center_material_is_being_sent=' . $goonjOffice . '&Camp_Vehicle_Dispatch.Goonj_Office_Name=' . $goonjOfficeName . '&Eck_Collection_Camp1=' . $droppingCenterId;
$homeUrl = \CRM_Utils_System::baseCMSURL();

// Step 1: Gather data
$dispatchData = [
'Camp_Vehicle_Dispatch.Dropping_Center' => $droppingCenterId,
'Camp_Vehicle_Dispatch.Filled_by' => $contactId,
'Camp_Vehicle_Dispatch.To_which_PU_Center_material_is_being_sent' => $goonjOffice,
'Camp_Vehicle_Dispatch.Goonj_Office_Name' => $goonjOfficeName,
'Eck_Collection_Camp1' => $droppingCenterId,
'id' => $droppingCenterId,
'Dropping_Centre.Where_do_you_wish_to_open_dropping_center_Address_' => 'Hardcoded test address for now'
];

// Step 2: Convert to JSON and encrypt
$json = json_encode($dispatchData);
$token = \CRM_Utils_Crypt::encrypt($json);

// Step 3: Generate encrypted URL
$vehicleDispatchFormUrl = $homeUrl . '/vehicle-dispatch/?token=' . urlencode($token);

$emailHtml = "
<html>
<body>
// Step 4: Compose HTML email
$emailHtml = "
<html>
<body>
<p>Dear {$initiatorName},</p>
<p>Thank you so much for your invaluable efforts in running the Goonj Dropping Center.
Your dedication plays a crucial role in our work, and we deeply appreciate your continued support.</p>
<p>Please fill out this Dispatch Form – <a href='{$vehicleDispatchFormUrl}'>Link</a> once the vehicle is loaded and ready to head to Goonj’s processing center.
This will help us to verify and acknowledge the materials as soon as they arrive.</p>
<p>We truly appreciate your cooperation and continued commitment to our cause.</p>
<p>Warm Regards,<br>Team Goonj..</p>
</body>
</html>
";
$from = HelperService::getDefaultFromEmail();
$mailParams = [
'subject' => 'Kindly fill the Dispatch Form for Material Pickup',
'from' => $from,
'toEmail' => $email,
'html' => $emailHtml,
];
</body>
</html>
";
Comment on lines +567 to +579

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Extract email HTML to a template file

Inline HTML violates the separation of concerns principle and makes the code harder to maintain. Consider moving this to a Smarty template for better maintainability and localization support.

Create a new template file templates/CRM/Goonjcustom/Email/DispatchForm.tpl and use CiviCRM's template system:

-  // Step 4: Compose HTML email
-  $emailHtml = "
-  <html>
-  <body>
-    <p>Dear {$initiatorName},</p>
-    <p>Thank you so much for your invaluable efforts in running the Goonj Dropping Center. 
-    Your dedication plays a crucial role in our work, and we deeply appreciate your continued support.</p>
-    <p>Please fill out this Dispatch Form – <a href='{$vehicleDispatchFormUrl}'>Link</a> once the vehicle is loaded and ready to head to Goonj's processing center. 
-    This will help us to verify and acknowledge the materials as soon as they arrive.</p>
-    <p>We truly appreciate your cooperation and continued commitment to our cause.</p>
-    <p>Warm Regards,<br>Team Goonj..</p>
-  </body>
-  </html>
-  ";
+  // Step 4: Compose HTML email
+  $tplParams = [
+    'initiatorName' => $initiatorName,
+    'vehicleDispatchFormUrl' => $vehicleDispatchFormUrl,
+  ];
+  $emailHtml = CRM_Core_Smarty::singleton()->fetchWith('CRM/Goonjcustom/Email/DispatchForm.tpl', $tplParams);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$emailHtml = "
<html>
<body>
<p>Dear {$initiatorName},</p>
<p>Thank you so much for your invaluable efforts in running the Goonj Dropping Center.
Your dedication plays a crucial role in our work, and we deeply appreciate your continued support.</p>
<p>Please fill out this Dispatch Form – <a href='{$vehicleDispatchFormUrl}'>Link</a> once the vehicle is loaded and ready to head to Goonj’s processing center.
This will help us to verify and acknowledge the materials as soon as they arrive.</p>
<p>We truly appreciate your cooperation and continued commitment to our cause.</p>
<p>Warm Regards,<br>Team Goonj..</p>
</body>
</html>
";
$from = HelperService::getDefaultFromEmail();
$mailParams = [
'subject' => 'Kindly fill the Dispatch Form for Material Pickup',
'from' => $from,
'toEmail' => $email,
'html' => $emailHtml,
];
</body>
</html>
";
// Step 4: Compose HTML email
$tplParams = [
'initiatorName' => $initiatorName,
'vehicleDispatchFormUrl'=> $vehicleDispatchFormUrl,
];
$emailHtml = CRM_Core_Smarty::singleton()
->fetchWith('CRM/Goonjcustom/Email/DispatchForm.tpl', $tplParams);
🤖 Prompt for AI Agents
In wp-content/civi-extensions/goonjcustom/Civi/DroppingCenterService.php around
lines 566 to 578, the email HTML is hardcoded inline, which reduces
maintainability and localization support. To fix this, extract the HTML content
into a new Smarty template file named
templates/CRM/Goonjcustom/Email/DispatchForm.tpl. Then, update the PHP code to
load and render this template using CiviCRM's template system, passing necessary
variables like initiatorName and vehicleDispatchFormUrl to the template for
dynamic content rendering.


// Step 5: Send email
$from = HelperService::getDefaultFromEmail();
$mailParams = [
'subject' => 'Kindly fill the Dispatch Form for Material Pickup',
'from' => $from,
'toEmail' => $email,
'html' => $emailHtml,
];

\CRM_Utils_Mail::send($mailParams);
}
\CRM_Utils_Mail::send($mailParams);
}

/**
*
Expand Down Expand Up @@ -659,13 +679,13 @@ public static function droppingCenterTabset($tabsetName, &$tabs, $context) {
'template' => 'CRM/Goonjcustom/Tabs/DroppingCenter/DonationBox.tpl',
'permissions' => ['goonj_chapter_admin', 'urbanops', 'urban_ops_admin', 'urban_ops_and_accounts_chapter_team'],
],
'outcome' => [
'title' => ts('Outcome'),
'module' => 'afsearchDroppingCenterOutcome',
'directive' => 'afsearch-dropping-center-outcome',
'template' => 'CRM/Goonjcustom/Tabs/DroppingCenter/Outcome.tpl',
'permissions' => ['goonj_chapter_admin', 'urbanops', 'urban_ops_admin', 'urban_ops_and_accounts_chapter_team'],
],
// 'outcome' => [
// 'title' => ts('Outcome'),
// 'module' => 'afsearchDroppingCenterOutcome',
// 'directive' => 'afsearch-dropping-center-outcome',
// 'template' => 'CRM/Goonjcustom/Tabs/DroppingCenter/Outcome.tpl',
// 'permissions' => ['goonj_chapter_admin', 'urbanops', 'urban_ops_admin', 'urban_ops_and_accounts_chapter_team'],
// ],
'feedback' => [
'title' => ts('Feedback'),
'module' => 'afsearchFeedback',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,44 +670,56 @@ public static function processDispatchEmail(string $op, string $objectName, $obj
/**
*
*/
public static function sendDispatchEmail($nameOfInstitution, $address, $phone, $email, $initiatorName, $droppingCenterId, $contactId, $goonjOffice, $goonjOfficeName) {
$homeUrl = \CRM_Utils_System::baseCMSURL();
public static function sendDispatchEmail($nameOfInstitution, $address, $phone, $email, $initiatorName, $droppingCenterId, $contactId, $goonjOffice, $goonjOfficeName) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor method to reduce parameter count

The method has 9 parameters, which makes it difficult to maintain and call correctly.

Consider using a data transfer object (DTO) or array to encapsulate the dispatch email data:

-public static function sendDispatchEmail($nameOfInstitution, $address, $phone, $email, $initiatorName, $droppingCenterId, $contactId, $goonjOffice, $goonjOfficeName) {
+public static function sendDispatchEmail(array $dispatchEmailData) {
+  // Extract values from $dispatchEmailData array

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/Civi/InstitutionDroppingCenterService.php
at line 673, the sendDispatchEmail method has 9 parameters, making it hard to
maintain and use. Refactor this method by creating a data transfer object (DTO)
or an associative array to encapsulate all these parameters into a single
argument. Update the method signature to accept this DTO or array and adjust the
method body to extract needed values from it, simplifying calls and improving
readability.

$homeUrl = \CRM_Utils_System::baseCMSURL();

// Step 1: Gather data
$dispatchData = [
'Camp_Vehicle_Dispatch.Institution_Dropping_Center' => $droppingCenterId,
'Camp_Vehicle_Dispatch.Filled_by' => $contactId,
'Camp_Vehicle_Dispatch.To_which_PU_Center_material_is_being_sent' => $goonjOffice,
'Camp_Vehicle_Dispatch.Goonj_Office_Name' => $goonjOfficeName,
'Eck_Collection_Camp1' => $droppingCenterId,
'id' => $droppingCenterId,
'Camp_Institution_Data.Name_of_the_institution' => $nameOfInstitution,
'Camp_Institution_Data.Address' => $address,
'Camp_Institution_Data.Email' => $email,
'Camp_Institution_Data.Contact_Number' => $phone,
];

// Step 2: Convert to JSON and encrypt
$json = json_encode($dispatchData);
$token = \CRM_Utils_Crypt::encrypt($json);

Comment on lines +690 to 693

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add token expiration for enhanced security

The encrypted token doesn't include an expiration timestamp, which could allow indefinite reuse.

Consider adding an expiration timestamp to the token data:

  // Step 2: Convert to JSON and encrypt
+ $dispatchData['exp'] = time() + (24 * 60 * 60); // 24 hour expiration
  $json = json_encode($dispatchData);
  $token = \CRM_Utils_Crypt::encrypt($json);
🤖 Prompt for AI Agents
In
wp-content/civi-extensions/goonjcustom/Civi/InstitutionDroppingCenterService.php
around lines 690 to 693, the encrypted token is created without an expiration
timestamp, allowing indefinite reuse. To fix this, add an expiration timestamp
field to the $dispatchData array before encoding it to JSON and encrypting. Set
the expiration to a reasonable future time (e.g., current time plus a validity
period) so that the token can be validated and rejected after expiration.

$baseUrl = '/institution-dropping-center-vehicle-dispatch/';

$vehicleDispatchFormUrl = $homeUrl . $baseUrl . '#?Camp_Vehicle_Dispatch.Institution_Dropping_Center=' . $droppingCenterId
. '&Camp_Vehicle_Dispatch.Filled_by=' . $contactId
. '&Camp_Vehicle_Dispatch.To_which_PU_Center_material_is_being_sent=' . $goonjOffice
. '&Camp_Vehicle_Dispatch.Goonj_Office_Name=' . $goonjOfficeName
. '&Eck_Collection_Camp1=' . $droppingCenterId
. '&Camp_Institution_Data.Name_of_the_institution=' . $nameOfInstitution
. "&Camp_Institution_Data.Address=" . urlencode($address)
. "&Camp_Institution_Data.Email=" . $email
. "&Camp_Institution_Data.Contact_Number=" . $phone;

$emailHtml = "
<html>
<body>
// Step 3: Generate encrypted URL
$vehicleDispatchFormUrl = $homeUrl . '/institution-dropping-center-vehicle-dispatch/?token=' . urlencode($token);

// Step 4: Compose HTML email
$emailHtml = "
<html>
<body>
<p>Dear {$initiatorName},</p>
<p>Thank you so much for your invaluable efforts in running the Goonj Dropping Center.
Your dedication plays a crucial role in our work, and we deeply appreciate your continued support.</p>
<p>Please fill out this Dispatch Form – <a href='{$vehicleDispatchFormUrl}'>Link</a> once the vehicle is loaded and ready to head to Goonj’s processing center.
This will help us to verify and acknowledge the materials as soon as they arrive.</p>
<p>We truly appreciate your cooperation and continued commitment to our cause.</p>
<p>Warm Regards,<br>Team Goonj..</p>
</body>
</html>
";
$from = HelperService::getDefaultFromEmail();
$mailParams = [
'subject' => 'Kindly fill the Dispatch Form for Material Pickup',
'from' => $from,
'toEmail' => $email,
'html' => $emailHtml,
];
</body>
</html>
";

// Step 5: Send email
$from = HelperService::getDefaultFromEmail();
$mailParams = [
'subject' => 'Kindly fill the Dispatch Form for Material Pickup',
'from' => $from,
'toEmail' => $email,
'html' => $emailHtml,
];

\CRM_Utils_Mail::send($mailParams);
}
\CRM_Utils_Mail::send($mailParams);
}

/**
*
Expand Down
Loading