service_name = 'gmb';
$this->title = 'Google My Business';
$this->icon = 'storefront';
$this->canSync = [
'initial' => true,
'update' => true,
'delete' => true,
];
$this->supportsWebp = false;
$this->defineFields();
$this->defineInstructions();
$this->defineOAuth();
$this->defineActions();
parent::__construct();
}
protected function defineFields():void
{
$client_id = $this->addField(
'client_id',
'OAuth Client ID',
'text',
'manage_options'
);
$client_id->setRequired();
$client_id->setHint('From your Google Cloud Console OAuth credentials.');
$secret = $this->addField(
'client_secret',
'OAuth Client Secret',
'text',
'manage_options',
);
$secret->setSubType('password');
$secret->setRequired();
if ($this->getAccessToken()) {
$accs = $this->addField('accounts', 'Accounts', 'select', [$this, 'testUserCanConnect']);
$accs->setHidden();
$accs->setOptions($this->getAccountOptions());
$acc = $this->addField('account_id', 'Set Account', 'select', [$this, 'testUserCanConnect']);
$acc->setOptions($this->loadCredentials()['accounts']??[]);
$acc->setHint('Select the account to connect to.');
if ($this->getAccountID()) {
$locs = $this->addField('locations', 'Locations', 'select', [$this, 'testUserCanConnect']);
$locs->setHidden();
$locs->setOptions($this->getLocationOptions());
$loc = $this->addField('location_id', 'Set Location', 'select', [$this, 'testUserCanConnect']);
$loc->setOptions($this->loadCredentials()['locations']??[]);
$loc->setHint('Select the location to connect to.');
}
}
}
public function testUserCanConnect():bool
{
$user = get_current_user_id();
return $this->userCanConnect($user);
}
protected function defineInstructions():void
{
$this->instructions = [
'Go to Google Cloud Console',
'Create OAuth 2.0 Client ID credentials',
'Enable Google My Business API',
'Add redirect URI: '.esc_html($this->getRedirectUri()).'',
'Use the "Authorize" button below to complete OAuth flow'
];
}
protected function defineOAuth():void
{
$this->oauth = new OAuthURLs(
'https://accounts.google.com/o/oauth2/v2/auth',
'https://oauth2.googleapis.com/token',
'https://oauth2.googleapis.com/revoke'
);
$this->oathScopes = [
'https://www.googleapis.com/auth/business.manage',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/plus.business.manage'
];
}
protected function defineActions():void
{
$this->addAction(
'Update Location',
[$this, 'handleUpdateLocation'],
'update_location',
);
}
public function handleUpdateLocation(array $data):array
{
if (empty($data['location_id']??'')) {
return $this->response(false, 'No location selected');
}
$credentials = [
'location_id' => sanitize_text_field($data['location_id'])
];
return $this->saveCredentials($credentials, false);
}
protected function initialize(): void
{
// TODO: Implement initialize() method.
}
protected function getRequestHeaders(): array
{
// TODO: Implement getRequestHeaders() method.
}
protected function handleResponse(\WP_Error|array $response, string $method, string $endpoint): array
{
if (is_wp_error($response) && $response->get_error_message() === 'rate_limit_exceeded') {
return $this->response(false, 'Rate limit exceeded');
}
return match($endpoint) {
'https://mybusinessaccountmanagement.googleapis.com/v1/accounts' => $this->handleGetAccountsResponse($response, $method),
sprintf('https://mybusinessbusinessinformation.googleapis.com/v1/%s/locations', $this->getAccountID()??'') => $this->handleGetLocationsResponse($response, $method),
default => $this->response(false, 'Unhandled response for '.$endpoint.' endpoint, with method: '.$method)
};
}
protected function refreshAccessToken(OAuthCredentials $credentials): array
{
// TODO: Implement refreshAccessToken() method.
}
/*********************************************************
* UTILITY
*********************************************************/
protected function getAccountID():string|false
{
return $this->loadCredentials()['account_id']??false;
}
protected function getAccountOptions(bool $force = false):array
{
$stored = $this->loadCredentials()['accounts']??[];
if ($force || empty($stored)) {
$stored = $this->getAccounts();
}
return $stored;
}
protected function getLocationID():string|false
{
return $this->loadCredentials()['location_id']??false;
}
protected function getLocationOptions(bool $force = false):array
{
$stored = $this->loadCredentials()['locations']??[];
if ($force || empty($stored)) {
$stored = $this->getLocations();
}
return $stored;
}
protected function getLocations():array|false
{
if (!$this->getAccessToken() || !$this->getAccountID()) {
return false;
}
try {
return $this->getRequest(
sprintf(
'/v1/%s/locations',
$this->getAccountID()
),
[
'readMask' => $this->readMask
]
);
} catch (Exception $e)
{
$this->logError('getLocations', 'Could not get locations: '.$e->getMessage());
return [];
}
}
protected function handleGetLocationsResponse(array $response, string $method):array
{
$locations = [];
if (isset($response['locations'])) {
foreach ($response['locations'] as $loc) {
if (isset($loc['name']) && isset($loc['title'])) {
$locations[$loc['name']] = $loc['title'];
}
}
}
return $locations;
}
protected function getAccounts(bool $force = false):array|false
{
if (!$this->getAccessToken()) {
return false;
}
return $this->getRequest(
'https://mybusinessaccountmanagement.googleapis.com/v1/accounts',
[],
$force
);
}
protected function handleGetAccountsResponse(array $response, string $method):array
{
$accounts = [];
if (isset($response['accounts']) && is_array($response['accounts'])) {
$accounts = $response['accounts'];
} elseif (is_array($response) && isset($response['name'])) {
$accounts = [$response];
}
$options = [];
foreach ($accounts as $account) {
if (isset($account['name']) && isset($account['accountName'])) {
$options[$account['name']] = $account['accountName'];
}
}
return $options;
}
protected function setContentTypes(): void
{
// TODO: Implement setContentTypes() method.
}
protected function formatForService(int $itemID, string $type = 'post'): array
{
// TODO: Implement formatForService() method.
}
}