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

Feature: add phone number to donor profile #7331

Merged
merged 25 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d8bb82a
feature: add phone column to donors table
glaubersilva Mar 26, 2024
cc00b04
feature: add donor phone to model and repository
glaubersilva Mar 26, 2024
3af83fd
feature: add phone to donor profile page
glaubersilva Mar 26, 2024
69974c4
feature: add give_get_phone_input method with support for internation…
glaubersilva Mar 26, 2024
856b84c
refactor: make country list translatable
glaubersilva Mar 27, 2024
ad2eb97
fix: case for country list key
glaubersilva Mar 27, 2024
ecf28ee
fix: change js logic to allow multiple input in a same page
glaubersilva Mar 27, 2024
966ff51
refactor: change method name and extract translation logic to give_ge…
glaubersilva Mar 27, 2024
4a0ad38
refactor: add support to custom classes in the tel input
glaubersilva Mar 27, 2024
1e793b5
feature: add logic to validate phone numbers
glaubersilva Mar 27, 2024
fcd761e
fix: save phone on DB as empty when it's null
glaubersilva Mar 27, 2024
723bf6f
refactor: rename hidden inputs
glaubersilva Mar 27, 2024
02558cf
doc: add unreleased tags
glaubersilva Mar 27, 2024
512df36
doc: standardizes comments
glaubersilva Mar 27, 2024
1269871
format: add comment in the proper place
glaubersilva Mar 27, 2024
92d08a3
refactor: simplify give_get_intl_tel_input_i18n_json_object() method
glaubersilva Mar 27, 2024
2f2f98d
refactor: change class
glaubersilva Mar 28, 2024
078a7d3
refactor: rename class
glaubersilva Mar 28, 2024
1002d0d
refactor: check phone property is set before filling out
glaubersilva Mar 28, 2024
2fd2065
feature: test "phone" property
glaubersilva Mar 28, 2024
f7a4c85
feature: add tests for phone property
glaubersilva Mar 28, 2024
fdfd614
refactor: change column position
glaubersilva Mar 28, 2024
6fc5a89
refactor: prevent the use of models in the legacy codebase.
glaubersilva Mar 28, 2024
c36a9fb
refactor: remove double sanitization
glaubersilva Mar 28, 2024
98aef6a
refactor: rename var
glaubersilva Mar 28, 2024
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
12 changes: 10 additions & 2 deletions includes/admin/donors/donor-actions.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 All @@ -17,11 +19,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 +128,10 @@ 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'] ) );

$donorModel = Donor::find($donor->id);
$donorModel->phone = sanitize_text_field($args['give_donor_phone_number--international-format']);
$donorModel->save();

jonwaldstein marked this conversation as resolved.
Show resolved Hide resolved
// 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/intl-tel-input@20.2.0/build/css/intlTelInput.css';
$scriptUrl = 'https://cdn.jsdelivr.net/npm/intl-tel-input@20.2.0/build/js/intlTelInput.min.js';
$utilsScriptUrl = 'https://cdn.jsdelivr.net/npm/intl-tel-input@20.2.0/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);
}
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',
glaubersilva marked this conversation as resolved.
Show resolved Hide resolved
'prefix' => 'string',
'additionalEmails' => ['array', []],
'totalAmountDonated' => Money::class,
Expand Down
9 changes: 9 additions & 0 deletions src/Donors/Repositories/DonorRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public function getAdditionalEmails(int $donorId)
}

/**
* @unreleased Add support to "phone" property
* @since 2.24.0 add support for $donor->totalAmountDonated and $donor->totalNumberOfDonation
* @since 2.21.0 add actions givewp_donor_creating and givewp_donor_created
* @since 2.20.0 mutate model and return void
Expand All @@ -122,6 +123,10 @@ public function insert(Donor $donor)
'name' => $donor->name,
];

if (isset($donor->phone)) {
$args['phone'] = $donor->phone;
}

if (isset($donor->totalAmountDonated)) {
$args['purchase_value'] = $donor->totalAmountDonated->formatToDecimal();
}
Expand Down Expand Up @@ -172,6 +177,7 @@ public function insert(Donor $donor)
}

/**
* @unreleased Add support to "phone" property
* @since 2.24.0 add support for $donor->totalAmountDonated and $donor->totalNumberOfDonation
* @since 2.23.1 use give()->donor_meta to update meta so data is upserted
* @since 2.21.0 add actions givewp_donor_updating and givewp_donor_updated
Expand All @@ -192,6 +198,7 @@ public function update(Donor $donor)
$args = [
'user_id' => $donor->userId,
'email' => $donor->email,
'phone' => $donor->phone,
'name' => $donor->name
];

Expand Down Expand Up @@ -367,6 +374,7 @@ public function getByAdditionalEmail(string $email)
}

/**
* @unreleased Add support to "phone" property
* @since 2.24.0 replace ModelQueryBuilder with DonorModelQueryBuilder
* @since 2.19.6
*
Expand All @@ -381,6 +389,7 @@ public function prepareQuery(): DonorModelQueryBuilder
'id',
['user_id', 'userId'],
'email',
'phone',
'name',
['purchase_value', 'totalAmountDonated'],
['purchase_count', 'totalNumberOfDonations'],
Expand Down
Loading
Loading