Jake Vanderwerf
10 days ago de317675a8069b747cb253ba3e2b5dc394ca36ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<?php
namespace JVBase\integrations;
 
use JVBase\managers\Cache;
use JVBase\managers\IconsManager;
 
if (!defined('ABSPATH')) {
    exit;
}
 
trait _Base {
    /**
     * @var string Unique identifier for this service (ex: square, facebook)
     */
    protected string $service_name;
    /**
     * @var int|null The user context. If it is an OAuth integration, users may have their own connections, accessible via their user id
     */
    protected ?int $userID = null;
    /**
     * @var string Human-readable service name (ex: 'Google My Business', 'Square', etc)
     */
    public string $title;
    /**
     * @var string Phosphoricons icon slug
     */
    public string $icon = '';
    /**
     * @var string API version string (ex: 'v2', '2024-01-01')
     */
    protected string $apiVersion;
    protected Cache $cache;
    protected ?string $cacheName = null;
    //Use Trait "Requests" to set this
    protected bool $hasRequests = false;
    protected ?RateLimits $requestLimiter = null;
    //Use Trait "OAuth" to set this
    protected ?RateLimits $oauthLimiter = null;
    protected bool $hasOAuth = false;
    //Use trait "Webhooks" to set this true
    protected bool $hasWebhooks = false;
 
    /**
     * @var array Each item in the array becomes a li element in the ordered list of instructions
     */
    protected array $instructions = [];
    /**
     * @var array The required fields for the credentials. Typically a site_key/secret_key or equivalent.
     */
    protected array $credentialFields = [];
    /**
     * @var array The required fields for OAuth connection
     */
    protected array $oauthFields = [];
    /**
     * @var array Optional fields that just tweak functionality
     */
    protected array $optionalFields = [];
    protected bool $supportsWebp = true;
    /**
     * @var bool Flag to indicate there are extra options that warrant a dedicated options page for this service
     * Usually used for default field values for syncable services
     */
    public bool $hasExtraOptions = false;
    public bool $hasBatchCreate = false;
    public bool $hasBatchUpdate = false;
    public bool $hasBatchDelete = false;
    public bool $canCreateOnUpdate = false;
    /**
     * Post Syncing Capabilities
     * Define what sync operations this integration supports
     */
    protected array $canSync = [
        'initial' => false,    // Can share new posts to the service
        'update' => false,     // Can update already-shared posts
        'delete' => false,     // Can remove posts from the service
    ];
 
    /**
     * @var array // Post types that can be synced (e.g., ['artwork', 'tattoo']): usually built by Registrar.php if the integration name exists as a key in [ 'integrations' => []]
     */
    protected array $syncPostTypes = [];
    /**
     * @var array Taxonomies that can be synced (e.g., ['category', 'section']): usually built by Registrar.php if the integration name exists as a key in [ 'integrations' => []]
     */
    protected array $syncTaxonomies = [];
    /**
     * @var array User roles that can be synced (e.g., ['customer']): usually built by Registrar.php if the integration name exists as a key in [ 'integrations' => []]
     */
    protected array $syncUsers = [];
    /**
     * @var array Integration's specific content types. Set by child classes' setContentTypes
     */
    protected array $contentTypes = [];
 
 
    /**
     * Check if integration is properly configured
     */
    public function isSetUp(): bool
    {
        return !empty($this->loadCredentials());
    }
 
    public function loadCredentials():array
    {
        return Auth::getInstance()->getCredentials($this->service_name, $this->userID);
    }
 
    protected function logError(string $method, string $message, array $context = []):void
    {
        $context['service'] = $this->service_name;
        JVB()->error()->log('['.self::class.']'.$method, $message, $context);
    }
 
    protected function getReturnURL():string
    {
        //If we are on the main admin page, we want to go back to our Integrations page on admin
        //If we are on the custom dashboard, we want to go back to that dashboard page
        return is_admin() ?
            admin_url('admin.php?page=jvb-integrations') :
            get_home_url(null, '/dash/integrations/');
    }
    protected function determineOptionPage():string
    {
        return is_admin() ?
            admin_url('admin.php?page=jvb-integrations-'.$this->service_name) :
            get_home_url(null, '/dash/integrations/'.$this->service_name.'/');
    }
 
    protected function outputIcon(string $icon):string
    {
        if (is_admin()) {
            $icons = IconsManager::for('admin');
            return $icons->getRawSvg($icon);
        }
        return jvbDashIcon($icon);
    }
 
    protected function initializeRateLimiters():void
    {
        $key = $this->service_name;
        if (!is_null($this->userID)) {
            $key .= '_'.$this->userID;
        }
 
        if ($this->hasRequests && !isset($this->requestLimiter) && !is_null($this->oauthLimiter)) {
            $this->requestLimiter = new RateLimits($key);
        }
        if ($this->hasOAuth && !isset($this->oauthLimiter) && !is_null($this->oauthLimiter)) {
            $key .= '_oauth';
            $this->oauthLimiter = new RateLimits($key, ['s' => 1,'m' => 10, 'h' => 100]);
        }
    }
 
    public function response(bool $success, string $message, array $data = []):array
    {
        $response = [
            'success'   => $success,
            'message'   => $message
        ];
        if (!empty($data)) {
            $response['data'] = $data;
        }
        return $response;
    }
}