Skip to content

Commit

Permalink
Feature: add phone number to donor profile (#7331)
Browse files Browse the repository at this point in the history
  • Loading branch information
glaubersilva authored Mar 29, 2024
1 parent 5386b28 commit 4174ebf
Show file tree
Hide file tree
Showing 12 changed files with 330 additions and 4 deletions.
16 changes: 14 additions & 2 deletions includes/admin/donors/donor-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
/**
* Processes a donor edit.
*
* @param array $args The $_POST array being passed.
* @unreleased Add support to the "phone" field
* @since 1.0
*
* @since 1.0
* @param array $args The $_POST array being passed.
*
* @return array|bool $output Response messages
* @throws Exception
*/
function give_edit_donor( $args ) {

Expand Down Expand Up @@ -124,6 +126,16 @@ function give_edit_donor( $args ) {
// Save company name in when admin update donor company name from dashboard.
$donor->update_meta( '_give_donor_company', sanitize_text_field( $args['give_donor_company'] ) );

/**
* Fires after using the submitted data to update the donor metadata.
*
* @param array $args The sanitized data submitted.
* @param int $donor_id The donor ID.
*
* @unreleased
*/
do_action('give_admin_donor_details_updating', $args, $donor->id);

// If First name of donor is empty, then fetch the current first name of donor.
if ( empty( $donor_info['first_name'] ) ) {
$donor_info['first_name'] = $donor->get_first_name();
Expand Down
28 changes: 26 additions & 2 deletions includes/admin/donors/donors.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* @since 1.0
*/

use Give\Donors\Models\Donor;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
Expand Down Expand Up @@ -298,6 +300,7 @@ function give_render_donor_view( $view, $callbacks ) {
/**
* View a donor
*
* @unreleased Add "phone" field
* @since 1.0
*
* @param Give_Donor $donor The Donor object being displayed.
Expand Down Expand Up @@ -478,10 +481,31 @@ function give_donor_view( $donor ) {
</td>
</tr>

<?php
<?php

$donor_phone_number = Donor::find($donor->id)->phone;
?>
<tr class="alternate">
<th scope="col">
<label for="tablecell"><?php
esc_html_e('Phone:', 'give'); ?></label>
</th>
<td>
<span class="donor-user-id info-item edit-item">
<?php
echo give_get_intl_tel_input($donor_phone_number, "give_donor_phone_number"); ?>
</span>

<span class="donor-user-id info-item editable">
<?php
echo $donor_phone_number; ?>
</span>
</td>
</tr>
<?php
$donor_company = $donor->get_meta( '_give_donor_company', true );
?>
<tr class="alternate">
<tr class="">
<th scope="col">
<label for="tablecell"><?php esc_html_e( 'Company Name:', 'give' ); ?></label>
</th>
Expand Down
114 changes: 114 additions & 0 deletions includes/misc-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2624,3 +2624,117 @@ function give_get_page_by_title(string $page_title, string $output = OBJECT, str

return get_post($pages[0], $output);
}

/**
* @see https://github.com/jackocnr/intl-tel-input
*
* @unreleased
*/
function give_get_intl_tel_input(string $value, string $id, string $class = '', string $name = ''):string {

if (empty($name)) {
$name = $id;
}

$styleUrl = 'https://cdn.jsdelivr.net/npm/[email protected]/build/css/intlTelInput.css';
$scriptUrl = 'https://cdn.jsdelivr.net/npm/[email protected]/build/js/intlTelInput.min.js';
$utilsScriptUrl = 'https://cdn.jsdelivr.net/npm/[email protected]/build/js/utils.js';

ob_start();

?>
<script src="<?php echo $scriptUrl; ?>"></script>
<link rel="stylesheet" href="<?php echo $styleUrl; ?>">

<input id="<?php echo $id; ?>" class="<?php echo $class; ?>" name="<?php echo $name; ?>" value="<?php echo $value; ?>" type='text'>
<span id="<?php echo $id . '--error-msg'; ?>" class="give-intl-tel-input-hide" style="color:red;"></span>

<style>
.give-intl-tel-input-hide {
display: none !important;
}
.give-intl-tel-input-error {
border: 1px solid red !important;
}
</style>
<script>
if (document.readyState !== 'loading') {
readyHandler();
} else {
document.addEventListener('DOMContentLoaded', readyHandler);
}
function readyHandler() {
const input = document.querySelector("#<?php echo $id; ?>");
const iti = window.intlTelInput(input, {
utilsScript: "<?php echo $utilsScriptUrl; ?>",
hiddenInput: function(telInputName) {
return {
phone: "<?php echo $id . '--international-format'; ?>",
country: "<?php echo $id . '--country-code'; ?>"
};
},
initialCountry: "<?php echo strtolower(give_get_country()); ?>",
showSelectedDialCode: true,
strictMode: false,
i18n: <?php echo give_get_intl_tel_input_i18n_json_object(); ?>
});

const errorMsg = document.querySelector("#<?php echo $id . '--error-msg'; ?>");
const errorMap = [
"<?php echo __('Invalid number', 'give'); ?>",
"<?php echo __('Invalid country code', 'give'); ?>",
"<?php echo __('Too short', 'give'); ?>",
"<?php echo __('Too long', 'give'); ?>",
"<?php echo __('Invalid number', 'give'); ?>",
];

const reset = () => {
input.classList.remove("give-intl-tel-input-error");
errorMsg.innerHTML = "";
errorMsg.classList.add("give-intl-tel-input-hide");
};

const showError = (msg) => {
input.classList.add("give-intl-tel-input-error");
errorMsg.innerHTML = msg;
errorMsg.classList.remove("give-intl-tel-input-hide");
};

input.addEventListener('change', reset);
input.addEventListener('keyup', reset);
input.form.addEventListener("submit", function(e) {
if (input.value.trim() && !iti.isValidNumber()) {
e.preventDefault();
const errorCode = iti.getValidationError();
const msg = errorMap[errorCode] || errorMap[0];
showError(msg);
return false;
}
});
}
</script>
<?php

return ob_get_clean();
}

/**
* @unreleased
*/
function give_get_intl_tel_input_i18n_json_object() {

$countryList = array_change_key_case(give_get_country_list());
array_shift($countryList); // Remove first empty item from the country list

$i18n = array_merge($countryList, [
'selectedCountryAriaLabel' => __('Selected country', 'give'), // Aria label for the selected country element
'noCountrySelected' => __('No country selected', 'give'), // Screen reader text for when no country is selected
'countryListAriaLabel' => __('List of countries', 'give'), // Aria label for the country list element
'searchPlaceholder' => __('Search', 'give'), // Placeholder for the search input in the dropdown (when countrySearch enabled)
'zeroSearchResults' => __('No results found', 'give'), // Screen reader text for when the search produces no results
'oneSearchResult' => __('1 result found', 'give'), // Screen reader text for when the search produces 1 result
'multipleSearchResults' => __('${count} results found', 'give'), // Screen reader text for when the search produces multiple results, where ${count} will be replaced by the count
]);

return json_encode($i18n);
}
26 changes: 26 additions & 0 deletions src/Donors/Actions/UpdateAdminDonorDetails.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Give\Donors\Actions;

use Exception;
use Give\Donors\Models\Donor;

/**
* This class allows us to use the Donor model to update data from the donor profile admin legacy page without adding new code directly to the legacy codebase.
*
* @unreleased
*/
class UpdateAdminDonorDetails
{
/**
* @unreleased
*
* @throws Exception
*/
public function __invoke(array $args, int $donorId)
{
$donor = Donor::find($donorId);
$donor->phone = $args['give_donor_phone_number--international-format'];
$donor->save();
}
}
6 changes: 6 additions & 0 deletions src/Donors/DataTransferObjects/DonorQueryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ final class DonorQueryData
* @var string
*/
public $email;
/**
* @var string
*/
public $phone;
/**
* @var string
*/
Expand Down Expand Up @@ -63,6 +67,7 @@ final class DonorQueryData
/**
* Convert data from donor object to Donor Model
*
* @unreleased Add "phone" property
* @since 2.24.0 add $totalAmountDonated and $totalNumberOfDonations
* @since 2.20.0 add donor prefix property
* @since 2.19.6
Expand All @@ -77,6 +82,7 @@ public static function fromObject($object)
$self->userId = (int)$object->userId;
$self->prefix = $object->{DonorMetaKeys::PREFIX()->getKeyAsCamelCase()};
$self->email = $object->email;
$self->phone = $object->phone;
$self->name = $object->name;
$self->firstName = $object->firstName;
$self->lastName = $object->lastName;
Expand Down
2 changes: 2 additions & 0 deletions src/Donors/Factories/DonorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
class DonorFactory extends ModelFactory
{
/**
* @unreleased Add "phone" property
* @since 2.19.6
*/
public function definition(): array
Expand All @@ -19,6 +20,7 @@ public function definition(): array
'lastName' => $lastName,
'name' => trim("$firstName $lastName"),
'email' => $this->faker->email,
'phone' => $this->faker->phoneNumber,
'totalAmountDonated' => new Money(0, 'USD'),
'totalNumberOfDonations' => 0
];
Expand Down
60 changes: 60 additions & 0 deletions src/Donors/Migrations/AddPhoneColumn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Give\Donors\Migrations;

use Give\Framework\Database\Exceptions\DatabaseQueryException;
use Give\Framework\Migrations\Contracts\Migration;
use Give\Framework\Migrations\Exceptions\DatabaseMigrationException;

/**
* @unreleased
*/
class AddPhoneColumn extends Migration
{
/**
* @unreleased
*
* @throws DatabaseMigrationException
*/
public function run()
{
global $wpdb;

$donorsTableName = "{$wpdb->prefix}give_donors";

try {
maybe_add_column(
$donorsTableName,
'phone',
"ALTER TABLE `$donorsTableName` ADD COLUMN `phone` varchar(50) NOT NULL DEFAULT '' AFTER `name`"
);
} catch (DatabaseQueryException $exception) {
throw new DatabaseMigrationException('An error occurred adding the phone column to the donors table',
0, $exception);
}
}

/**
* @unreleased
*/
public static function id(): string
{
return 'donors-add-phone-column';
}

/**
* @unreleased
*/
public static function title(): string
{
return 'Add phone column to donors table';
}

/**
* @unreleased
*/
public static function timestamp()
{
return strtotime('2024-26-03');
}
}
3 changes: 3 additions & 0 deletions src/Donors/Models/Donor.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
/**
* Class Donor
*
* @unreleased Add "phone" property
* @since 2.24.0 add new properties $totalAmountDonated and $totalNumberOfDonations
* @since 2.19.6
*
Expand All @@ -31,6 +32,7 @@
* @property string $firstName
* @property string $lastName
* @property string $email
* @property string $phone
* @property string[] $additionalEmails
* @property Money $totalAmountDonated
* @property int $totalNumberOfDonations
Expand All @@ -50,6 +52,7 @@ class Donor extends Model implements ModelCrud, ModelHasFactory
'firstName' => 'string',
'lastName' => 'string',
'email' => 'string',
'phone' => 'string',
'prefix' => 'string',
'additionalEmails' => ['array', []],
'totalAmountDonated' => Money::class,
Expand Down
Loading

0 comments on commit 4174ebf

Please sign in to comment.