<?php
|
namespace JVBase\integrations;
|
|
use JVBase\meta\Form;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
trait Admin {
|
use _Base;
|
//An array of AdminAction objects
|
protected array $actions = [];
|
protected array $instructions = [];
|
|
protected array $fields = [];
|
protected function initializeActions():void
|
{
|
$actions = [
|
[
|
'name' => 'Save Credentials',
|
'label' => 'Save Changes',
|
'icon' => 'floppy-disk',
|
'action' => [$this, 'saveCredentials']
|
],
|
[
|
'name' => 'Clear Credentials',
|
'icon' => 'broom',
|
'action' => [$this, 'clearCredentials']
|
],
|
];
|
foreach ($actions as $a) {
|
$this->addAction($a['name'], $a['action'], $a['slug']??null, $a['icon']??null, $a['label']??null);
|
}
|
}
|
|
public function addAction(string $name, callable $callback, ?string $slug = null, ?string $icon = null, ?string $label = null):void
|
{
|
$action = new AdminActions($name, $callback);
|
if (!is_null($slug)) {
|
$action->setSlug($slug);
|
}
|
if (!is_null($icon)) {
|
$action->setIcon($icon);
|
}
|
if (!is_null($label)) {
|
$action->setLabel($label);
|
}
|
$this->actions[$action->getSlug()] = $action;
|
}
|
/**
|
* @param string $action
|
* @param mixed|null $data
|
* @return array [
|
* 'success' => {bool},
|
* 'message' => {string} optional message,
|
* 'data' => {mixed} optional data to return
|
* ]
|
*/
|
public function processAction(string $action, mixed $data = null):array
|
{
|
if (!array_key_exists($action, $this->actions)) {
|
$this->logError('processAction', 'Attempted action not setup: '.print_r(['action' => $action, 'service' => $this->service_name], true));
|
return $this->response(false, 'Attempted action not set up');
|
}
|
$theAction = $this->actions[$action];
|
if (!$theAction->checkPermission()) {
|
$this->logError('processAction', 'User has no capabilities to perform this action: '.print_r(['action' => $action, 'service' => $this->service_name], true));
|
return $this->response(false, 'Insufficient permissions');
|
}
|
|
$result = $theAction->handleCallback($data);
|
if (is_wp_error($result)) {
|
$this->logError('processAction', $result->get_error_message());
|
return $this->response(false, $result->get_error_message());
|
}
|
|
return $result;
|
}
|
|
|
public function renderConnection(bool $return = false):string
|
{
|
if ($this->userID && !JVB()->userCanConnect($this->service_name, $this->userID)) {
|
return '';
|
}
|
|
$credentials = $this->loadCredentials();
|
$isConnected = !empty($credentials);
|
|
$meta = '';
|
if ($isConnected && array_key_exists('updated_at', $credentials) && $credentials['updated_at'] > 0) {
|
$meta = sprintf(
|
'<div class="meta">
|
<small>Last updated: %s ago</small>
|
</div>',
|
human_time_diff($credentials['updated_at'])
|
);
|
}
|
|
$form = sprintf(
|
'<form id="%s" class="integration %s" data-service="%s" data-save="integrations">
|
<div class="header row x-btw">
|
<h3>%s</h3>
|
<div class="setup">
|
<span class="indicator">%s</span>
|
<span class="text">%sSet Up</span>
|
</div>
|
</div>
|
%s',
|
$this->service_name,
|
$isConnected ? 'connected' : 'disconnected',
|
esc_attr($this->service_name),
|
esc_html($this->title),
|
$isConnected ? '●' : '○',
|
$isConnected ? '' : 'Not ',
|
$meta,
|
);
|
|
if (!empty($this->instructions)) {
|
$form .= sprintf(
|
'<details%s>
|
<summary>Instructions</summary>
|
<ol>%s</ol>
|
</details>',
|
$isConnected ? '' : ' open',
|
implode('',array_map(function($el) {
|
return sprintf('<li>%s</li>', $el);
|
}, $this->instructions))
|
);
|
}
|
|
|
if (current_user_can('manage_options')) {
|
$form .= sprintf(
|
'<details class="initial-setup"%s>
|
<summary>Setup</summary>
|
%s
|
%s
|
</details>',
|
$isConnected ? '' : ' open',
|
$this->outputFields($this->credentialFields),
|
method_exists($this, 'renderWebhookUrl') ? $this->renderWebhookUrl() : ''
|
);
|
}
|
|
if (method_exists($this, 'renderOAuthConnectionForm')) {
|
$form .= $this->renderOAuthConnectionForm();
|
}
|
|
if (!empty($this->optionalFields) || $this->hasExtraOptions) {
|
$form .= '<div class="integration-content">';
|
if (!empty($this->optionalFields)) {
|
$form .= sprintf(
|
'<details class="advanced">
|
<summary>Advanced Settings</summary>%s</details>',
|
$this->outputFields($this->optionalFields)
|
);
|
}
|
if ($this->hasExtraOptions) {
|
$form .= sprintf(
|
'<a href="%s" class="btn">More Settings</a>',
|
$this->determineOptionPage()
|
);
|
}
|
$form .= '</div>';
|
}
|
|
$form .= $this->outputActionButtons();
|
$form .= '</form>';
|
|
if (!$return) {
|
echo $form;
|
}
|
|
return $form;
|
}
|
protected function outputActionButtons():string
|
{
|
return sprintf('<div class="actions row x-btw wrap">%s</div>',implode('', array_map(function($action) {
|
$label = '';
|
if (!empty ($action->getIcon())) {
|
$label .= $this->outputIcon($action->getIcon());
|
}
|
$label .= $action->getLabel();
|
return sprintf(
|
'<button type="button" data-action="%s"%s%s>%s</button>',
|
$action->getSlug,
|
$action->getName(),
|
empty($action->getConfirm()) ? '' : ' data-confirm="'.$action->getConfirm().'"',
|
$label
|
);
|
}, array_filter($this->actions, function ($action) {
|
return $action->checkPermission();
|
}))));
|
}
|
|
protected function outputFields(array $fields):string
|
{
|
$credentials = $this->loadCredentials();
|
$fields = array_filter($fields, function ($field) {
|
return $field->checkPermission();
|
});
|
return implode('', array_map(function($f) use ($credentials) {
|
$value = array_key_exists($f->name, $credentials) ? $credentials[$f->name] : '';
|
$config = $f->getConfig();
|
if (!empty($value)) {
|
$config['readonly'] = true;
|
}
|
$config['base'] = $this->service_name.'_';
|
return Form::render($f->name, $value, $f->getConfig());
|
}, $fields));
|
}
|
|
public function addField(string $name, string $label, string $type, callable|string|bool $permission):Field
|
{
|
$field = new Field($name, $label, $type, $permission);
|
$this->fields[$name] = $field;
|
return $field;
|
}
|
public function setFieldRequired(string $name):bool
|
{
|
if (!array_key_exists($name, $this->fields)) {
|
return false;
|
}
|
$this->fields[$name]->setRequired();
|
return true;
|
}
|
|
}
|