It’s going to be a bit involved. Here’s a step by step with the code.
In the following steps, any time a folder I’m referencing doesn’t exist, create it.
Also be mindful of when a folder or a file name is capitalized and when it’s not.
First, in application\config\generated_overrides\community_store
create a file and call it authorized_us_states.php
Inside put this code:
<?php
/**
* -----------------------------------------------------------------------------
* Generated 2024-09-12T09:17:49-04:00
*
* DO NOT EDIT THIS FILE DIRECTLY
*
* @item list
* @group authorized_us_states
* @namespace community_store
* -----------------------------------------------------------------------------
*/
return [
'list' => [
'CA',
'MN',
'TX',
'WA',
],
];
I added a list of US states code as an example. Follow the same pattern for the states you need.
Then in application\controllers\SinglePage
create the file Checkout.php
Add the following code to it:
<?php
namespace Application\Controller\SinglePage;
use Concrete\Package\CommunityStore\Controller\SinglePage\Checkout as CsCheckout;
class Checkout extends CsCheckout
{
public function view($guest = false)
{
parent::view($guest);
$finalList = ['' => ''];
$statelist = $this->app->make('helper/lists/states_provinces')->getStates();
$authorizedUsStates = \Config::get('community_store::authorized_us_states.list');
foreach ($statelist as $code => $state) {
if (in_array($code, $authorizedUsStates)) {
$finalList[$code] = $state;
}
}
$this->set("states", $finalList);
}
}
Next, in application\controllers\CommunityStore\Utilities
create the file StateProvince.php
In it add the following code
<?php
namespace Application\Controller\CommunityStore\Utilities;
use Concrete\Package\CommunityStore\Src\CommunityStore\Utilities\StateProvince as CSStateProvince;
class StateProvince extends CSStateProvince
{
public function getStates()
{
$service = $this->app->make('helper/security');
$countryCode = $service->sanitizeString($this->request->request->get('country'));
$selectedState = $service->sanitizeString($this->request->request->get('selectedState'));
$type = $service->sanitizeString($this->request->request->get('type'));
$class = empty($this->request->request->get('class')) ? 'form-control' : $service->sanitizeString($this->request->request->get('class'));
$dataList = $this->app->make('helper/json')->decode($this->request->request->get('data'), true);
$data = '';
if (is_array($dataList) && count($dataList)) {
foreach ($dataList as $name => $value) {
$data .= ' data-' . $name . '="' . $value . '"';
}
}
$requiresstate = ['US', 'AU', 'CA', 'CN', 'MX', 'MY'];
$required = '';
if (in_array($countryCode, $requiresstate)) {
$required = ' required="required" ';
}
$ret = '';
$list = $this->app->make('helper/lists/states_provinces')->getStateProvinceArray($countryCode);
if ($list) {
$class = trim(str_replace('form-select', '', $class));
$class .= ' form-select';
if ("tax" == $type) {
$ret .= "<select name='taxState' id='taxState' class='{$class}'{$data}>";
} else {
$ret .= "<select $required name='store-checkout-{$type}-state' id='store-checkout-{$type}-state' ccm-passed-value='' class='{$class}'{$data}>";
}
$ret .= '<option {selected} value=""></option>';
$hasSelectedState = false;
// Here is your list of authorized US states, modify it to suit your needs following the template
$authorizedUsStates = \Config::get('community_store::authorized_us_states.list'); //['CA', 'WA', 'MN'];
foreach ($list as $code => $state) {
if ($countryCode == 'US' && !in_array($code, $authorizedUsStates)) {
continue;
}
if (!empty($selectedState) && $code == $selectedState) {
$ret .= "<option selected value='{$code}'>{$state}</option>";
$hasSelectedState = true;
} else {
$ret .= "<option value='{$code}'>{$state}</option>";
}
}
$ret .= "</select>";
if ($hasSelectedState) {
$ret = str_replace('{selected}', '', $ret);
} else {
$ret = str_replace('{selected}', 'selected', $ret);
}
} else {
$class = trim(str_replace('form-select', '', $class));
if (!$class) {
$class = 'form-control';
}
if ("tax" == $type) {
$ret .= "<input type='text' name='taxState' id='taxState' class='{$class}'{$data} value='$selectedState'>";
} else {
$ret .= "<input type='text' name='store-checkout-{$type}-state' id='store-checkout-{$type}-state' value='{$selectedState}' class='{$class}'{$data} placeholder='" . t('State / Province') . "'>";
}
}
echo $ret;
exit();
}
}
And finally in application\bootstrap
at the bottom of the file app.php
add
//Overriding Community Store StateProvince class
$app->bind(
'\Concrete\Package\CommunityStore\Src\CommunityStore\Utilities\StateProvince',
'\Application\Controller\CommunityStore\Utilities\StateProvince'
);
//Overriding Community Store Checkout page controller
$app->bind(
'\Concrete\Package\CommunityStore\Controller\SinglePage\Checkout',
'\Application\Controller\SinglePage\Checkout'
);
Now your country list, in Community Store only, should only display the states selected in the first step, when the United States are selected in the list.
I hope this helps. Feel free to reach out if something is not clear or not working.