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
7 changes: 4 additions & 3 deletions db/cats_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ insert into `module_schema`(`module_schema_id`,`name`,`version`) values (9,'ext
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (10,'graphs',0);
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (11,'home',0);
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (12,'import',0);
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (13,'install',363);
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (13,'install',365);
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (14,'joborders',0);
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (15,'lists',0);
insert into `module_schema`(`module_schema_id`,`name`,`version`) values (16,'login',0);
Expand Down Expand Up @@ -999,6 +999,7 @@ CREATE TABLE `site` (
`time_zone` int(5) DEFAULT '0',
`time_format_24` int(1) DEFAULT '0',
`date_format_ddmmyy` int(1) DEFAULT '0',
`default_phone_country_code` varchar(8) COLLATE utf8_unicode_ci NOT NULL DEFAULT '+1',
`is_hr_mode` int(1) DEFAULT '0',
`file_size_kb` int(11) DEFAULT '0',
`page_views` bigint(20) DEFAULT '0',
Expand All @@ -1014,8 +1015,8 @@ CREATE TABLE `site` (

/*Data for the table `site` */

insert into `site`(`site_id`,`name`,`is_demo`,`user_licenses`,`entered_by`,`date_created`,`unix_name`,`company_id`,`is_free`,`account_active`,`account_deleted`,`reason_disabled`,`time_zone`,`time_format_24`,`date_format_ddmmyy`,`is_hr_mode`,`file_size_kb`,`page_views`,`page_view_days`,`last_viewed_day`,`first_time_setup`,`localization_configured`,`agreed_to_license`,`limit_warning`) values (1,'testdomain.com',0,0,0,'2005-06-01 00:00:00',NULL,NULL,0,1,0,NULL,2,0,1,0,0,574,1,'2009-11-19',0,0,1,0);
insert into `site`(`site_id`,`name`,`is_demo`,`user_licenses`,`entered_by`,`date_created`,`unix_name`,`company_id`,`is_free`,`account_active`,`account_deleted`,`reason_disabled`,`time_zone`,`time_format_24`,`date_format_ddmmyy`,`is_hr_mode`,`file_size_kb`,`page_views`,`page_view_days`,`last_viewed_day`,`first_time_setup`,`localization_configured`,`agreed_to_license`,`limit_warning`) values (180,'CATS_ADMIN',0,0,0,'2005-06-01 00:00:00','catsadmin',NULL,0,1,0,NULL,2,0,1,0,0,0,0,NULL,0,0,0,0);
insert into `site`(`site_id`,`name`,`is_demo`,`user_licenses`,`entered_by`,`date_created`,`unix_name`,`company_id`,`is_free`,`account_active`,`account_deleted`,`reason_disabled`,`time_zone`,`time_format_24`,`date_format_ddmmyy`,`default_phone_country_code`,`is_hr_mode`,`file_size_kb`,`page_views`,`page_view_days`,`last_viewed_day`,`first_time_setup`,`localization_configured`,`agreed_to_license`,`limit_warning`) values (1,'testdomain.com',0,0,0,'2005-06-01 00:00:00',NULL,NULL,0,1,0,NULL,2,0,1,'+1',0,0,574,1,'2009-11-19',0,0,1,0);
insert into `site`(`site_id`,`name`,`is_demo`,`user_licenses`,`entered_by`,`date_created`,`unix_name`,`company_id`,`is_free`,`account_active`,`account_deleted`,`reason_disabled`,`time_zone`,`time_format_24`,`date_format_ddmmyy`,`default_phone_country_code`,`is_hr_mode`,`file_size_kb`,`page_views`,`page_view_days`,`last_viewed_day`,`first_time_setup`,`localization_configured`,`agreed_to_license`,`limit_warning`) values (180,'CATS_ADMIN',0,0,0,'2005-06-01 00:00:00','catsadmin',NULL,0,1,0,NULL,2,0,1,'+1',0,0,0,0,NULL,0,0,0,0);

/*Table structure for table `sph_counter` */

Expand Down
10 changes: 10 additions & 0 deletions installwizard.php
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,16 @@
</select>
</td>
</tr>
<tr>
<td>Please enter your default phone country calling code.</td>
</tr>
<tr>
<td>
<span>+</span>
<input type="text" name="defaultPhoneCountryCodeDigits" id="defaultPhoneCountryCodeDigits" value="" size="5" maxlength="5" oninput="this.value = this.value.replace(/[^0-9]/g, '');"
/>
</td>
</tr>
</table>
<br />
<br />
Expand Down
28 changes: 28 additions & 0 deletions lib/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class CATSSession
private $_storedBuild = -1;
private $_timeZoneOffset = 0;
private $_timeZone = 0;
private $_defaultPhoneCountryCode = '+1';
private $_dateDMY = false;
private $_pipelineEntriesPerPage = 15;
private $_storedData = array();
Expand Down Expand Up @@ -533,6 +534,29 @@ public function getTimeZone()
return $this->_timeZone;
}

/**
* Returns the default phone country calling code (E.164) for the
* current site. The value is stored in the "site" table.
*
* @return string
*/
public function getDefaultPhoneCountryCode()
{
return $this->_defaultPhoneCountryCode;
}

/**
* Sets the default phone country calling code for the current site
* on the session object. This does not write to the database.
*
* @param string $countryCode
* @return void
*/
public function setDefaultPhoneCountryCode($countryCode)
{
$this->_defaultPhoneCountryCode = $countryCode;
}

// FIXME: Document me!
public function getUserCategories()
{
Expand Down Expand Up @@ -678,6 +702,7 @@ public function processLogin($username, $password, $addToHistory = true)
site.account_active AS accountActive,
site.account_deleted AS accountDeleted,
site.time_zone AS timeZone,
site.default_phone_country_code AS defaultPhoneCountryCode,
site.date_format_ddmmyy AS dateFormatDMY,
site.is_free AS isFree,
site.is_hr_mode AS isHrMode,
Expand Down Expand Up @@ -810,6 +835,7 @@ public function processLogin($username, $password, $addToHistory = true)
$this->_userAgent = $userAgent;
$this->_timeZoneOffset = $rs['timeZone'] - OFFSET_GMT;
$this->_timeZone = $rs['timeZone'];
$this->_defaultPhoneCountryCode = $rs['defaultPhoneCountryCode'];
$this->_dateDMY = ($rs['dateFormatDMY'] == 0 ? false : true);
$this->_canSeeEEOInfo = ($rs['canSeeEEOInfo'] == 0 ? false : true);
$this->_pipelineEntriesPerPage = $rs['pipelineEntriesPerPage'];
Expand Down Expand Up @@ -958,6 +984,7 @@ public function transparentLogin($toSiteID, $asUserID, $asSiteID)
site.account_active AS accountActive,
site.account_deleted AS accountDeleted,
site.time_zone AS timeZone,
site.default_phone_country_code AS defaultPhoneCountryCode,
site.date_format_ddmmyy AS dateFormatDMY,
site.is_free AS isFree,
site.is_hr_mode AS isHrMode
Expand Down Expand Up @@ -992,6 +1019,7 @@ public function transparentLogin($toSiteID, $asUserID, $asSiteID)
$this->_accountDeleted = ($rs['accountDeleted'] == 0 ? false : true);
$this->_email = $rs['email'];
$this->_timeZone = $rs['timeZone'];
$this->_defaultPhoneCountryCode = $rs['defaultPhoneCountryCode'];
$this->_dateDMY = ($rs['dateFormatDMY'] == 0 ? false : true);
$this->_isFirstTimeSetup = true;
$this->_isAgreedToLicense = true;
Expand Down
22 changes: 22 additions & 0 deletions lib/Site.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,28 @@ public function setLocalization($timeZone, $isDMY)
return (boolean) $this->_db->query($sql);
}

/**
* Sets the default phone country calling code for the current site.
*
* @param string $countryCode E.164 country calling code (for example "+49").
* @return boolean True if successful; false otherwise.
*/
public function setDefaultPhoneCountryCode($countryCode)
{
$sql = sprintf(
"UPDATE
site
SET
default_phone_country_code = %s
WHERE
site_id = %s",
$this->_db->makeQueryString($countryCode),
$this->_siteID
);

return (boolean) $this->_db->query($sql);
}

/**
* Get site information by unix name.
*
Expand Down
175 changes: 149 additions & 26 deletions lib/StringUtility.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,44 +119,167 @@ public static function containsPhoneNumber($string)
return false;
}

/**
* Returns the first phone number that could be extracted from a string.
*
* Uses the new E.164-based implementation. The previous NANP-specific
* implementation is kept below as commented legacy code to support
* future refactoring.
*
* @param string $string String to test.
* @return string Phone number or '' if not found.
*/
public static function extractPhoneNumber($string)
{
/*
* Legacy NANP-based implementation kept for reference during
* refactoring.
*
* if (preg_match('/'
* . self::matchPHECountryCode . self::matchPHSeparator . self::matchPHEAreaCode
* . self::matchPHSeparator . self::matchPHEExchange . self::matchPHSeparator
* . self::matchPHENumber . self::matchPHSeparator . self::matchPHEExtension
* . '/i', $string, $matches))
* {
* // Do not format international phone numbers.
* if (!empty($matches['countryCode']) && ($matches['countryCode'] != '1'))
* {
* return $string;
* }
*
* $formattedPhoneNumber = sprintf(
* '%s-%s-%s',
* $matches['areaCode'],
* $matches['exchange'],
* $matches['number']
* );
*
* if (isset($matches['extension']) && !empty($matches['extension']))
* {
* $formattedPhoneNumber .= ' x ' . $matches['extension'];
* }
*
* return $formattedPhoneNumber;
* }
*
* return '';
*/

return self::extractPhoneNumberE164($string);
}

/**
* Returns the first phone number that could be extracted from a string.
* Returns the first phone number that could be extracted from a string
* and normalizes it to E.164 where possible.
*
* @param string to test
* @return string phone number or '' if not found
* @param string $string String to test.
* @return string Normalized E.164 phone number or '' if not found.
*/
public static function extractPhoneNumber($string)
private static function extractPhoneNumberE164($string)
{
if (preg_match('/'
. self::matchPHECountryCode . self::matchPHSeparator . self::matchPHEAreaCode
. self::matchPHSeparator . self::matchPHEExchange . self::matchPHSeparator
. self::matchPHENumber . self::matchPHSeparator . self::matchPHEExtension
. '/i', $string, $matches))
/* 1) Trim leading / trailing whitespace. */
$string = trim((string) $string);

/* 2) Replace leading "00" with "+" (0049... -> +49...). */
if (strpos($string, '00') === 0)
{
//print_r($matches);
$string = '+' . substr($string, 2);
}

/* Don't format international phone numbers. */
if (!empty($matches['countryCode']) && ($matches['countryCode'] != '1'))
{
return $string;
}
/*
* 3) Remove all characters except digits and '+'.
* This strips spaces, '-', '/', '()', '.', etc.
*/
$string = preg_replace('/[^0-9+]/', '', $string);

/*
* 4) If there are no digits (and no '+' sign) left after normalization,
* we treat this as "no phone number found".
*/
if ($string === '')
{
return '';
}

$formattedPhoneNumber = sprintf(
"%s-%s-%s",
$matches['areaCode'],
$matches['exchange'],
$matches['number']
);
/*
* 5) If the value already starts with '+', assume that the caller
* provided a full international number in E.164 format.
*/
if ($string[0] === '+')
{
return $string;
}

/*
* 6) Local number:
* - determine the default country calling code
* - strip leading trunk zeros
* - build the E.164 representation
*/
$countryCode = self::getDefaultPhoneCountryCode();

if (isset($matches['extension']) && !empty($matches['extension']))
if ($countryCode === '')
{
/*
* No configuration available; we cannot safely build an
* E.164 number. Returning an empty string makes this
* failure explicit.
*/
return '';
}

$nationalNumber = ltrim($string, '0');

if ($nationalNumber === '')
{
/* Input consisted only of zeros – treat as invalid. */
return '';
}

return $countryCode . $nationalNumber;
}

/**
* Returns the default phone country calling code (E.164) for the
* current site.
*
* The value is obtained from the active session if available. If no
* usable configuration can be read, a hard-coded fallback is returned
* to keep the behaviour predictable.
*
* @return string E.164 country calling code (for example "+49").
*/
private static function getDefaultPhoneCountryCode()
{
/*
* Try to read the default phone country code from the current
* session. This requires the Session class to expose a
* getDefaultPhoneCountryCode() method which returns the value
* stored in the "site" table.
*/
if (isset($_SESSION['CATS'])
&& method_exists($_SESSION['CATS'], 'getDefaultPhoneCountryCode'))
{
$code = trim((string) $_SESSION['CATS']->getDefaultPhoneCountryCode());

/*
* Basic sanity check: the value must start with '+' and
* contain at least one digit. More strict validation is
* performed when the value is saved in the administration UI.
*/
if ($code !== '' && preg_match('/^\+[0-9]+$/', $code))
{
$formattedPhoneNumber .= ' x ' . $matches['extension'];
return $code;
}

return $formattedPhoneNumber;
}

return '';
/*
* Fallback: if no usable configuration is available we return the
* original NANP-style default of "+1". This keeps behaviour
* predictable for existing installations that have not yet
* configured a different default.
*/
return '+1';
}

/**
Expand Down
6 changes: 6 additions & 0 deletions modules/install/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,12 @@ public static function get()
'364' => '
UPDATE user SET password = md5(password) WHERE can_change_password=1;
',
'365' => '
ALTER IGNORE TABLE `site`
ADD COLUMN `default_phone_country_code` varchar(8)
COLLATE utf8_unicode_ci NOT NULL DEFAULT \'+1\'
AFTER `date_format_ddmmyy`;
',

);
}
Expand Down
Loading