mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-07-24 15:05:26 -04:00
Use specialized class to to pass phone number between apps and services instead of ambigious std::string. Introduced class (utils::PhoneNumber) wraps calls to libphonenumber providing more convienient interface. However using libphonenumber directly may be resource hungry in terms of stack, heap and cpu usage, so helper class has been introduced to pass information about phone numbers (utils::PhoneNumber::View). It is designed to maintain integrity thus can be created from an instance of utils::PhoneNumber only or moved/copied to. Add new field to the calllog db holding e164 formatted number. Both entered and e164 numbers will be needed to be able to match with contacts correctly. Add constexpr information about country codes (utils::country).
170 lines
4.7 KiB
C++
170 lines
4.7 KiB
C++
#include "PhoneNumber.hpp"
|
|
|
|
#include "country.hpp"
|
|
#include "log/log.hpp"
|
|
|
|
#include <phonenumbers/phonenumberutil.h>
|
|
#include <phonenumbers/asyoutypeformatter.h>
|
|
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
using namespace utils;
|
|
|
|
PhoneNumber::PhoneNumber(const std::string &phoneNumber, country::Id defaultCountryCode)
|
|
: valid(false), countryCode(defaultCountryCode), util(*phn_util::GetInstance()), rawInput(phoneNumber)
|
|
{
|
|
valid = util.ParseAndKeepRawInput(phoneNumber, country::getAlpha2Code(countryCode), &pbNumber) ==
|
|
errCode::NO_PARSING_ERROR;
|
|
}
|
|
|
|
bool PhoneNumber::isValid() const
|
|
{
|
|
return valid;
|
|
}
|
|
|
|
const std::string &PhoneNumber::get() const
|
|
{
|
|
/// raw input can also be returned directly from pbNumber::rawInput() but
|
|
/// unfortunately if number parsing failed raw input is not preserved so
|
|
/// additional field had to be added in order to be able to always return
|
|
/// raw input
|
|
return rawInput;
|
|
}
|
|
|
|
std::string PhoneNumber::getFormatted() const
|
|
{
|
|
if (!valid) {
|
|
return rawInput;
|
|
}
|
|
|
|
std::string formatted;
|
|
util.FormatInOriginalFormat(pbNumber, country::getAlpha2Code(countryCode), &formatted);
|
|
return formatted;
|
|
}
|
|
|
|
std::string PhoneNumber::toE164() const
|
|
{
|
|
if (!valid) {
|
|
throw std::runtime_error("Can't create E164 format from an invalid number.");
|
|
}
|
|
|
|
std::string e164number;
|
|
util.Format(pbNumber, formatType::E164, &e164number);
|
|
|
|
return e164number;
|
|
}
|
|
|
|
bool PhoneNumber::operator==(const PhoneNumber &right)
|
|
{
|
|
return util.IsNumberMatch(pbNumber, right.pbNumber) == phn_util::EXACT_MATCH;
|
|
}
|
|
|
|
bool PhoneNumber::operator==(const View &view)
|
|
{
|
|
if (isValid() != view.isValid()) {
|
|
return false;
|
|
}
|
|
|
|
return isValid() ? toE164() == view.getE164() : rawInput == view.getEntered();
|
|
}
|
|
|
|
PhoneNumber::numberType PhoneNumber::getType() const
|
|
{
|
|
return util.GetNumberType(pbNumber);
|
|
}
|
|
|
|
bool PhoneNumber::e164format(const std::string &number, std::string &e164, country::Id defaultCountryCode)
|
|
{
|
|
i18n::phonenumbers::PhoneNumber phNumber;
|
|
auto &util = *phn_util::GetInstance();
|
|
|
|
auto result = util.Parse(number, country::getAlpha2Code(defaultCountryCode), &phNumber);
|
|
if (result != errCode::NO_PARSING_ERROR) {
|
|
return false;
|
|
}
|
|
|
|
util.Format(phNumber, formatType::E164, &e164);
|
|
|
|
return true;
|
|
}
|
|
|
|
PhoneNumber::View PhoneNumber::makeView() const
|
|
{
|
|
return PhoneNumber::View(get(), getFormatted(), isValid() ? toE164() : "", isValid());
|
|
}
|
|
|
|
PhoneNumber::View PhoneNumber::validateNumber(const std::string &e164, const std::string &entered)
|
|
{
|
|
auto &util = *phn_util::GetInstance();
|
|
|
|
// parse E164 number
|
|
i18n::phonenumbers::PhoneNumber pbNumberE164;
|
|
if (util.Parse(e164, country::getAlpha2Code(country::Id::UNKNOWN), &pbNumberE164) != errCode::NO_PARSING_ERROR) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// get region code from E164 number
|
|
std::string regionCode;
|
|
util.GetRegionCodeForNumber(pbNumberE164, ®ionCode);
|
|
if (regionCode == country::getAlpha2Code(country::Id::UNKNOWN)) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// use region code to parse number originally entered by the user
|
|
// keep raw input in order to be able to use original format in formatting
|
|
i18n::phonenumbers::PhoneNumber pbNumberEntered;
|
|
if (util.ParseAndKeepRawInput(entered, regionCode, &pbNumberEntered) != errCode::NO_PARSING_ERROR) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// check if numbers match
|
|
if (util.IsNumberMatch(pbNumberE164, pbNumberEntered) != phn_util::EXACT_MATCH) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// format number to generate full view of the number
|
|
std::string formatted;
|
|
util.FormatInOriginalFormat(pbNumberEntered, regionCode, &formatted);
|
|
|
|
return PhoneNumber::View(entered, formatted, e164, true);
|
|
}
|
|
|
|
void PhoneNumber::View::clear()
|
|
{
|
|
this->operator=(View());
|
|
}
|
|
|
|
PhoneNumber::View PhoneNumber::viewFromE164(const std::string &e164)
|
|
{
|
|
PhoneNumber number(e164, country::Id::UNKNOWN);
|
|
return number.makeView();
|
|
}
|
|
|
|
const std::string &PhoneNumber::View::getEntered() const
|
|
{
|
|
return entered;
|
|
}
|
|
|
|
const std::string &PhoneNumber::View::getE164() const
|
|
{
|
|
return e164;
|
|
}
|
|
|
|
const std::string &PhoneNumber::View::getFormatted() const
|
|
{
|
|
return formatted;
|
|
}
|
|
|
|
bool PhoneNumber::View::isValid() const
|
|
{
|
|
return valid;
|
|
}
|
|
|
|
PhoneNumber::View::View(const std::string &enteredNumber,
|
|
const std::string &formattedNumber,
|
|
const std::string &e164Number,
|
|
bool valid)
|
|
: entered(enteredNumber), formatted(formattedNumber), e164(e164Number), valid(valid)
|
|
{}
|