From 8bb6c53dba0492725b0ff78bda647c0094776865 Mon Sep 17 00:00:00 2001 From: anonymoususer72041 <247563575+anonymoususer72041@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:00:00 +0200 Subject: [PATCH 1/6] Add country column to company, contact, candidate and job orders --- db/cats_schema.sql | 6 +++++- modules/install/Schema.php | 6 ++++++ test/data/securityTests.sql | 18 +++++++++--------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/db/cats_schema.sql b/db/cats_schema.sql index 6fbd1dbcc..0bb1ce682 100755 --- a/db/cats_schema.sql +++ b/db/cats_schema.sql @@ -172,6 +172,7 @@ CREATE TABLE `candidate` ( `city` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `state` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `zip` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL, + `country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL, `source` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, `date_available` datetime DEFAULT NULL, `can_relocate` int(1) NOT NULL DEFAULT '0', @@ -460,6 +461,7 @@ CREATE TABLE `company` ( `city` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `state` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `zip` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL, + `country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL, `phone1` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL, `phone2` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL, `url` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, @@ -486,7 +488,7 @@ CREATE TABLE `company` ( /*Data for the table `company` */ -insert into `company`(`company_id`,`site_id`,`billing_contact`,`name`,`address`,`city`,`state`,`zip`,`phone1`,`phone2`,`url`,`key_technologies`,`notes`,`entered_by`,`owner`,`date_created`,`date_modified`,`is_hot`,`fax_number`,`import_id`,`default_company`) values (1,1,NULL,'Internal Postings','','','','','','','','','',0,0,'1000-01-01 00:00:00','1000-01-01 00:00:00',0,'',NULL,1); +insert into `company`(`company_id`,`site_id`,`billing_contact`,`name`,`address`,`city`,`state`,`zip`,`country`,`phone1`,`phone2`,`url`,`key_technologies`,`notes`,`entered_by`,`owner`,`date_created`,`date_modified`,`is_hot`,`fax_number`,`import_id`,`default_company`) values (1,1,NULL,'Internal Postings','','','','',NULL,'','','','','',0,0,'1000-01-01 00:00:00','1000-01-01 00:00:00',0,'',NULL,1); /*Table structure for table `company_department` */ @@ -521,6 +523,7 @@ CREATE TABLE `contact` ( `city` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `state` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, `zip` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL, + `country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL, `is_hot` int(1) DEFAULT NULL, `notes` text COLLATE utf8_unicode_ci, `entered_by` int(11) NOT NULL DEFAULT '0', @@ -802,6 +805,7 @@ CREATE TABLE `joborder` ( `openings` int(11) DEFAULT NULL, `city` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `state` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, + `country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL, `start_date` datetime DEFAULT NULL, `date_created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00', `date_modified` datetime NOT NULL DEFAULT '1000-01-01 00:00:00', diff --git a/modules/install/Schema.php b/modules/install/Schema.php index 6be26b691..9b470e37f 100755 --- a/modules/install/Schema.php +++ b/modules/install/Schema.php @@ -1498,6 +1498,12 @@ public static function get() ALTER TABLE `joborder` CHANGE `state` `state` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL; ', + '379' => ' + ALTER TABLE `candidate` ADD COLUMN `country` VARCHAR(2) DEFAULT NULL AFTER `zip`; + ALTER TABLE `company` ADD COLUMN `country` VARCHAR(2) DEFAULT NULL AFTER `zip`; + ALTER TABLE `contact` ADD COLUMN `country` VARCHAR(2) DEFAULT NULL AFTER `zip`; + ALTER TABLE `joborder` ADD COLUMN `country` VARCHAR(2) DEFAULT NULL AFTER `state`; + ', ); } diff --git a/test/data/securityTests.sql b/test/data/securityTests.sql index c16d088eb..3af0fb269 100644 --- a/test/data/securityTests.sql +++ b/test/data/securityTests.sql @@ -12,26 +12,26 @@ VALUES (10008, 1, 'testerRoot', 'noreply@noreply.com', 'f5d1278e8109edd94e1e4197e04873b9', 500, 1, 1, '', '', 0, NULL, 'CATS=3b00bmdrn4vrc1eu2mv555p601', 15, 'a:9:{s:31:"home:ImportantPipelineDashboard";a:6:{i:0;a:2:{s:4:"name";s:10:"First Name";s:5:"width";i:85;}i:1;a:2:{s:4:"name";s:9:"Last Name";s:5:"width";i:75;}i:2;a:2:{s:4:"name";s:6:"Status";s:5:"width";i:75;}i:3;a:2:{s:4:"name";s:8:"Position";s:5:"width";i:275;}i:4;a:2:{s:4:"name";s:7:"Company";s:5:"width";i:210;}i:5;a:2:{s:4:"name";s:8:"Modified";s:5:"width";i:80;}}s:18:"home:CallsDataGrid";a:2:{i:0;a:2:{s:4:"name";s:4:"Time";s:5:"width";i:90;}i:1;a:2:{s:4:"name";s:4:"Name";s:5:"width";i:175;}}s:25:"activity:ActivityDataGrid";a:7:{i:0;a:2:{s:4:"name";s:4:"Date";s:5:"width";i:110;}i:1;a:2:{s:4:"name";s:10:"First Name";s:5:"width";i:85;}i:2;a:2:{s:4:"name";s:9:"Last Name";s:5:"width";i:75;}i:3;a:2:{s:4:"name";s:9:"Regarding";s:5:"width";i:125;}i:4;a:2:{s:4:"name";s:8:"Activity";s:5:"width";i:65;}i:5;a:2:{s:4:"name";s:5:"Notes";s:5:"width";i:240;}i:6;a:2:{s:4:"name";s:10:"Entered By";s:5:"width";i:60;}}s:37:"joborders:JobOrdersListByViewDataGrid";a:12:{i:0;a:2:{s:4:"name";s:11:"Attachments";s:5:"width";i:10;}i:1;a:2:{s:4:"name";s:2:"ID";s:5:"width";i:26;}i:2;a:2:{s:4:"name";s:5:"Title";s:5:"width";i:170;}i:3;a:2:{s:4:"name";s:7:"Company";s:5:"width";i:135;}i:4;a:2:{s:4:"name";s:4:"Type";s:5:"width";i:30;}i:5;a:2:{s:4:"name";s:6:"Status";s:5:"width";i:40;}i:6;a:2:{s:4:"name";s:7:"Created";s:5:"width";i:55;}i:7;a:2:{s:4:"name";s:3:"Age";s:5:"width";i:30;}i:8;a:2:{s:4:"name";s:9:"Submitted";s:5:"width";i:18;}i:9;a:2:{s:4:"name";s:8:"Pipeline";s:5:"width";i:18;}i:10;a:2:{s:4:"name";s:9:"Recruiter";s:5:"width";i:65;}i:11;a:2:{s:4:"name";s:5:"Owner";s:5:"width";i:55;}}s:39:"candidates:candidatesListByViewDataGrid";a:9:{i:0;a:2:{s:4:"name";s:11:"Attachments";s:5:"width";i:31;}i:1;a:2:{s:4:"name";s:10:"First Name";s:5:"width";i:75;}i:2;a:2:{s:4:"name";s:9:"Last Name";s:5:"width";i:85;}i:3;a:2:{s:4:"name";s:4:"City";s:5:"width";i:75;}i:4;a:2:{s:4:"name";s:5:"State";s:5:"width";i:50;}i:5;a:2:{s:4:"name";s:10:"Key Skills";s:5:"width";i:215;}i:6;a:2:{s:4:"name";s:5:"Owner";s:5:"width";i:65;}i:7;a:2:{s:4:"name";s:7:"Created";s:5:"width";i:60;}i:8;a:2:{s:4:"name";s:8:"Modified";s:5:"width";i:60;}}s:37:"companies:CompaniesListByViewDataGrid";a:9:{i:0;a:2:{s:4:"name";s:11:"Attachments";s:5:"width";i:10;}i:1;a:2:{s:4:"name";s:4:"Name";s:5:"width";i:255;}i:2;a:2:{s:4:"name";s:4:"Jobs";s:5:"width";i:40;}i:3;a:2:{s:4:"name";s:4:"City";s:5:"width";i:90;}i:4;a:2:{s:4:"name";s:5:"State";s:5:"width";i:50;}i:5;a:2:{s:4:"name";s:5:"Phone";s:5:"width";i:85;}i:6;a:2:{s:4:"name";s:5:"Owner";s:5:"width";i:65;}i:7;a:2:{s:4:"name";s:7:"Created";s:5:"width";i:60;}i:8;a:2:{s:4:"name";s:8:"Modified";s:5:"width";i:60;}}s:35:"contacts:ContactsListByViewDataGrid";a:9:{i:0;a:2:{s:4:"name";s:11:"Attachments";s:5:"width";i:10;}i:1;a:2:{s:4:"name";s:10:"First Name";s:5:"width";i:80;}i:2;a:2:{s:4:"name";s:9:"Last Name";s:5:"width";i:80;}i:3;a:2:{s:4:"name";s:7:"Company";s:5:"width";i:135;}i:4;a:2:{s:4:"name";s:5:"Title";s:5:"width";i:135;}i:5;a:2:{s:4:"name";s:10:"Work Phone";s:5:"width";i:85;}i:6;a:2:{s:4:"name";s:5:"Owner";s:5:"width";i:85;}i:7;a:2:{s:4:"name";s:7:"Created";s:5:"width";i:60;}i:8;a:2:{s:4:"name";s:8:"Modified";s:5:"width";i:60;}}s:19:"lists:ListsDataGrid";a:7:{i:0;a:2:{s:4:"name";s:5:"Count";s:5:"width";i:45;}i:1;a:2:{s:4:"name";s:11:"Description";s:5:"width";i:355;}i:2;a:2:{s:4:"name";s:9:"Data Type";s:5:"width";i:75;}i:3;a:2:{s:4:"name";s:9:"List Type";s:5:"width";i:75;}i:4;a:2:{s:4:"name";s:5:"Owner";s:5:"width";i:75;}i:5;a:2:{s:4:"name";s:7:"Created";s:5:"width";i:60;}i:6;a:2:{s:4:"name";s:8:"Modified";s:5:"width";i:60;}}s:53:"candidates:candidatesSavedListByViewDataGrid:s:1:"1";";a:9:{i:0;a:2:{s:4:"name";s:11:"Attachments";s:5:"width";i:31;}i:1;a:2:{s:4:"name";s:10:"First Name";s:5:"width";i:75;}i:2;a:2:{s:4:"name";s:9:"Last Name";s:5:"width";i:85;}i:3;a:2:{s:4:"name";s:4:"City";s:5:"width";i:75;}i:4;a:2:{s:4:"name";s:5:"State";s:5:"width";i:50;}i:5;a:2:{s:4:"name";s:10:"Key Skills";s:5:"width";i:200;}i:6;a:2:{s:4:"name";s:5:"Owner";s:5:"width";i:65;}i:7;a:2:{s:4:"name";s:8:"Modified";s:5:"width";i:60;}i:8;a:2:{s:4:"name";s:13:"Added To List";s:5:"width";i:75;}}}', 0, '', '', '', '', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0); INSERT INTO `company` -(`company_id`, `site_id`, `billing_contact`, `name`, `address`, `address2`, `city`, `state`, `zip`, `phone1`, `phone2`, `url`, `key_technologies`, `notes`, `entered_by`, `owner`, `date_created`, `date_modified`, `is_hot`, `fax_number`, `import_id`, `default_company`) +(`company_id`, `site_id`, `billing_contact`, `name`, `address`, `address2`, `city`, `state`, `zip`, `country`, `phone1`, `phone2`, `url`, `key_technologies`, `notes`, `entered_by`, `owner`, `date_created`, `date_modified`, `is_hot`, `fax_number`, `import_id`, `default_company`) VALUES -(20001, 1, NULL, 'Internal Postings', '', '', '', '', '', '', '', '', '', '', 0, 0, '2009-11-19 10:00:20', '2009-11-19 10:00:20', 0, '', NULL, 1), -(20002, 1, NULL, 'Google', '', '', '', '', '', '', '', '', '', '', 1, 1, '2016-08-10 14:47:24', '2016-08-10 14:47:24', 0, '', NULL, 0); +(20001, 1, NULL, 'Internal Postings', '', '', '', '', '', NULL, '', '', '', '', '', 0, 0, '2009-11-19 10:00:20', '2009-11-19 10:00:20', 0, '', NULL, 1), +(20002, 1, NULL, 'Google', '', '', '', '', '', NULL, '', '', '', '', '', 1, 1, '2016-08-10 14:47:24', '2016-08-10 14:47:24', 0, '', NULL, 0); INSERT INTO `contact` -(`contact_id`, `company_id`, `site_id`, `last_name`, `first_name`, `title`, `email1`, `email2`, `phone_work`, `phone_cell`, `phone_other`, `address`, `city`, `state`, `zip`, `is_hot`, `notes`, `entered_by`, `owner`, `date_created`, `date_modified`, `left_company`, `import_id`, `company_department_id`, `reports_to`) +(`contact_id`, `company_id`, `site_id`, `last_name`, `first_name`, `title`, `email1`, `email2`, `phone_work`, `phone_cell`, `phone_other`, `address`, `city`, `state`, `zip`, `country`, `is_hot`, `notes`, `entered_by`, `owner`, `date_created`, `date_modified`, `left_company`, `import_id`, `company_department_id`, `reports_to`) VALUES -(30001, 20002, 1, 'Blue', 'Elizabeth', 'Google HR', 'elizabeth@blue.com', '', '', '', '', '', '', '', '', 0, '', 1, 1, '2016-08-10 14:47:47', '2016-08-10 15:04:48', 0, 0, 0, 0); +(30001, 20002, 1, 'Blue', 'Elizabeth', 'Google HR', 'elizabeth@blue.com', '', '', '', '', '', '', '', '', NULL, 0, '', 1, 1, '2016-08-10 14:47:47', '2016-08-10 15:04:48', 0, 0, 0, 0); INSERT INTO `candidate` -(`candidate_id`, `site_id`, `last_name`, `first_name`, `middle_name`, `phone_home`, `phone_cell`, `phone_work`, `address`, `city`, `state`, `zip`, `source`, `date_available`, `can_relocate`, `notes`, `key_skills`, `current_employer`, `entered_by`, `owner`, `date_created`, `date_modified`, `email1`, `email2`, `web_site`, `import_id`, `is_hot`, `eeo_ethnic_type_id`, `eeo_veteran_type_id`, `eeo_disability_status`, `eeo_gender`, `desired_pay`, `current_pay`, `is_active`, `is_admin_hidden`, `best_time_to_call`) +(`candidate_id`, `site_id`, `last_name`, `first_name`, `middle_name`, `phone_home`, `phone_cell`, `phone_work`, `address`, `city`, `state`, `zip`, `country`, `source`, `date_available`, `can_relocate`, `notes`, `key_skills`, `current_employer`, `entered_by`, `owner`, `date_created`, `date_modified`, `email1`, `email2`, `web_site`, `import_id`, `is_hot`, `eeo_ethnic_type_id`, `eeo_veteran_type_id`, `eeo_disability_status`, `eeo_gender`, `desired_pay`, `current_pay`, `is_active`, `is_admin_hidden`, `best_time_to_call`) VALUES -(20000, 1, 'Tuk', 'Pipin', '', '', '', '', '', '', '', '', '(none)', NULL, 0, '', '', '', 1, 1, '2016-08-10 14:48:32', '2016-08-10 14:48:57', '', '', '', 0, 0, 0, 0, '', '', '', '', 1, 0, ''); +(20000, 1, 'Tuk', 'Pipin', '', '', '', '', '', '', '', '', NULL, '(none)', NULL, 0, '', '', '', 1, 1, '2016-08-10 14:48:32', '2016-08-10 14:48:57', '', '', '', 0, 0, 0, 0, '', '', '', '', 1, 0, ''); INSERT INTO `joborder` -(`joborder_id`, `recruiter`, `contact_id`, `company_id`, `entered_by`, `owner`, `site_id`, `client_job_id`, `title`, `description`, `notes`, `type`, `duration`, `rate_max`, `salary`, `status`, `is_hot`, `openings`, `city`, `state`, `start_date`, `date_created`, `date_modified`, `public`, `company_department_id`, `is_admin_hidden`, `openings_available`, `questionnaire_id`) +(`joborder_id`, `recruiter`, `contact_id`, `company_id`, `entered_by`, `owner`, `site_id`, `client_job_id`, `title`, `description`, `notes`, `type`, `duration`, `rate_max`, `salary`, `status`, `is_hot`, `openings`, `city`, `state`, `country`, `start_date`, `date_created`, `date_modified`, `public`, `company_department_id`, `is_admin_hidden`, `openings_available`, `questionnaire_id`) VALUES -(40001, 1, 30001, 20002, 1, 1, 1, '', 'OpenCATS Tester', '', '', 'H', '', '', '', 'Active', 0, 1, 'London', 'United Kingdom', NULL, '2016-08-10 14:48:21', '2016-08-10 15:03:11', 0, 0, 0, 1, NULL); +(40001, 1, 30001, 20002, 1, 1, 1, '', 'OpenCATS Tester', '', '', 'H', '', '', '', 'Active', 0, 1, 'London', NULL, 'GB', NULL, '2016-08-10 14:48:21', '2016-08-10 15:03:11', 0, 0, 0, 1, NULL); INSERT INTO `candidate_joborder` (`candidate_joborder_id`, `candidate_id`, `joborder_id`, `site_id`, `status`, `date_submitted`, `date_created`, `date_modified`, `rating_value`, `added_by`) From 724fee2f4779f5c50e2a0fd980fbaa1edf533ee6 Mon Sep 17 00:00:00 2001 From: anonymoususer72041 <247563575+anonymoususer72041@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:00:00 +0200 Subject: [PATCH 2/6] Add country fields to company, contact, candidate and job orders --- ajax/getCompanyLocation.php | 1 + ajax/getCompanyLocationAndDepartments.php | 1 + constants.php | 51 +++++++++++++++++++ js/company.js | 21 ++++++++ js/contact.js | 18 ++++++- lib/Candidates.php | 24 +++++++-- lib/Companies.php | 25 +++++++-- lib/Contacts.php | 41 +++++++++++++-- lib/JobOrders.php | 22 ++++++-- lib/TemplateUtility.php | 36 +++++++++++++ modules/candidates/Add.tpl | 9 ++++ modules/candidates/CandidatesUI.php | 11 +++- modules/candidates/Edit.tpl | 9 ++++ modules/companies/Add.tpl | 9 ++++ modules/companies/CompaniesUI.php | 18 +++++-- modules/companies/Edit.tpl | 9 ++++ modules/contacts/Add.tpl | 9 ++++ modules/contacts/ContactsUI.php | 9 +++- modules/contacts/Edit.tpl | 9 ++++ modules/joborders/Add.tpl | 22 ++++++++ modules/joborders/Edit.tpl | 11 ++++ modules/joborders/JobOrdersUI.php | 8 ++- src/OpenCATS/Entity/Company.php | 13 +++++ src/OpenCATS/Entity/CompanyRepository.php | 3 ++ src/OpenCATS/Entity/JobOrder.php | 13 +++++ src/OpenCATS/Entity/JobOrderRepository.php | 3 ++ .../Tests/UnitTests/CompanyRepositoryTest.php | 9 +++- src/OpenCATS/Tests/UnitTests/JobOrderTest.php | 10 +++- test/features/bootstrap/FeatureContext.php | 1 + 29 files changed, 398 insertions(+), 27 deletions(-) diff --git a/ajax/getCompanyLocation.php b/ajax/getCompanyLocation.php index a0cce48f0..b87568fba 100755 --- a/ajax/getCompanyLocation.php +++ b/ajax/getCompanyLocation.php @@ -61,6 +61,7 @@ " " . $locationArray['city'] . "\n" . " " . $locationArray['state'] . "\n" . " " . $locationArray['zip'] . "\n" . + " " . $locationArray['country'] . "\n" . "\n" ); diff --git a/ajax/getCompanyLocationAndDepartments.php b/ajax/getCompanyLocationAndDepartments.php index 25abb2023..71e5b2a4f 100755 --- a/ajax/getCompanyLocationAndDepartments.php +++ b/ajax/getCompanyLocationAndDepartments.php @@ -67,6 +67,7 @@ " " . $locationArray['city'] . "\n" . " " . $locationArray['state'] . "\n" . " " . $locationArray['zip'] . "\n" . + " " . $locationArray['country'] . "\n" . " " . $departmentsString . "\n" . "\n" ); diff --git a/constants.php b/constants.php index 48d4f0239..91b74bb75 100644 --- a/constants.php +++ b/constants.php @@ -282,6 +282,57 @@ array(12, 'GMT+13:00 Nuku`alofa') ); +/* Countries */ +$countries = array( + 'AE' => 'United Arab Emirates', + 'AR' => 'Argentina', + 'AT' => 'Austria', + 'AU' => 'Australia', + 'BE' => 'Belgium', + 'BG' => 'Bulgaria', + 'BR' => 'Brazil', + 'CA' => 'Canada', + 'CH' => 'Switzerland', + 'CL' => 'Chile', + 'CN' => 'China', + 'CO' => 'Colombia', + 'CZ' => 'Czech Republic', + 'DE' => 'Germany', + 'DK' => 'Denmark', + 'EG' => 'Egypt', + 'ES' => 'Spain', + 'FI' => 'Finland', + 'FR' => 'France', + 'GB' => 'United Kingdom', + 'GR' => 'Greece', + 'HK' => 'Hong Kong', + 'HU' => 'Hungary', + 'IE' => 'Ireland', + 'IL' => 'Israel', + 'IN' => 'India', + 'IT' => 'Italy', + 'JP' => 'Japan', + 'KR' => 'South Korea', + 'MA' => 'Morocco', + 'MX' => 'Mexico', + 'NL' => 'Netherlands', + 'NO' => 'Norway', + 'NZ' => 'New Zealand', + 'PE' => 'Peru', + 'PL' => 'Poland', + 'PT' => 'Portugal', + 'RO' => 'Romania', + 'SA' => 'Saudi Arabia', + 'SE' => 'Sweden', + 'SG' => 'Singapore', + 'SK' => 'Slovakia', + 'TN' => 'Tunisia', + 'TR' => 'Turkey', + 'TW' => 'Taiwan', + 'US' => 'United States', + 'ZA' => 'South Africa' +); + /* These file extensions will have '.txt' appended to them on upload. */ $badFileExtensions = array( 'shtml', diff --git a/js/company.js b/js/company.js index 2687b6f76..0acc93d4f 100755 --- a/js/company.js +++ b/js/company.js @@ -41,6 +41,10 @@ function CompanyLocation_populate(companySelectID, sessionCookie) { document.getElementById("city").value = ""; document.getElementById("state").value = ""; + if (document.getElementById("country")) + { + document.getElementById("country").value = ""; + } return; } @@ -92,6 +96,10 @@ function CompanyLocation_populate(companySelectID, sessionCookie) document.getElementById("city").value = ""; document.getElementById("state").value = ""; + if (document.getElementById("country")) + { + document.getElementById("country").value = ""; + } if (document.getElementById("zip")) { @@ -105,6 +113,7 @@ function CompanyLocation_populate(companySelectID, sessionCookie) var cityNode = http.responseXML.getElementsByTagName("city").item(0); var stateNode = http.responseXML.getElementsByTagName("state").item(0); var zipNode = http.responseXML.getElementsByTagName("zip").item(0); + var countryNode = http.responseXML.getElementsByTagName("country").item(0); if (document.getElementById("address")) { @@ -147,6 +156,18 @@ function CompanyLocation_populate(companySelectID, sessionCookie) document.getElementById("zip").value = ""; } } + + if (document.getElementById("country")) + { + if (countryNode.firstChild) + { + document.getElementById("country").value = countryNode.firstChild.nodeValue; + } + else + { + document.getElementById("country").value = ""; + } + } } AJAX_callCATSFunction( diff --git a/js/contact.js b/js/contact.js index a35a0f44f..08411b29f 100755 --- a/js/contact.js +++ b/js/contact.js @@ -90,6 +90,10 @@ function ContactDepartments_populate(companyID, sessionCookie) document.getElementById("city").value = ""; document.getElementById("state").value = ""; document.getElementById("zip").value = ""; + if (document.getElementById("country")) + { + document.getElementById("country").value = ""; + } return; } @@ -97,6 +101,7 @@ function ContactDepartments_populate(companyID, sessionCookie) var cityNode = http.responseXML.getElementsByTagName("city").item(0); var stateNode = http.responseXML.getElementsByTagName("state").item(0); var zipNode = http.responseXML.getElementsByTagName("zip").item(0); + var countryNode = http.responseXML.getElementsByTagName("country").item(0); var departmentsNode = http.responseXML.getElementsByTagName("departments").item(0); if (document.getElementById("address")) @@ -142,6 +147,18 @@ function ContactDepartments_populate(companyID, sessionCookie) } } + if (document.getElementById("country")) + { + if (countryNode.firstChild) + { + document.getElementById("country").value = countryNode.firstChild.nodeValue; + } + else + { + document.getElementById("country").value = ""; + } + } + if (departmentsNode.firstChild) { document.getElementById("departmentsCSV").value = departmentsNode.firstChild.nodeValue; @@ -166,4 +183,3 @@ function ContactDepartments_populate(companyID, sessionCookie) false ); } - diff --git a/lib/Candidates.php b/lib/Candidates.php index 5020326aa..ef4de5b72 100755 --- a/lib/Candidates.php +++ b/lib/Candidates.php @@ -97,7 +97,7 @@ public function add($firstName, $middleName, $lastName, $email1, $email2, $source, $keySkills, $dateAvailable, $currentEmployer, $canRelocate, $currentPay, $desiredPay, $notes, $webSite, $bestTimeToCall, $enteredBy, $owner, $gender = '', $race = '', $veteran = '', $disability = '', - $skipHistory = false) + $skipHistory = false, $country = '') { $sql = sprintf( "INSERT INTO candidate ( @@ -114,6 +114,7 @@ public function add($firstName, $middleName, $lastName, $email1, $email2, city, state, zip, + country, source, key_skills, date_available, @@ -160,6 +161,7 @@ public function add($firstName, $middleName, $lastName, $email1, $email2, %s, %s, %s, + %s, 0, %s, %s, @@ -183,6 +185,7 @@ public function add($firstName, $middleName, $lastName, $email1, $email2, $this->_db->makeQueryString($city), $this->_db->makeQueryString($state), $this->_db->makeQueryString($zip), + $this->_db->makeQueryStringOrNULL($country), $this->_db->makeQueryString($source), $this->_db->makeQueryString($keySkills), $this->_db->makeQueryStringOrNULL($dateAvailable), @@ -256,8 +259,20 @@ public function update($candidateID, $isActive, $firstName, $middleName, $lastNa $city, $state, $zip, $source, $keySkills, $dateAvailable, $currentEmployer, $canRelocate, $currentPay, $desiredPay, $notes, $webSite, $bestTimeToCall, $owner, $isHot, $email, $emailAddress, - $gender = '', $race = '', $veteran = '', $disability = '') + $gender = '', $race = '', $veteran = '', $disability = '', $country = false) { + if ($country === false) + { + $countrySQL = ",\n"; + } + else + { + $countrySQL = sprintf( + ",\n country = %s,\n", + $this->_db->makeQueryStringOrNULL($country) + ); + } + $sql = sprintf( "UPDATE candidate @@ -275,7 +290,7 @@ public function update($candidateID, $isActive, $firstName, $middleName, $lastNa address2 = %s, city = %s, state = %s, - zip = %s, + zip = %s%s source = %s, key_skills = %s, date_available = %s, @@ -311,6 +326,7 @@ public function update($candidateID, $isActive, $firstName, $middleName, $lastNa $this->_db->makeQueryString($city), $this->_db->makeQueryString($state), $this->_db->makeQueryString($zip), + $countrySQL, $this->_db->makeQueryString($source), $this->_db->makeQueryString($keySkills), $this->_db->makeQueryStringOrNULL($dateAvailable), @@ -481,6 +497,7 @@ public function get($candidateID) candidate.city AS city, candidate.state AS state, candidate.zip AS zip, + candidate.country AS country, candidate.source AS source, candidate.key_skills AS keySkills, candidate.current_employer AS currentEmployer, @@ -618,6 +635,7 @@ public function getForEditing($candidateID) candidate.city AS city, candidate.state AS state, candidate.zip AS zip, + candidate.country AS country, candidate.source AS source, candidate.key_skills AS keySkills, candidate.current_employer AS currentEmployer, diff --git a/lib/Companies.php b/lib/Companies.php index 6f4c3330a..917358a77 100755 --- a/lib/Companies.php +++ b/lib/Companies.php @@ -85,7 +85,7 @@ public function __construct($siteID) */ public function add($name, $address, $address2, $city, $state, $zip, $phone1, $phone2, $faxNumber, $url, $keyTechnologies, $isHot, - $notes, $enteredBy, $owner) + $notes, $enteredBy, $owner, $country = '') { $company= Company::create( $this->_siteID, @@ -95,6 +95,7 @@ public function add($name, $address, $address2, $city, $state, $zip, $phone1, $city, $state, $zip, + $country, $phone1, $phone2, $faxNumber, @@ -137,8 +138,20 @@ public function add($name, $address, $address2, $city, $state, $zip, $phone1, public function update($companyID, $name, $address, $address2, $city, $state, $zip, $phone1, $phone2, $faxNumber, $url, $keyTechnologies, $isHot, $notes, $owner, - $billingContact, $email, $emailAddress) + $billingContact, $email, $emailAddress, $country = false) { + if ($country === false) + { + $countrySQL = ",\n"; + } + else + { + $countrySQL = sprintf( + ",\n country = %s,\n", + $this->_db->makeQueryStringOrNULL($country) + ); + } + $sql = sprintf( "UPDATE company @@ -148,7 +161,7 @@ public function update($companyID, $name, $address, $address2, $city, $state, address2 = %s, city = %s, state = %s, - zip = %s, + zip = %s%s phone1 = %s, phone2 = %s, fax_number = %s, @@ -169,6 +182,7 @@ public function update($companyID, $name, $address, $address2, $city, $state, $this->_db->makeQueryString($city), $this->_db->makeQueryString($state), $this->_db->makeQueryString($zip), + $countrySQL, $this->_db->makeQueryString($phone1), $this->_db->makeQueryString($phone2), $this->_db->makeQueryString($faxNumber), @@ -329,6 +343,7 @@ public function get($companyID) company.city AS city, company.state AS state, company.zip AS zip, + company.country AS country, company.phone1 AS phone1, company.phone2 AS phone2, company.fax_number AS faxNumber, @@ -389,6 +404,7 @@ public function getForEditing($companyID) company.city AS city, company.state AS state, company.zip AS zip, + company.country AS country, company.phone1 AS phone1, company.phone2 AS phone2, company.fax_number AS faxNumber, @@ -517,7 +533,8 @@ public function getLocationArray($companyID) company.address AS address, company.city AS city, company.state AS state, - company.zip AS zip + company.zip AS zip, + company.country AS country FROM company WHERE diff --git a/lib/Contacts.php b/lib/Contacts.php index e2670d541..31202c0b9 100755 --- a/lib/Contacts.php +++ b/lib/Contacts.php @@ -81,7 +81,7 @@ public function __construct($siteID) */ public function add($companyID, $firstName, $lastName, $title, $department, $reportsTo, $email1, $email2, $phoneWork, $phoneCell, $phoneOther, $address, $address2, - $city, $state, $zip, $isHot, $notes, $enteredBy, $owner) + $city, $state, $zip, $isHot, $notes, $enteredBy, $owner, $country = '') { /* Get the department ID of the selected department. */ $departmentID = $this->getDepartmentIDByName( @@ -106,6 +106,7 @@ public function add($companyID, $firstName, $lastName, $title, $department, city, state, zip, + country, is_hot, left_company, notes, @@ -133,6 +134,7 @@ public function add($companyID, $firstName, $lastName, $title, $department, %s, %s, %s, + %s, 0, %s, %s, @@ -157,6 +159,7 @@ public function add($companyID, $firstName, $lastName, $title, $department, $this->_db->makeQueryString($city), $this->_db->makeQueryString($state), $this->_db->makeQueryString($zip), + $this->_db->makeQueryStringOrNULL($country), ($isHot ? '1' : '0'), $this->_db->makeQueryString($notes), $this->_db->makeQueryInteger($enteredBy), @@ -209,13 +212,25 @@ public function add($companyID, $firstName, $lastName, $title, $department, public function update($contactID, $companyID, $firstName, $lastName, $title, $department, $reportsTo, $email1, $email2, $phoneWork, $phoneCell, $phoneOther, $address, $address2, $city, $state, $zip, $isHot, - $leftCompany, $notes, $owner, $email, $emailAddress) + $leftCompany, $notes, $owner, $email, $emailAddress, $country = false) { /* Get the department ID of the selected department. */ $departmentID = $this->getDepartmentIDByName( $department, $companyID, $this->_db ); + if ($country === false) + { + $countrySQL = ",\n"; + } + else + { + $countrySQL = sprintf( + ",\n contact.country = %s,\n", + $this->_db->makeQueryStringOrNULL($country) + ); + } + $sql = sprintf( "UPDATE contact @@ -235,7 +250,7 @@ public function update($contactID, $companyID, $firstName, $lastName, contact.address2 = %s, contact.city = %s, contact.state = %s, - contact.zip = %s, + contact.zip = %s%s contact.is_hot = %s, contact.left_company = %s, contact.notes = %s, @@ -261,6 +276,7 @@ public function update($contactID, $companyID, $firstName, $lastName, $this->_db->makeQueryString($city), $this->_db->makeQueryString($state), $this->_db->makeQueryString($zip), + $countrySQL, ($isHot ? '1' : '0'), ($leftCompany ? '1' : '0'), $this->_db->makeQueryString($notes), @@ -312,8 +328,20 @@ public function update($contactID, $companyID, $firstName, $lastName, * @return boolean True if successful; false otherwise. */ public function updateByCompany($companyID, $address, $address2, $city, - $state, $zip) + $state, $zip, $country = false) { + if ($country === false) + { + $countrySQL = ",\n"; + } + else + { + $countrySQL = sprintf( + ",\n country = %s,\n", + $this->_db->makeQueryStringOrNULL($country) + ); + } + $sql = sprintf( "UPDATE contact @@ -322,7 +350,7 @@ public function updateByCompany($companyID, $address, $address2, $city, address2 = %s, city = %s, state = %s, - zip = %s, + zip = %s%s date_modified = NOW() WHERE left_company != 1 @@ -335,6 +363,7 @@ public function updateByCompany($companyID, $address, $address2, $city, $this->_db->makeQueryString($city), $this->_db->makeQueryString($state), $this->_db->makeQueryString($zip), + $countrySQL, $this->_db->makeQueryInteger($companyID), $this->_siteID ); @@ -451,6 +480,7 @@ public function get($contactID) contact.city AS city, contact.state AS state, contact.zip AS zip, + contact.country AS country, contact.notes AS notes, contact.is_hot AS isHotContact, contact.left_company AS leftCompany, @@ -527,6 +557,7 @@ public function getForEditing($contactID) contact.city AS city, contact.state AS state, contact.zip AS zip, + contact.country AS country, contact.notes AS notes, contact.is_hot AS isHotContact, contact.left_company AS leftCompany, diff --git a/lib/JobOrders.php b/lib/JobOrders.php index ce46d55af..c0cc2893a 100755 --- a/lib/JobOrders.php +++ b/lib/JobOrders.php @@ -94,7 +94,7 @@ public function __construct($siteID) public function add($title, $companyId, $contactId, $description, $notes, $duration, $maxRate, $type, $isHot, $public, $openings, $companyJobId, $salary, $city, $state, $startDate, $enteredBy, $recruiter, $owner, - $department, $questionnaire = false) + $department, $questionnaire = false, $country = '') { /* Get the department ID of the selected department. */ // FIXME: Move this up to the UserInterface level. I don't like this @@ -120,6 +120,7 @@ public function add($title, $companyId, $contactId, $description, $notes, $salary, $city, $state, + $country, $startDate, $enteredBy, $recruiter, @@ -163,7 +164,7 @@ public function add($title, $companyId, $contactId, $description, $notes, public function update($jobOrderID, $title, $companyJobID, $companyID, $contactID, $description, $notes, $duration, $maxRate, $type, $isHot, $openings, $openingsAvailable, $salary, $city, $state, $startDate, $status, $recruiter, - $owner, $public, $email, $emailAddress, $department, $questionnaire = false) + $owner, $public, $email, $emailAddress, $department, $questionnaire = false, $country = false) { /* Get the department ID of the selected department. */ // FIXME: Move this up to the UserInterface level. I don't like this @@ -173,6 +174,18 @@ public function update($jobOrderID, $title, $companyJobID, $companyID, $department, $companyID, $this->_db ); + if ($country === false) + { + $countrySQL = ",\n"; + } + else + { + $countrySQL = sprintf( + ",\n country = %s,\n", + $this->_db->makeQueryStringOrNULL($country) + ); + } + // FIXME: Is the OrNULL usage below correct? Can these fields be NULL? $sql = sprintf( "UPDATE @@ -194,7 +207,7 @@ public function update($jobOrderID, $title, $companyJobID, $companyID, status = %s, salary = %s, city = %s, - state = %s, + state = %s%s company_department_id = %s, recruiter = %s, owner = %s, @@ -222,6 +235,7 @@ public function update($jobOrderID, $title, $companyJobID, $companyID, $this->_db->makeQueryString($salary), $this->_db->makeQueryString($city), $this->_db->makeQueryStringOrNULL($state), + $countrySQL, $this->_db->makeQueryInteger($departmentID), $this->_db->makeQueryInteger($recruiter), $this->_db->makeQueryInteger($owner), @@ -392,6 +406,7 @@ public function get($jobOrderID) joborder.status AS status, joborder.city AS city, joborder.state AS state, + joborder.country AS country, joborder.recruiter AS recruiter, joborder.owner AS owner, joborder.public AS public, @@ -506,6 +521,7 @@ public function getForEditing($jobOrderID) joborder.status AS status, joborder.city AS city, joborder.state AS state, + joborder.country AS country, joborder.recruiter AS recruiter, joborder.owner AS owner, joborder.public AS public, diff --git a/lib/TemplateUtility.php b/lib/TemplateUtility.php index 8c0c5406b..f6c509224 100755 --- a/lib/TemplateUtility.php +++ b/lib/TemplateUtility.php @@ -257,6 +257,42 @@ public static function printTimeZoneSelect($selectID, $selectStyle, echo ''; } + /** + * Prints a country selection dropdown list. + * + * @param string ID and name attributes of the country select input + * @param string selected country code + * @param boolean include blank option + * @return void + */ + public static function printCountrySelect($selectID, $selectedCode, $includeBlank = true) + { + $selectedCode = strtoupper(trim($selectedCode)); + if (strlen($selectedCode) != 2 || !isset($GLOBALS['countries'][$selectedCode])) + { + $selectedCode = ''; + } + + echo ''; + } + /** * Prints the Quick Search box and MRU list. * diff --git a/modules/candidates/Add.tpl b/modules/candidates/Add.tpl index ebd9a8c06..36368f5a4 100755 --- a/modules/candidates/Add.tpl +++ b/modules/candidates/Add.tpl @@ -271,6 +271,15 @@ + + + + + + preassignedFields['country']) ? $this->preassignedFields['country'] : ''), true); ?> + + + diff --git a/modules/candidates/CandidatesUI.php b/modules/candidates/CandidatesUI.php index 78383a35c..1edf02c77 100755 --- a/modules/candidates/CandidatesUI.php +++ b/modules/candidates/CandidatesUI.php @@ -1030,6 +1030,7 @@ public function checkParsingFunctions() 'city' => $this->getTrimmedInput('city', $_POST), 'state' => $this->getTrimmedInput('state', $_POST), 'zip' => $this->getTrimmedInput('zip', $_POST), + 'country' => $this->getTrimmedInput('country', $_POST), 'source' => $this->getTrimmedInput('source', $_POST), 'keySkills' => $this->getTrimmedInput('keySkills', $_POST), 'currentEmployer' => $this->getTrimmedInput('currentEmployer', $_POST), @@ -1433,6 +1434,7 @@ private function onEdit() $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); $zip = $this->getTrimmedInput('zip', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $source = $this->getTrimmedInput('source', $_POST); $keySkills = $this->getTrimmedInput('keySkills', $_POST); $currentEmployer = $this->getTrimmedInput('currentEmployer', $_POST); @@ -1491,7 +1493,8 @@ private function onEdit() $gender, $race, $veteran, - $disability + $disability, + ($country == '' ? false : $country) ); if (!$updateSuccess) { @@ -2839,6 +2842,7 @@ private function _addCandidate($isModal, $directoryOverride = '') $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); $zip = $this->getTrimmedInput('zip', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $source = $this->getTrimmedInput('source', $_POST); $keySkills = $this->getTrimmedInput('keySkills', $_POST); $currentEmployer = $this->getTrimmedInput('currentEmployer', $_POST); @@ -2903,7 +2907,9 @@ private function _addCandidate($isModal, $directoryOverride = '') $gender, $race, $veteran, - $disability + $disability, + false, + $country ); @@ -3917,6 +3923,7 @@ private function addDuplicates() $this->_template->assign('isFinishedMode', true); $this->_template->display('./modules/candidates/LinkDuplicity.tpl'); } + } ?> diff --git a/modules/candidates/Edit.tpl b/modules/candidates/Edit.tpl index ed1d5aa70..3b547f64a 100755 --- a/modules/candidates/Edit.tpl +++ b/modules/candidates/Edit.tpl @@ -162,6 +162,15 @@ + + + + + + data['country'], true); ?> + + + diff --git a/modules/companies/Add.tpl b/modules/companies/Add.tpl index 3e0c2d69e..48003038a 100755 --- a/modules/companies/Add.tpl +++ b/modules/companies/Add.tpl @@ -116,6 +116,15 @@ + + + + + + + + + diff --git a/modules/companies/CompaniesUI.php b/modules/companies/CompaniesUI.php index b551aa243..e6074ec87 100755 --- a/modules/companies/CompaniesUI.php +++ b/modules/companies/CompaniesUI.php @@ -599,6 +599,7 @@ private function onAdd() $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); $zip = $this->getTrimmedInput('zip', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $keyTechnologies = $this->getTrimmedInput('keyTechnologies', $_POST); $notes = $this->getTrimmedInput('notes', $_POST); @@ -618,7 +619,7 @@ private function onAdd() $companyID = $companies->add( $name, $address, $address2, $city, $state, $zip, $phone1, $phone2, $faxNumber, $url, $keyTechnologies, $isHot, - $notes, $this->_userID, $this->_userID + $notes, $this->_userID, $this->_userID, $country ); if ($companyID <= 0) @@ -871,6 +872,7 @@ private function onEdit() $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); $zip = $this->getTrimmedInput('zip', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $keyTechnologies = $this->getTrimmedInput('keyTechnologies', $_POST); $notes = $this->getTrimmedInput('notes', $_POST); @@ -894,7 +896,8 @@ private function onEdit() if (!$companies->update($companyID, $name, $address, $address2, $city, $state, $zip, $phone1, $phone2, $faxNumber, $url, $keyTechnologies, - $isHot, $notes, $owner, $billingContact, $email, $emailAddress)) + $isHot, $notes, $owner, $billingContact, $email, $emailAddress, + ($country == '' ? false : $country))) { CommonErrors::fatal(COMMONERROR_RECORDERROR, $this, 'Failed to update company.'); } @@ -910,7 +913,15 @@ private function onEdit() if ($_POST['updateContacts'] == 'yes') { $contacts = new Contacts($this->_siteID); - $contacts->updateByCompany($companyID, $address, $address2, $city, $state, $zip); + $contacts->updateByCompany( + $companyID, + $address, + $address2, + $city, + $state, + $zip, + ($country == '' ? false : $country) + ); } } @@ -1276,6 +1287,7 @@ private function _formatListByViewResults($resultSet) return $resultSet; } + } ?> diff --git a/modules/companies/Edit.tpl b/modules/companies/Edit.tpl index 3d79d8f44..ff4ae0c60 100755 --- a/modules/companies/Edit.tpl +++ b/modules/companies/Edit.tpl @@ -179,6 +179,15 @@ + + + + + + data['country'], true); ?> + + + Edit all contacts address information to match company address?
diff --git a/modules/contacts/Add.tpl b/modules/contacts/Add.tpl index dea3d7291..33ff4c6e5 100755 --- a/modules/contacts/Add.tpl +++ b/modules/contacts/Add.tpl @@ -210,6 +210,15 @@ + + + + + + + + + diff --git a/modules/contacts/ContactsUI.php b/modules/contacts/ContactsUI.php index a84257f82..52c972fb8 100755 --- a/modules/contacts/ContactsUI.php +++ b/modules/contacts/ContactsUI.php @@ -537,6 +537,7 @@ private function onAdd() $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); $zip = $this->getTrimmedInput('zip', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $notes = $this->getTrimmedInput('notes', $_POST); /* Hot contact? */ @@ -565,7 +566,8 @@ private function onAdd() $contactID = $contacts->add( $companyID, $firstName, $lastName, $title, $department, $reportsTo, $email1, $email2, $phoneWork, $phoneCell, $phoneOther, $address, $address2, - $city, $state, $zip, $isHot, $notes, $this->_userID, $this->_userID + $city, $state, $zip, $isHot, $notes, $this->_userID, $this->_userID, + $country ); if ($contactID <= 0) @@ -826,6 +828,7 @@ private function onEdit() $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); $zip = $this->getTrimmedInput('zip', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $notes = $this->getTrimmedInput('notes', $_POST); $isHot = $this->isChecked('isHot', $_POST); @@ -853,7 +856,8 @@ private function onEdit() if (!$contacts->update($contactID, $companyID, $firstName, $lastName, $title, $department, $reportsTo, $email1, $email2, $phoneWork, $phoneCell, $phoneOther, $address, $address2, $city, $state, $zip, $isHot, - $leftCompany, $notes, $owner, $email, $emailAddress)) + $leftCompany, $notes, $owner, $email, $emailAddress, + ($country == '' ? false : $country))) { CommonErrors::fatal(COMMONERROR_RECORDERROR, $this, 'Failed to update contact.'); } @@ -1614,6 +1618,7 @@ private function _addActivityScheduleEvent($regardingID, $directoryOverride = '' './modules/contacts/AddActivityScheduleEventModal.tpl' ); } + } ?> diff --git a/modules/contacts/Edit.tpl b/modules/contacts/Edit.tpl index 87d36cbba..1683a154b 100755 --- a/modules/contacts/Edit.tpl +++ b/modules/contacts/Edit.tpl @@ -229,6 +229,15 @@ + + + + + + + data['country'], true); ?> + + diff --git a/modules/joborders/Add.tpl b/modules/joborders/Add.tpl index af66cf0ed..b369a7169 100755 --- a/modules/joborders/Add.tpl +++ b/modules/joborders/Add.tpl @@ -181,6 +181,28 @@ + + + + + + selectedCompanyID !== false && isset($this->selectedCompanyLocation['country'])) + { + $selectedCountry = $this->selectedCompanyLocation['country']; + } + else if (isset($this->jobOrderSourceRS['country'])) + { + $selectedCountry = $this->jobOrderSourceRS['country']; + } + TemplateUtility::printCountrySelect('country', $selectedCountry, true); + ?> + +   +   + + diff --git a/modules/joborders/Edit.tpl b/modules/joborders/Edit.tpl index c7bf8364e..0dce45e1e 100755 --- a/modules/joborders/Edit.tpl +++ b/modules/joborders/Edit.tpl @@ -189,6 +189,17 @@ + + + + + + data['country'], true); ?> + +   +   + + diff --git a/modules/joborders/JobOrdersUI.php b/modules/joborders/JobOrdersUI.php index 18bd4ad72..3dfb3999c 100755 --- a/modules/joborders/JobOrdersUI.php +++ b/modules/joborders/JobOrdersUI.php @@ -817,6 +817,7 @@ private function onAdd() $type = $this->getTrimmedInput('type', $_POST); $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $duration = $this->getTrimmedInput('duration', $_POST); $department = $this->getTrimmedInput('department', $_POST); $maxRate = $this->getTrimmedInput('maxRate', $_POST); @@ -837,7 +838,7 @@ private function onAdd() $title, $companyID, $contactID, $description, $notes, $duration, $maxRate, $type, $isHot, $isPublic, $openings, $companyJobID, $salary, $city, $state, $startDate, $this->_userID, $recruiter, - $owner, $department, $questionnaireID + $owner, $department, $questionnaireID, $country ); if ($jobOrderID <= 0) @@ -1154,6 +1155,7 @@ private function onEdit() $type = $this->getTrimmedInput('type', $_POST); $city = $this->getTrimmedInput('city', $_POST); $state = $this->getTrimmedInput('state', $_POST); + $country = $this->getTrimmedInput('country', $_POST); $status = $this->getTrimmedInput('status', $_POST); $duration = $this->getTrimmedInput('duration', $_POST); $department = $this->getTrimmedInput('department', $_POST); @@ -1173,7 +1175,8 @@ private function onEdit() if (!$jobOrders->update($jobOrderID, $title, $companyJobID, $companyID, $contactID, $description, $notes, $duration, $maxRate, $type, $isHot, $openings, $openingsAvailable, $salary, $city, $state, $startDate, $status, $recruiter, - $owner, $public, $email, $emailAddress, $department, $questionnaireID)) + $owner, $public, $email, $emailAddress, $department, $questionnaireID, + ($country == '' ? false : $country))) { CommonErrors::fatal(COMMONERROR_RECORDERROR, $this, 'Failed to update job order.'); } @@ -2083,6 +2086,7 @@ private function _formatListByViewResults($resultSet) return $resultSet; } + } ?> diff --git a/src/OpenCATS/Entity/Company.php b/src/OpenCATS/Entity/Company.php index da91e8c3b..70b67c0b2 100644 --- a/src/OpenCATS/Entity/Company.php +++ b/src/OpenCATS/Entity/Company.php @@ -10,6 +10,7 @@ class Company private $city; private $state; private $zipCode; + private $country; private $phoneNumberOne; private $phoneNumberTwo; private $faxNumber; @@ -85,6 +86,16 @@ function getZipCode() { return $this->zipCode; } + + function setCountry($value) + { + $this->country = $value; + } + + function getCountry() + { + return $this->country; + } function setPhoneNumberOne($value) { @@ -188,6 +199,7 @@ static function create( $city, $state, $zipCode, + $country, $phoneNumberOne, $phoneNumberTwo, $faxNumber, @@ -205,6 +217,7 @@ static function create( $company->setCity($city); $company->setState($state); $company->setZipCode($zipCode); + $company->setCountry($country); $company->setPhoneNumberOne($phoneNumberOne); $company->setPhoneNumberTwo($phoneNumberTwo); $company->setFaxNumber($faxNumber); diff --git a/src/OpenCATS/Entity/CompanyRepository.php b/src/OpenCATS/Entity/CompanyRepository.php index 8fe4c27d5..4cc01c57d 100644 --- a/src/OpenCATS/Entity/CompanyRepository.php +++ b/src/OpenCATS/Entity/CompanyRepository.php @@ -23,6 +23,7 @@ function persist(Company $company, \History $history) city, state, zip, + country, phone1, phone2, fax_number, @@ -53,6 +54,7 @@ function persist(Company $company, \History $history) %s, %s, %s, + %s, NOW(), NOW() )", @@ -62,6 +64,7 @@ function persist(Company $company, \History $history) $this->databaseConnection->makeQueryString($company->getCity()), $this->databaseConnection->makeQueryString($company->getState()), $this->databaseConnection->makeQueryString($company->getZipCode()), + $this->databaseConnection->makeQueryStringOrNULL($company->getCountry()), $this->databaseConnection->makeQueryString($company->getPhoneNumberOne()), $this->databaseConnection->makeQueryString($company->getPhoneNumberTwo()), $this->databaseConnection->makeQueryString($company->getFaxNumber()), diff --git a/src/OpenCATS/Entity/JobOrder.php b/src/OpenCATS/Entity/JobOrder.php index 86e8f9a77..7ecc0bc8f 100644 --- a/src/OpenCATS/Entity/JobOrder.php +++ b/src/OpenCATS/Entity/JobOrder.php @@ -22,6 +22,7 @@ class JobOrder private $salary; private $city; private $state; + private $country; private $startDate; private $enteredBy; private $recruiter; @@ -189,6 +190,16 @@ function getState() { return $this->state; } + + function setCountry($value) + { + $this->country = $value; + } + + function getCountry() + { + return $this->country; + } function getDepartmentId() { @@ -277,6 +288,7 @@ static function create( $salary, $city, $state, + $country, $startDate, $enteredBy, $recruiter, @@ -305,6 +317,7 @@ static function create( $instance->setOpenings($openings); $instance->setAvailableOpenings($openings); $instance->setSalary($salary); + $instance->setCountry($country); $instance->setDepartmemtId($departmentId); $instance->setEnteredBy($enteredBy); $instance->setRecruiter($recruiter); diff --git a/src/OpenCATS/Entity/JobOrderRepository.php b/src/OpenCATS/Entity/JobOrderRepository.php index 041114b28..f22c48fd9 100644 --- a/src/OpenCATS/Entity/JobOrderRepository.php +++ b/src/OpenCATS/Entity/JobOrderRepository.php @@ -37,6 +37,7 @@ function persist(JobOrder $jobOrder, \History $history) salary, city, state, + country, company_department_id, start_date, entered_by, @@ -71,6 +72,7 @@ function persist(JobOrder $jobOrder, \History $history) %s, %s, %s, + %s, NOW(), NOW(), %s, @@ -92,6 +94,7 @@ function persist(JobOrder $jobOrder, \History $history) $this->databaseConnection->makeQueryString($jobOrder->getSalary()), $this->databaseConnection->makeQueryString($jobOrder->getCity()), $this->databaseConnection->makeQueryStringOrNULL($jobOrder->getState()), + $this->databaseConnection->makeQueryStringOrNULL($jobOrder->getCountry()), $this->databaseConnection->makeQueryInteger($jobOrder->getDepartmentId()), $this->databaseConnection->makeQueryStringOrNULL($jobOrder->getStartDate()), $this->databaseConnection->makeQueryInteger($jobOrder->getEnteredBy()), diff --git a/src/OpenCATS/Tests/UnitTests/CompanyRepositoryTest.php b/src/OpenCATS/Tests/UnitTests/CompanyRepositoryTest.php index c7a74fe04..fd00f0e1c 100644 --- a/src/OpenCATS/Tests/UnitTests/CompanyRepositoryTest.php +++ b/src/OpenCATS/Tests/UnitTests/CompanyRepositoryTest.php @@ -20,6 +20,7 @@ class CompanyRepositoryTests extends TestCase const CITY = "Colonia"; const STATE = "Maldonado"; const ZIP_CODE = "31337"; + const COUNTRY = "US"; const PHONE_NUMBER_ONE = "+53 123 45678"; const PHONE_NUMBER_TWO = "+53 987 65432"; const FAX_NUMBER = '+53 123 65432'; @@ -50,6 +51,11 @@ function test_persist_CreatesNewCompany_InputValuesAreEscaped() [$this->equalTo(self::KEY_TECHNOLOGIES)], [$this->equalTo(self::NOTES)] ); + $databaseConnectionMock->expects($this->exactly(1)) + ->method('makeQueryStringOrNULL') + ->withConsecutive( + [$this->equalTo(self::COUNTRY)] + ); $databaseConnectionMock->expects($this->exactly(2)) ->method('makeQueryInteger') ->withConsecutive( @@ -114,7 +120,7 @@ private function getHistoryMock() private function getDatabaseConnectionMock() { return $this->getMockBuilder('\DatabaseConnection') - ->setMethods(['makeQueryString', 'makeQueryInteger', 'query', 'getLastInsertID']) + ->setMethods(['makeQueryString', 'makeQueryStringOrNULL', 'makeQueryInteger', 'query', 'getLastInsertID']) ->getMock(); } @@ -128,6 +134,7 @@ private function createCompany() self::CITY, self::STATE, self::ZIP_CODE, + self::COUNTRY, self::PHONE_NUMBER_ONE, self::PHONE_NUMBER_TWO, self::FAX_NUMBER, diff --git a/src/OpenCATS/Tests/UnitTests/JobOrderTest.php b/src/OpenCATS/Tests/UnitTests/JobOrderTest.php index 7127cb89b..5b9f6adc9 100644 --- a/src/OpenCATS/Tests/UnitTests/JobOrderTest.php +++ b/src/OpenCATS/Tests/UnitTests/JobOrderTest.php @@ -21,6 +21,7 @@ class JobOrderTest extends TestCase const JOB_ORDER_SALARY = 30000; const CITY = 'Colonia'; const STATE = 'MALDONADO'; + const COUNTRY = 'US'; const JOB_ORDER_START_DATE = '2016-05-02'; const JOB_ORDER_ENTERED_BY = 31337; const JOB_ORDER_RECRUITER = 31337; @@ -125,6 +126,12 @@ function test_create_CreateAndGetState_ReturnsState() $jobOrder = $this->createJobOrder(); $this->assertEquals(self::STATE, $jobOrder->getState()); } + + function test_create_CreateAndGetCountry_ReturnsCountry() + { + $jobOrder = $this->createJobOrder(); + $this->assertEquals(self::COUNTRY, $jobOrder->getCountry()); + } function test_create_CreateAndGetDepartmentId_ReturnsDepartmentId() { @@ -187,6 +194,7 @@ private function createJobOrder() self::JOB_ORDER_SALARY, self::CITY, self::STATE, + self::COUNTRY, self::JOB_ORDER_START_DATE, self::JOB_ORDER_ENTERED_BY, self::JOB_ORDER_RECRUITER, @@ -195,4 +203,4 @@ private function createJobOrder() self::JOB_ORDER_QUESTIONNAIRE ); } -} \ No newline at end of file +} diff --git a/test/features/bootstrap/FeatureContext.php b/test/features/bootstrap/FeatureContext.php index 5c1d11d43..311c5dad4 100644 --- a/test/features/bootstrap/FeatureContext.php +++ b/test/features/bootstrap/FeatureContext.php @@ -393,6 +393,7 @@ public function thereIsAJobOrderForAFor($jobTitle, $companyName) '', '', '', + '', '' ); $JobOrderRepository = new JobOrderRepository(DatabaseConnection::getInstance()); From 01a1019721d1c74bab8684c24b0a3e7adfb0bbd7 Mon Sep 17 00:00:00 2001 From: anonymoususer72041 <247563575+anonymoususer72041@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:00:00 +0200 Subject: [PATCH 3/6] Add country field support in Career Portal --- modules/careers/CareersUI.php | 96 +++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/modules/careers/CareersUI.php b/modules/careers/CareersUI.php index 9cdddf814..9a297f624 100755 --- a/modules/careers/CareersUI.php +++ b/modules/careers/CareersUI.php @@ -43,6 +43,7 @@ include_once(LEGACY_ROOT . '/lib/DocumentToText.php'); include_once(LEGACY_ROOT . '/lib/FileUtility.php'); include_once(LEGACY_ROOT . '/lib/ParseUtility.php'); +include_once(LEGACY_ROOT . '/lib/StringUtility.php'); class CareersUI extends UserInterface { @@ -254,6 +255,30 @@ private function careersPage() $content = str_replace('', '', $content); $content = str_replace('', '', $content); $content = str_replace('', '', $content); + $selectedCountryCode = strtoupper(trim((string) $candidate['country'])); + if (strlen($selectedCountryCode) != 2 || !isset($GLOBALS['countries'][$selectedCountryCode])) + { + $selectedCountryCode = ''; + } + + $countrySelectHTML = ''; + $content = str_replace('', $countrySelectHTML, $content); + $content = str_replace('', $countrySelectHTML, $content); $content = str_replace('', '', $content); $content = str_replace('', '', $content); $content = str_replace('', '', $content); @@ -301,7 +326,7 @@ private function careersPage() // Get the fields (if included in the template) to update $fields = array('firstName', 'lastName', 'email1', 'phoneHome', 'phoneCell', 'phoneWork', 'address', 'address2', - 'city', 'state', 'zip', 'keySkills', 'currentEmployer', 'bestTimeToCall' + 'country', 'city', 'state', 'zip', 'keySkills', 'currentEmployer', 'bestTimeToCall' ); $fieldValues = array(); @@ -318,6 +343,12 @@ private function careersPage() $fieldValues[$field] = $candidate[$field]; } } + $country = strtoupper(trim((string) $country)); + if ($country != '' && !isset($GLOBALS['countries'][$country])) + { + $country = ''; + } + $fieldValues['country'] = $country; // Get the attachment to replace (if exists) $attachmentID = false; @@ -368,7 +399,8 @@ private function careersPage() $candidate['eeoGender'], $candidate['eeoEthnicType'], $candidate['eeoVeteranType'], - $candidate['eeoDisabilityStatus'] + $candidate['eeoDisabilityStatus'], + $country ); $uploadResume = FileUtility::getUploadFileFromPost($siteID, 'careerportaladd', 'file'); @@ -461,6 +493,7 @@ private function careersPage() $city = isset($_POST[$id='city']) ? $_POST[$id] : ''; $state = isset($_POST[$id='state']) ? $_POST[$id] : ''; $zip = isset($_POST[$id='zip']) ? $_POST[$id] : ''; + $country = isset($_POST[$id='country']) ? $_POST[$id] : ''; $phone = isset($_POST[$id='phone']) ? $_POST[$id] : ''; $email = isset($_POST[$id='email']) ? $_POST[$id] : ''; $phoneHome = isset($_POST[$id='phoneHome']) ? $_POST[$id] : ''; @@ -491,6 +524,10 @@ private function careersPage() $city = $candidate['city']; $state = $candidate['state']; $zip = $candidate['zip']; + if (!isset($_POST['country'])) + { + $country = $candidate['country']; + } $phone = $candidate['phoneWork']; $phoneHome = $candidate['phoneHome']; $phoneCell = $candidate['phoneCell']; @@ -526,6 +563,10 @@ private function careersPage() $city = $candidate['city']; $state = $candidate['state']; $zip = $candidate['zip']; + if (!isset($_POST['country'])) + { + $country = $candidate['country']; + } $phone = $candidate['phoneWork']; $phoneHome = $candidate['phoneHome']; $phoneCell = $candidate['phoneCell']; @@ -654,6 +695,29 @@ private function careersPage() $template['Content'] = str_replace('', '', $template['Content']); $template['Content'] = str_replace('', '', $template['Content']); $template['Content'] = str_replace('', '', $template['Content']); + $selectedCountryCode = strtoupper(trim((string) $country)); + if (strlen($selectedCountryCode) != 2 || !isset($GLOBALS['countries'][$selectedCountryCode])) + { + $selectedCountryCode = ''; + } + + $countrySelectHTML = ''; + $template['Content'] = str_replace('', $countrySelectHTML, $template['Content']); $template['Content'] = str_replace('', '', $template['Content']); $template['Content'] = str_replace('', '', $template['Content']); $template['Content'] = str_replace('', '', $template['Content']); @@ -1247,6 +1311,17 @@ private function _makeApplyValidator($template) }'; } + if (strpos($template['Content'], '') !== false) + { + $validator .= ' + if (document.getElementById(\'country\').value == \'\') + { + alert(\'Please select a country.\'); + document.getElementById(\'country\').focus(); + return false; + }'; + } + if (strpos($template['Content'], '') !== false) { $validator .= ' @@ -1523,6 +1598,15 @@ private function onApplyToJobOrder($siteID, $candidateID = false) $city = $this->getSanitisedInput('city', $_POST); $state = $this->getSanitisedInput('state', $_POST); $zip = $this->getSanitisedInput('zip', $_POST); + $country = false; + if (isset($_POST['country'])) + { + $country = strtoupper($this->getTrimmedInput('country', $_POST)); + if ($country != '' && !isset($GLOBALS['countries'][$country])) + { + $country = ''; + } + } $source = $this->getSanitisedInput('source', $_POST); $phone = $this->getSanitisedInput('phone', $_POST); $phoneHome = $this->getSanitisedInput('phoneHome', $_POST); @@ -1569,7 +1653,7 @@ private function onApplyToJobOrder($siteID, $candidateID = false) * Save basic information in a cookie in case the site is using registration to * process repeated postings, etc. */ - $fields = array('firstName', 'lastName', 'email', 'address', 'address2', 'city', 'state', 'zip', 'phone', + $fields = array('firstName', 'lastName', 'email', 'address', 'address2', 'city', 'state', 'zip', 'country', 'phone', 'phoneHome', 'phoneCell' ); $storedVal = ''; @@ -1592,7 +1676,7 @@ private function onApplyToJobOrder($siteID, $candidateID = false) $lastName, $email, $email2, $phoneHome, $phoneCell, $phone, $address, $address2, $city, $state, $zip, $source, $keySkills, '', $employer, '', '', '', $candidate['notes'], '', $bestTimeToCall, $automatedUser['userID'], false, - '', '', $gender, $race, $veteran, $disability + '', '', $gender, $race, $veteran, $disability, $country ); /* Update extra feilds */ @@ -1637,7 +1721,9 @@ private function onApplyToJobOrder($siteID, $candidateID = false) $gender, $race, $veteran, - $disability + $disability, + false, + $country === false ? '' : $country ); /* Update extra fields. */ From cdb932c58db0064028569df8a0f546c26feb7aae Mon Sep 17 00:00:00 2001 From: anonymoususer72041 <247563575+anonymoususer72041@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:00:00 +0200 Subject: [PATCH 4/6] Add country field to default Career Portal apply template --- db/cats_schema.sql | 4 +-- modules/install/Schema.php | 53 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/db/cats_schema.sql b/db/cats_schema.sql index 0bb1ce682..3d4c56d7c 100755 --- a/db/cats_schema.sql +++ b/db/cats_schema.sql @@ -432,9 +432,9 @@ insert into `career_portal_template`(`career_portal_template_id`,`career_portal insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (17,'CATS 2.0','Content - Questionnaire','
\r\n\r\n

\r\n
\r\n\r\n
\r\n
'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (18,'CATS 2.0','Content - Job Details','
\r\n \r\n

Position Details: </h1>\r\n <table id=\"detailsTable\">\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Location:</strong></td>\r\n <td><city>, <state></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Openings:</strong></td>\r\n <td><openings></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Salary Range:</strong></td>\r\n <td><salary></td>\r\n </tr>\r\n </table>\r\n <div id=\"descriptive\">\r\n <p><strong>Description:</strong></p>\r\n <description>\r\n </div>\r\n <div id=\"detailsTools\">\r\n <h2>Perform an action:</h2>\r\n <a-applyToJob onmouseover=\"buttonMouseOver(\'applyToPosition\',true);\" onmouseout=\"buttonMouseOver(\'applyToPosition\',false);\"><img src=\"images/careers_apply.gif\" id=\"applyToPosition\" alt=\"IMAGE: Apply to Position\" /></a>\r\n </div>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (19,'CATS 2.0','Content - Thanks for your Submission','<div id=\"careerContent\">\r\n <h1>Application Submitted For: <title></h1>\r\n <div id=\"descriptive\">\r\n <p>Please check your email inbox — You should receive an email confirmation of your application.</p>\r\n <p>Thank you for submitting your application to us. We will review it shortly and make contact with you soon.</p>\r\n </div>\r\n <div id=\"detailsTools\">\r\n <h2>Perform an action:</h2>\r\n <ul>\r\n <li><a href=\"\">Visit our website</a></li>\r\n </ul>\r\n </div>\r\n </div>'); -insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (20,'CATS 2.0','Content - Apply for Position','<div id=\"careerContent\">\r\n <h1>Applying to: <title></h1>\r\n <div class=\"applyBoxLeft\">\r\n <div><h3>1. Import Resume (or CV) and Populate Fields</h3></div>\r\n <table>\r\n <tr>\r\n <td>\r\n \r\n <input-resumeUploadPreview>\r\n </td>\r\n </tr>\r\n </table>\r\n <br />\r\n\r\n <div><h3>2. Tell us about yourself</h3></div>\r\n <p class=\"instructions\">All fields marked with asterisk (*) are required.</p>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td>\r\n <td><input-firstName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td>\r\n <td><input-lastName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailConfirmLabel\" for=\"emailconfirm\">*Confirm Email:</label></td>\r\n <td><input-emailconfirm></td>\r\n </tr>\r\n </table>\r\n </div>\r\n \r\n <div class=\"applyBoxRight\">\r\n <div><h3>3. How may we contact you?</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td>\r\n <td><input-phone-home></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td>\r\n <td><input-phone-cell></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td>\r\n <td><input-phone></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td>\r\n <td><input-best-time-to-call></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td>\r\n <td><input-address></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td>\r\n <td><input-city></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td>\r\n <td><input-state></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td>\r\n <td><input-zip></td>\r\n </tr>\r\n </table>\r\n <br />\r\n <div><h3>4. Additional Information</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td>\r\n <td><input-keySkills></td>\r\n </tr>\r\n <tr>\r\n <td> </td>\r\n <td><img src=\"images/careers_submit.gif\" onmouseover=\"buttonMouseOver(\'submitApplicationNow\',true)\" onmouseout=\"buttonMouseOver(\'submitApplicationNow\',false)\" style=\"cursor: pointer;\" id=\"submitApplicationNow\" alt=\"Submit Application Now\" onclick=\"if (applyValidate()) { document.applyToJobForm.submit(); }\" /></td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>'); +insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (20,'CATS 2.0','Content - Apply for Position','<div id=\"careerContent\">\r\n <h1>Applying to: <title></h1>\r\n <div class=\"applyBoxLeft\">\r\n <div><h3>1. Import Resume (or CV) and Populate Fields</h3></div>\r\n <table>\r\n <tr>\r\n <td>\r\n \r\n <input-resumeUploadPreview>\r\n </td>\r\n </tr>\r\n </table>\r\n <br />\r\n\r\n <div><h3>2. Tell us about yourself</h3></div>\r\n <p class=\"instructions\">All fields marked with asterisk (*) are required.</p>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td>\r\n <td><input-firstName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td>\r\n <td><input-lastName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailConfirmLabel\" for=\"emailconfirm\">*Confirm Email:</label></td>\r\n <td><input-emailconfirm></td>\r\n </tr>\r\n </table>\r\n </div>\r\n \r\n <div class=\"applyBoxRight\">\r\n <div><h3>3. How may we contact you?</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td>\r\n <td><input-phone-home></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td>\r\n <td><input-phone-cell></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td>\r\n <td><input-phone></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td>\r\n <td><input-best-time-to-call></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td>\r\n <td><input-address></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td>\r\n <td><input-city></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td>\r\n <td><input-state><br /><input-country></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td>\r\n <td><input-zip></td>\r\n </tr>\r\n </table>\r\n <br />\r\n <div><h3>4. Additional Information</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td>\r\n <td><input-keySkills></td>\r\n </tr>\r\n <tr>\r\n <td> </td>\r\n <td><img src=\"images/careers_submit.gif\" onmouseover=\"buttonMouseOver(\'submitApplicationNow\',true)\" onmouseout=\"buttonMouseOver(\'submitApplicationNow\',false)\" style=\"cursor: pointer;\" id=\"submitApplicationNow\" alt=\"Submit Application Now\" onclick=\"if (applyValidate()) { document.applyToJobForm.submit(); }\" /></td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (21,'CATS 2.0','Content - Candidate Registration','<div id=\"careerContent\">\r\n <h1><applyContent>Applying to <title></applyContent></h1>\r\n <center>\r\n <table cellpadding=\"0\" cellspacing=\"0\">\r\n <tr>\r\n <td><label id=\"emailLabel\" for=\"email\"><h2>Enter your e-mail address:</h2></label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td align=\"right\" valign=\"top\"><input-new></td>\r\n <td style=\"line-height: 18px;\">\r\n <applyContent>\r\n <strong>I have not registered on this website.</strong><br />\r\n (I haven\'t applied to any jobs online)\r\n </applyContent>\r\n </td>\r\n </tr>\r\n <tr>\r\n <td align=\"right\" valign=\"top\"><input-registered></td>\r\n <td style=\"line-height: 20px;\">\r\n <strong>I have registered before</strong><br />\r\n and my last name is:<br />\r\n <input-lastName><br />\r\n and my zip code is:<br />\r\n <input-zip><br /><br />\r\n <input-rememberMe> Remember my information for future visits<br /><br />\r\n <input-submit><br /><br />\r\n </td>\r\n </tr>\r\n </table>\r\n </center>\r\n</div>\r\n'); -insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (22,'CATS 2.0','Content - Candidate Profile','<div id=\"careerContent\"> <h1 style=\"padding: 0; margin: 0; border: 0;\">My Profile</h1><h3 style=\"font-weight: normal;\">Any changes you make to your profile will be updated on our website for all past and future jobs you apply for.</h3> <br /> <div class=\"applyBoxLeft\"> <div><h3>1. Tell us about yourself</h3></div> <p class=\"instructions\">All fields marked with asterisk (*) are required.</p> <table> <tr> <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td> <td><input-firstName></td> </tr> <tr> <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td> <td><input-lastName></td> </tr> <tr> <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td> <td><input-email1></td> </tr> <tr> <td colspan=\"2\"> <input-resume> </td> </tr> </table> </div> <div class=\"applyBoxRight\"> <div><h3>2. How may we contact you?</h3></div> <table> <tr> <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td> <td><input-phoneHome></td> </tr> <tr> <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td> <td><input-phoneCell></td> </tr> <tr> <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td> <td><input-phoneWork></td> </tr> <tr> <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td> <td><input-bestTimeToCall></td> </tr> <tr> <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td> <td><input-address></td> </tr> <tr> <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td> <td><input-city></td> </tr> <tr> <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td> <td><input-state></td> </tr> <tr> <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td> <td><input-zip></td> </tr> </table> <br /> <div><h3>3. Additional Information</h3></div> <table> <tr> <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td> <td><input-keySkills></td> </tr> <tr> <td> </td> <td style=\"padding-top: 40px;\"><input-submit></td> </tr> </table> </div></div>'); +insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (22,'CATS 2.0','Content - Candidate Profile','<div id=\"careerContent\"> <h1 style=\"padding: 0; margin: 0; border: 0;\">My Profile</h1><h3 style=\"font-weight: normal;\">Any changes you make to your profile will be updated on our website for all past and future jobs you apply for.</h3> <br /> <div class=\"applyBoxLeft\"> <div><h3>1. Tell us about yourself</h3></div> <p class=\"instructions\">All fields marked with asterisk (*) are required.</p> <table> <tr> <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td> <td><input-firstName></td> </tr> <tr> <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td> <td><input-lastName></td> </tr> <tr> <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td> <td><input-email1></td> </tr> <tr> <td colspan=\"2\"> <input-resume> </td> </tr> </table> </div> <div class=\"applyBoxRight\"> <div><h3>2. How may we contact you?</h3></div> <table> <tr> <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td> <td><input-phoneHome></td> </tr> <tr> <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td> <td><input-phoneCell></td> </tr> <tr> <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td> <td><input-phoneWork></td> </tr> <tr> <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td> <td><input-bestTimeToCall></td> </tr> <tr> <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td> <td><input-address></td> </tr> <tr> <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td> <td><input-city></td> </tr> <tr> <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td> <td><input-state><br /><input-country></td> </tr> <tr> <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td> <td><input-zip></td> </tr> </table> <br /> <div><h3>3. Additional Information</h3></div> <table> <tr> <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td> <td><input-keySkills></td> </tr> <tr> <td> </td> <td style=\"padding-top: 40px;\"><input-submit></td> </tr> </table> </div></div>'); /*Table structure for table `career_portal_template_site` */ diff --git a/modules/install/Schema.php b/modules/install/Schema.php index 9b470e37f..58e04638b 100755 --- a/modules/install/Schema.php +++ b/modules/install/Schema.php @@ -1504,6 +1504,59 @@ public static function get() ALTER TABLE `contact` ADD COLUMN `country` VARCHAR(2) DEFAULT NULL AFTER `zip`; ALTER TABLE `joborder` ADD COLUMN `country` VARCHAR(2) DEFAULT NULL AFTER `state`; ', + '375' => ' + UPDATE + career_portal_template + SET + value = REPLACE(value, \'<td><input-state></td>\', \'<td><input-state><br /><input-country></td>\') + WHERE + career_portal_name = \'CATS 2.0\' + AND setting = \'Content - Apply for Position\' + AND value NOT LIKE \'%<input-country>%\' + AND value LIKE \'%<h1>Applying to: <title></h1>%\' + AND value LIKE \'%<label id="stateCountryLabel" for="stateCountry">*State/Country:</label>%\' + AND value LIKE \'%<label id="zipPostalLabel" for="zipPostal">*Zip/Postal Code:</label>%\' + AND value LIKE \'%<td><input-state></td>%\'; + + UPDATE + career_portal_template_site + SET + value = REPLACE(value, \'<td><input-state></td>\', \'<td><input-state><br /><input-country></td>\') + WHERE + career_portal_name = \'CATS 2.0\' + AND setting = \'Content - Apply for Position\' + AND value NOT LIKE \'%<input-country>%\' + AND value LIKE \'%<h1>Applying to: <title></h1>%\' + AND value LIKE \'%<label id="stateCountryLabel" for="stateCountry">*State/Country:</label>%\' + AND value LIKE \'%<label id="zipPostalLabel" for="zipPostal">*Zip/Postal Code:</label>%\' + AND value LIKE \'%<td><input-state></td>%\'; + + UPDATE + career_portal_template + SET + value = REPLACE(value, \'<td><input-state></td>\', \'<td><input-state><br /><input-country></td>\') + WHERE + career_portal_name = \'CATS 2.0\' + AND setting = \'Content - Candidate Profile\' + AND value NOT LIKE \'%<input-country>%\' + AND value LIKE \'%<h1 style="padding: 0; margin: 0; border: 0;">My Profile</h1>%\' + AND value LIKE \'%<label id="stateCountryLabel" for="stateCountry">*State/Country:</label>%\' + AND value LIKE \'%<label id="zipPostalLabel" for="zipPostal">*Zip/Postal Code:</label>%\' + AND value LIKE \'%<td><input-state></td>%\'; + + UPDATE + career_portal_template_site + SET + value = REPLACE(value, \'<td><input-state></td>\', \'<td><input-state><br /><input-country></td>\') + WHERE + career_portal_name = \'CATS 2.0\' + AND setting = \'Content - Candidate Profile\' + AND value NOT LIKE \'%<input-country>%\' + AND value LIKE \'%<h1 style="padding: 0; margin: 0; border: 0;">My Profile</h1>%\' + AND value LIKE \'%<label id="stateCountryLabel" for="stateCountry">*State/Country:</label>%\' + AND value LIKE \'%<label id="zipPostalLabel" for="zipPostal">*Zip/Postal Code:</label>%\' + AND value LIKE \'%<td><input-state></td>%\'; + ', ); } From 7cccf724fc9f4e33fa3af41fab77608a84e16a44 Mon Sep 17 00:00:00 2001 From: anonymoususer72041 <247563575+anonymoususer72041@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:00:00 +0200 Subject: [PATCH 5/6] Show country in Career Portal job location * Remove legacy `<city>` / `<state>` placeholder handling from the public Career Portal template rendering and rely on `<location>` only * Update the shipped default Job Details template to use `<location>` and add a safe schema migration that upgrades stored default Job Details templates * Note: Custom Career Portal templates that still reference `<city>` and/or `<state>` will no longer render a location and must be updated to use `<location>` --- db/cats_schema.sql | 2 +- lib/JobOrders.php | 1 + modules/careers/CareersUI.php | 42 +++++++++++++++++++--- modules/install/Schema.php | 66 +++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 6 deletions(-) diff --git a/db/cats_schema.sql b/db/cats_schema.sql index 3d4c56d7c..6f69fb07c 100755 --- a/db/cats_schema.sql +++ b/db/cats_schema.sql @@ -430,7 +430,7 @@ insert into `career_portal_template`(`career_portal_template_id`,`career_portal insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (15,'CATS 2.0','CSS','table.sortable\r\n{\r\ntext-align:left;\r\nempty-cells: show;\r\nwidth: 940px;\r\n}\r\ntd\r\n{\r\npadding:5px;\r\n}\r\ntr.rowHeading\r\n{\r\n background: #e0e0e0; border: 1px solid #cccccc; border-left: none; border-right: none;\r\n}\r\ntr.oddTableRow\r\n{\r\nbackground: #ebebeb; \r\n}\r\ntr.evenTableRow\r\n{\r\n background: #ffffff; \r\n}\r\na.sortheader:hover,\r\na.sortheader:link,\r\na.sortheader:visited\r\n{\r\ncolor:#000;\r\n}\r\n\r\nbody, html { margin: 0; padding: 0; background: #ffffff; font: normal 12px/14px Arial, Helvetica, sans-serif; color: #000000; }\r\n#container { margin: 0 auto; padding: 0; width: 940px; height: auto; }\r\n#logo { float: left; margin: 0; }\r\n #logo img { width: 424px; height: 103px; }\r\n#actions { float: right; margin: 0; width: 310px; height: 100px; background: #efefef; border: 1px solid #cccccc; }\r\n #actions img { float: left; margin: 2px 6px 2px 15px; width: 130px; height: 25px; }\r\n#footer { clear: both; margin: 20px auto 0 auto; width: 150px; }\r\n #footer img { width: 137px; height: 38px; }\r\n\r\na:link, a:active { color: #1763b9; }\r\na:hover { color: #c75a01; }\r\na:visited { color: #333333; }\r\nimg { border: none; }\r\n\r\nh1 { margin: 0 0 10px 0; font: bold 18px Arial, Helvetica, sans-serif; }\r\nh2 { margin: 8px 0 8px 15px; font: bold 14px Arial, Helvetica, sans-serif; }\r\nh3 { margin: 0; font: bold 14px Arial, Helvetica, sans-serif; }\r\np { font: normal 12px Arial, Helvetica, sans-serif; }\r\np.instructions { margin: 0 0 0 10px; font: italic 12px Arial, Helvetica, sans-serif; color: #666666; }\r\n\r\n\r\n/* CONTENTS ON PAGE SPECS */\r\n#careerContent { clear: both; padding: 15px 0 0 0; }\r\n\r\n \r\n/* DISPLAY JOB DETAILS */\r\n#detailsTable { width: 400px; }\r\n #detailsTable td.detailsHeader { width: 30%; }\r\ndiv#descriptive { float: left; width: 585px; }\r\ndiv#detailsTools { float: right; padding: 0 0 8px 0; width: 280px; background: #ffffff; border: 1px solid #cccccc; }\r\n div#detailsTools img { margin: 2px 6px 5px 15px; }\r\n\r\n/* DISPLAY APPLICATION FORM */\r\ndiv.applyBoxLeft, div.applyBoxRight { width: 450px; height: 470px; background: #f9f9f9; border: 1px solid #cccccc; border-top: none; }\r\ndiv.applyBoxLeft { float: left; margin: 0 10px 0 0; }\r\ndiv.applyBoxRight { float: right; margin: 0 0 0 10px; }\r\n div.applyBoxLeft div, div.applyBoxRight div { margin: 0 0 5px 0; padding: 3px 10px; background: #efefef; border-top: 1px solid #cccccc; border-bottom: 1px solid #cccccc; }\r\n div.applyBoxLeft table, div.applyBoxRight table { margin: 0 auto; width: 420px; }\r\n div.applyBoxLeft table td, div.applyBoxRight table td { padding: 3px; vertical-align: top; }\r\n td.label { text-align: right; width: 110px; }\r\n form#applyToJobForm { }\r\n form#applyToJobForm label { font-weight: bold; }\r\n form#applyToJobForm input.inputBoxName, form#applyToJobForm input.inputBoxNormal { width: 285px; height: 15px; }\r\n form#applyToJobForm input.submitButton { width: 197px; height: 27px; background: url(\'images/careers_submit.gif\') no-repeat; }\r\n\r\n form#applyToJobForm input.submitButtonDown { width: 197px; height: 27px; background: url(\'images/careers_submit-o.gif\') no-repeat; }\r\n form#applyToJobForm textarea { margin: 8px 0 0 0; width: 410px; height: 170px; }\r\n form#applyToJobForm textarea.inputBoxArea{ width: 285px; height: 70px; }\r\n\r\n'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (16,'CATS 2.0','Content - Search Results','<div id=\"careerContent\">\r\n <registeredCandidate>\r\n <h1>Current Available Openings, Recently Posted Jobs: <numberOfSearchResults></h1>\r\n<searchResultsTable>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (17,'CATS 2.0','Content - Questionnaire','<div id=\"careerContent\">\r\n<questionnaire>\r\n<br /><br />\r\n<div style=\"text-align: right;\">\r\n<submit value=\"Continue\">\r\n</div>\r\n</div>'); -insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (18,'CATS 2.0','Content - Job Details','<div id=\"careerContent\">\r\n <registeredCandidate>\r\n <h1>Position Details: <title></h1>\r\n <table id=\"detailsTable\">\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Location:</strong></td>\r\n <td><city>, <state></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Openings:</strong></td>\r\n <td><openings></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Salary Range:</strong></td>\r\n <td><salary></td>\r\n </tr>\r\n </table>\r\n <div id=\"descriptive\">\r\n <p><strong>Description:</strong></p>\r\n <description>\r\n </div>\r\n <div id=\"detailsTools\">\r\n <h2>Perform an action:</h2>\r\n <a-applyToJob onmouseover=\"buttonMouseOver(\'applyToPosition\',true);\" onmouseout=\"buttonMouseOver(\'applyToPosition\',false);\"><img src=\"images/careers_apply.gif\" id=\"applyToPosition\" alt=\"IMAGE: Apply to Position\" /></a>\r\n </div>\r\n </div>'); +insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (18,'CATS 2.0','Content - Job Details','<div id=\"careerContent\">\r\n <registeredCandidate>\r\n <h1>Position Details: <title></h1>\r\n <table id=\"detailsTable\">\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Location:</strong></td>\r\n <td><location></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Openings:</strong></td>\r\n <td><openings></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Salary Range:</strong></td>\r\n <td><salary></td>\r\n </tr>\r\n </table>\r\n <div id=\"descriptive\">\r\n <p><strong>Description:</strong></p>\r\n <description>\r\n </div>\r\n <div id=\"detailsTools\">\r\n <h2>Perform an action:</h2>\r\n <a-applyToJob onmouseover=\"buttonMouseOver(\'applyToPosition\',true);\" onmouseout=\"buttonMouseOver(\'applyToPosition\',false);\"><img src=\"images/careers_apply.gif\" id=\"applyToPosition\" alt=\"IMAGE: Apply to Position\" /></a>\r\n </div>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (19,'CATS 2.0','Content - Thanks for your Submission','<div id=\"careerContent\">\r\n <h1>Application Submitted For: <title></h1>\r\n <div id=\"descriptive\">\r\n <p>Please check your email inbox — You should receive an email confirmation of your application.</p>\r\n <p>Thank you for submitting your application to us. We will review it shortly and make contact with you soon.</p>\r\n </div>\r\n <div id=\"detailsTools\">\r\n <h2>Perform an action:</h2>\r\n <ul>\r\n <li><a href=\"\">Visit our website</a></li>\r\n </ul>\r\n </div>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (20,'CATS 2.0','Content - Apply for Position','<div id=\"careerContent\">\r\n <h1>Applying to: <title></h1>\r\n <div class=\"applyBoxLeft\">\r\n <div><h3>1. Import Resume (or CV) and Populate Fields</h3></div>\r\n <table>\r\n <tr>\r\n <td>\r\n \r\n <input-resumeUploadPreview>\r\n </td>\r\n </tr>\r\n </table>\r\n <br />\r\n\r\n <div><h3>2. Tell us about yourself</h3></div>\r\n <p class=\"instructions\">All fields marked with asterisk (*) are required.</p>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td>\r\n <td><input-firstName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td>\r\n <td><input-lastName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailConfirmLabel\" for=\"emailconfirm\">*Confirm Email:</label></td>\r\n <td><input-emailconfirm></td>\r\n </tr>\r\n </table>\r\n </div>\r\n \r\n <div class=\"applyBoxRight\">\r\n <div><h3>3. How may we contact you?</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td>\r\n <td><input-phone-home></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td>\r\n <td><input-phone-cell></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td>\r\n <td><input-phone></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td>\r\n <td><input-best-time-to-call></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td>\r\n <td><input-address></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td>\r\n <td><input-city></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td>\r\n <td><input-state><br /><input-country></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td>\r\n <td><input-zip></td>\r\n </tr>\r\n </table>\r\n <br />\r\n <div><h3>4. Additional Information</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td>\r\n <td><input-keySkills></td>\r\n </tr>\r\n <tr>\r\n <td> </td>\r\n <td><img src=\"images/careers_submit.gif\" onmouseover=\"buttonMouseOver(\'submitApplicationNow\',true)\" onmouseout=\"buttonMouseOver(\'submitApplicationNow\',false)\" style=\"cursor: pointer;\" id=\"submitApplicationNow\" alt=\"Submit Application Now\" onclick=\"if (applyValidate()) { document.applyToJobForm.submit(); }\" /></td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (21,'CATS 2.0','Content - Candidate Registration','<div id=\"careerContent\">\r\n <h1><applyContent>Applying to <title></applyContent></h1>\r\n <center>\r\n <table cellpadding=\"0\" cellspacing=\"0\">\r\n <tr>\r\n <td><label id=\"emailLabel\" for=\"email\"><h2>Enter your e-mail address:</h2></label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td align=\"right\" valign=\"top\"><input-new></td>\r\n <td style=\"line-height: 18px;\">\r\n <applyContent>\r\n <strong>I have not registered on this website.</strong><br />\r\n (I haven\'t applied to any jobs online)\r\n </applyContent>\r\n </td>\r\n </tr>\r\n <tr>\r\n <td align=\"right\" valign=\"top\"><input-registered></td>\r\n <td style=\"line-height: 20px;\">\r\n <strong>I have registered before</strong><br />\r\n and my last name is:<br />\r\n <input-lastName><br />\r\n and my zip code is:<br />\r\n <input-zip><br /><br />\r\n <input-rememberMe> Remember my information for future visits<br /><br />\r\n <input-submit><br /><br />\r\n </td>\r\n </tr>\r\n </table>\r\n </center>\r\n</div>\r\n'); diff --git a/lib/JobOrders.php b/lib/JobOrders.php index c0cc2893a..0c6e9e277 100755 --- a/lib/JobOrders.php +++ b/lib/JobOrders.php @@ -654,6 +654,7 @@ public function getAll($status, $userID = -1, $companyID = -1, joborder.duration AS duration, joborder.city AS city, joborder.state AS state, + joborder.country AS country, joborder.status AS status, joborder.company_department_id AS departmentID, joborder.questionnaire_id as questionnaireID, diff --git a/modules/careers/CareersUI.php b/modules/careers/CareersUI.php index 9a297f624..7ac6418e2 100755 --- a/modules/careers/CareersUI.php +++ b/modules/careers/CareersUI.php @@ -964,9 +964,7 @@ private function careersPage() } $jobTitleEscaped = htmlspecialchars((string) $jobOrderData['title'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); - $jobCityEscaped = htmlspecialchars((string) $jobOrderData['city'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); $jobOpeningsEscaped = htmlspecialchars((string) $jobOrderData['openings'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); - $jobStateEscaped = htmlspecialchars((string) $jobOrderData['state'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); $jobTypeEscaped = htmlspecialchars((string) $jobOrders->typeCodeToString($jobOrderData['type']), ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); $jobCreatedEscaped = htmlspecialchars((string) $jobOrderData['dateCreated'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); $jobRecruiterEscaped = htmlspecialchars((string) $jobOrderData['recruiterFullName'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); @@ -978,11 +976,19 @@ private function careersPage() $jobRateEscaped = nl2br(htmlspecialchars((string) $jobOrderData['maxRate'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING)); $jobSalaryEscaped = nl2br(htmlspecialchars((string) $jobOrderData['salary'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING)); $jobDaysOldEscaped = nl2br(htmlspecialchars((string) $jobOrderData['daysOld'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING)); + $jobLocationEscaped = htmlspecialchars( + $this->getLocationString( + $jobOrderData['city'], + $jobOrderData['state'], + $jobOrderData['country'] + ), + ENT_QUOTES | ENT_SUBSTITUTE, + HTML_ENCODING + ); $template['Content'] = str_replace('<registeredCandidate>', $useCookie && $isRegistrationEnabled ? $this->getRegisteredCandidateBlock($siteID, $template['Content - Candidate Registration']) : '', $template['Content']); $template['Content'] = str_replace('<title>', $jobTitleEscaped, $template['Content']); - $template['Content'] = str_replace('<city>', $jobCityEscaped, $template['Content']); + $template['Content'] = str_replace('<location>', $jobLocationEscaped, $template['Content']); $template['Content'] = str_replace('<openings>', $jobOpeningsEscaped, $template['Content']); - $template['Content'] = str_replace('<state>', $jobStateEscaped, $template['Content']); $template['Content'] = str_replace('<type>', $jobTypeEscaped, $template['Content']); $template['Content'] = str_replace('<created>', $jobCreatedEscaped, $template['Content']); $template['Content'] = str_replace('<recruiter>', $jobRecruiterEscaped, $template['Content']); @@ -1555,7 +1561,11 @@ private function getResultsTable($rs, $settings, $unformatted = false, $paramete $html .= '</td>'; $html .= '<td>'; - $html .= htmlspecialchars((string) $line['city'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING) . ', ' . htmlspecialchars((string) $line['state'], ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); + $html .= htmlspecialchars($this->getLocationString( + $line['city'], + $line['state'], + $line['country'] + ), ENT_QUOTES | ENT_SUBSTITUTE, HTML_ENCODING); $html .= '</td>'; $html .= '</tr>'."\n"; @@ -1565,6 +1575,28 @@ private function getResultsTable($rs, $settings, $unformatted = false, $paramete return $html; } + private function getLocationString($city, $state, $country) + { + $city = (string) $city; + $state = (string) $state; + $country = trim((string) $country); + + $location = StringUtility::makeCityStateString($city, $state); + + if ($country == '') + { + return $location; + } + + $countryName = isset($GLOBALS['countries'][$country]) ? $GLOBALS['countries'][$country] : $country; + if ($location == '') + { + return $countryName; + } + + return $location . ', ' . $countryName; + } + /* Called by Careers Page function to handle the processing of candidate input. */ private function onApplyToJobOrder($siteID, $candidateID = false) { diff --git a/modules/install/Schema.php b/modules/install/Schema.php index 58e04638b..f0dc172c6 100755 --- a/modules/install/Schema.php +++ b/modules/install/Schema.php @@ -1557,6 +1557,72 @@ public static function get() AND value LIKE \'%<label id="zipPostalLabel" for="zipPostal">*Zip/Postal Code:</label>%\' AND value LIKE \'%<td><input-state></td>%\'; ', + '376' => ' + UPDATE + career_portal_template + SET + value = REPLACE( + REPLACE( + REPLACE(value, \'<td><city>, <state></td>\', \'<td><location></td>\'), + \'<city>, <state>\', + \'<location>\' + ), + \'<city>,<state>\', + \'<location>\' + ) + WHERE + setting = \'Content - Job Details\' + AND value NOT LIKE \'%<location>%\' + AND + ( + ( + career_portal_name = \'CATS 2.0\' + AND value LIKE \'%<h1>Position Details: <title></h1>%\' + AND value LIKE \'%<td class="detailsHeader"><strong>Location:</strong></td>%\' + AND value LIKE \'%<td class="detailsHeader"><strong>Openings:</strong></td>%\' + AND value LIKE \'%<td class="detailsHeader"><strong>Salary Range:</strong></td>%\' + AND value LIKE \'%<a-applyToJob onmouseover="buttonMouseOver(\'\'applyToPosition\'\',true);" onmouseout="buttonMouseOver(\'\'applyToPosition\'\',false);"><img src="images/careers_apply.gif" id="applyToPosition" alt="IMAGE: Apply to Position" /></a>%\' + ) + OR + ( + value LIKE \'%<p class="noteUnsized">Job Details</p>%\' + AND value LIKE \'%Date Created:%\' + AND value LIKE \'%Location:%\' + ) + ); + + UPDATE + career_portal_template_site + SET + value = REPLACE( + REPLACE( + REPLACE(value, \'<td><city>, <state></td>\', \'<td><location></td>\'), + \'<city>, <state>\', + \'<location>\' + ), + \'<city>,<state>\', + \'<location>\' + ) + WHERE + setting = \'Content - Job Details\' + AND value NOT LIKE \'%<location>%\' + AND + ( + ( + value LIKE \'%<h1>Position Details: <title></h1>%\' + AND value LIKE \'%<td class="detailsHeader"><strong>Location:</strong></td>%\' + AND value LIKE \'%<td class="detailsHeader"><strong>Openings:</strong></td>%\' + AND value LIKE \'%<td class="detailsHeader"><strong>Salary Range:</strong></td>%\' + AND value LIKE \'%<a-applyToJob onmouseover="buttonMouseOver(\'\'applyToPosition\'\',true);" onmouseout="buttonMouseOver(\'\'applyToPosition\'\',false);"><img src="images/careers_apply.gif" id="applyToPosition" alt="IMAGE: Apply to Position" /></a>%\' + ) + OR + ( + value LIKE \'%<p class="noteUnsized">Job Details</p>%\' + AND value LIKE \'%Date Created:%\' + AND value LIKE \'%Location:%\' + ) + ); + ', ); } From 9d31035646c442988ec5e790a7a1ebf1ea5dac01 Mon Sep 17 00:00:00 2001 From: anonymoususer72041 <247563575+anonymoususer72041@users.noreply.github.com> Date: Sat, 25 Apr 2026 11:10:55 +0200 Subject: [PATCH 6/6] Use Google country short name in zip lookup --- lib/ZipLookup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ZipLookup.php b/lib/ZipLookup.php index b19d35d02..60b336902 100755 --- a/lib/ZipLookup.php +++ b/lib/ZipLookup.php @@ -41,7 +41,7 @@ public function getCityStateByZip($zip) $loc_level_3 = (string) $value->long_name; } if ($value->type[0] == 'country') { - $loc_level_4 = (string) $value->long_name; + $loc_level_4 = (string) $value->short_name; } } } else { @@ -53,7 +53,7 @@ public function getCityStateByZip($zip) // Set the state based on US or non-US location $aAddress[2] = $loc_level_1; - if ($loc_level_4 == 'United States') { + if ($loc_level_4 == 'US') { $aAddress[3] = $loc_level_3; } else { $aAddress[3] = $loc_level_2;