627 lines
24 KiB
PHP
627 lines
24 KiB
PHP
<?php
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class Ansico_Plugins_Client {
|
|
private $settings;
|
|
|
|
public function __construct($settings = array()) {
|
|
$this->settings = empty($settings) ? Ansico_Plugins::get_settings() : $settings;
|
|
}
|
|
|
|
private function base_url() {
|
|
return trailingslashit((string) $this->settings['forgejo_base_url']);
|
|
}
|
|
|
|
private function owner_name() {
|
|
return trim((string) $this->settings['forgejo_owner']);
|
|
}
|
|
|
|
private function owner_type() {
|
|
$owner_type = isset($this->settings['owner_type']) ? strtolower((string) $this->settings['owner_type']) : 'user';
|
|
return in_array($owner_type, array('org', 'organisation', 'organization'), true) ? 'org' : 'user';
|
|
}
|
|
|
|
private function cache_key($method, $url) {
|
|
return 'ansico_plugins_' . md5(strtoupper((string) $method) . '|' . $url . '|' . wp_json_encode(array(
|
|
'token' => !empty($this->settings['access_token']) ? 1 : 0,
|
|
'ssl' => !empty($this->settings['verify_ssl']) ? 1 : 0,
|
|
)));
|
|
}
|
|
|
|
private function normalize_http_response($response) {
|
|
return array(
|
|
'code' => (int) wp_remote_retrieve_response_code($response),
|
|
'message' => (string) wp_remote_retrieve_response_message($response),
|
|
'body' => (string) wp_remote_retrieve_body($response),
|
|
'headers' => array(),
|
|
);
|
|
}
|
|
|
|
private function parse_json_response($response, $error_code, $error_message) {
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
$body = isset($response['body']) ? (string) $response['body'] : '';
|
|
$data = json_decode($body, true);
|
|
if (JSON_ERROR_NONE !== json_last_error()) {
|
|
return new WP_Error($error_code, $error_message . ' JSON error: ' . json_last_error_msg());
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function get_owner_endpoint() {
|
|
$base = $this->base_url();
|
|
$owner = rawurlencode($this->owner_name());
|
|
|
|
if ('org' === $this->owner_type()) {
|
|
return sprintf('%sapi/v1/orgs/%s/repos?limit=100', $base, $owner);
|
|
}
|
|
|
|
return sprintf('%sapi/v1/users/%s/repos?limit=100', $base, $owner);
|
|
}
|
|
|
|
public function test_connection() {
|
|
$base = $this->base_url();
|
|
if ('' === $base) {
|
|
return new WP_Error('missing_base_url', __('Forgejo base URL mangler.', 'ansico-plugins'));
|
|
}
|
|
|
|
$response = $this->request('GET', $base . 'api/v1/version', false);
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
if ($response['code'] < 200 || $response['code'] >= 300) {
|
|
return new WP_Error('bad_response', sprintf(__('Forgejo svarede med HTTP %d.', 'ansico-plugins'), (int) $response['code']));
|
|
}
|
|
|
|
$body = $this->parse_json_response($response, 'invalid_version', __('Kunne ikke læse version fra Forgejo.', 'ansico-plugins'));
|
|
if (is_wp_error($body)) {
|
|
return $body;
|
|
}
|
|
|
|
return array(
|
|
'version' => isset($body['version']) ? (string) $body['version'] : __('Ukendt', 'ansico-plugins'),
|
|
);
|
|
}
|
|
|
|
public function get_repositories_without_filter() {
|
|
if ('' === $this->base_url() || '' === $this->owner_name()) {
|
|
return new WP_Error('missing_settings', __('Du skal udfylde Forgejo URL og owner/org først.', 'ansico-plugins'));
|
|
}
|
|
|
|
$response = $this->request('GET', $this->get_owner_endpoint());
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
if ($response['code'] < 200 || $response['code'] >= 300) {
|
|
return new WP_Error('repos_http_error', sprintf(__('Repository-endpoint svarede med HTTP %d.', 'ansico-plugins'), (int) $response['code']));
|
|
}
|
|
|
|
$repos = $this->parse_json_response($response, 'invalid_repos', __('Kunne ikke læse repositories fra Forgejo.', 'ansico-plugins'));
|
|
if (is_wp_error($repos)) {
|
|
return $repos;
|
|
}
|
|
|
|
return is_array($repos) ? $repos : array();
|
|
}
|
|
|
|
public function get_repositories() {
|
|
$all_repos = $this->get_repositories_without_filter();
|
|
if (is_wp_error($all_repos)) {
|
|
return $all_repos;
|
|
}
|
|
|
|
$topic_filter = strtolower(trim((string) $this->settings['topic_filter']));
|
|
$filtered = array();
|
|
|
|
foreach ($all_repos as $repo) {
|
|
if (empty($repo['name']) || empty($repo['owner']['login'])) {
|
|
continue;
|
|
}
|
|
|
|
$topics = $this->get_repository_topics_safe($repo);
|
|
$repo['topics'] = $topics;
|
|
$normalized_topics = array_map('strtolower', array_map('strval', (array) $topics));
|
|
|
|
if ('' === $topic_filter || in_array($topic_filter, $normalized_topics, true)) {
|
|
$filtered[] = $repo;
|
|
}
|
|
}
|
|
|
|
return $filtered;
|
|
}
|
|
|
|
public function get_repositories_debug() {
|
|
$all_repos = $this->get_repositories_without_filter();
|
|
if (is_wp_error($all_repos)) {
|
|
return $all_repos;
|
|
}
|
|
|
|
$topic_filter = strtolower(trim((string) $this->settings['topic_filter']));
|
|
$rows = array();
|
|
|
|
foreach ($all_repos as $repo) {
|
|
$owner = !empty($repo['owner']['login']) ? (string) $repo['owner']['login'] : '';
|
|
$name = !empty($repo['name']) ? (string) $repo['name'] : '';
|
|
$topics_result = ($owner !== '' && $name !== '') ? $this->get_repository_topics($owner, $name) : new WP_Error('missing_repo_data', __('Repo mangler owner eller navn.', 'ansico-plugins'));
|
|
$topics = is_wp_error($topics_result) ? array() : (array) $topics_result;
|
|
$release = ($owner !== '' && $name !== '') ? $this->get_latest_release($owner, $name) : new WP_Error('missing_repo_data', __('Repo mangler owner eller navn.', 'ansico-plugins'));
|
|
|
|
$rows[] = array(
|
|
'name' => $name,
|
|
'full_name' => !empty($repo['full_name']) ? (string) $repo['full_name'] : $name,
|
|
'topics' => $topics,
|
|
'matches_filter' => ('' === $topic_filter || in_array($topic_filter, array_map('strtolower', array_map('strval', $topics)), true)),
|
|
'release' => is_wp_error($release) ? '' : (!empty($release['tag_name']) ? (string) $release['tag_name'] : (!empty($release['name']) ? (string) $release['name'] : '')),
|
|
'topics_error' => is_wp_error($topics_result) ? $topics_result->get_error_message() : '',
|
|
'release_error' => is_wp_error($release) ? $release->get_error_message() : '',
|
|
);
|
|
}
|
|
|
|
return $rows;
|
|
}
|
|
|
|
private function get_repository_topics_safe($repo) {
|
|
if (!empty($repo['topics']) && is_array($repo['topics'])) {
|
|
return $repo['topics'];
|
|
}
|
|
|
|
$owner = !empty($repo['owner']['login']) ? (string) $repo['owner']['login'] : '';
|
|
$name = !empty($repo['name']) ? (string) $repo['name'] : '';
|
|
if ('' === $owner || '' === $name) {
|
|
return array();
|
|
}
|
|
|
|
$topics = $this->get_repository_topics($owner, $name);
|
|
if (!is_wp_error($topics)) {
|
|
return (array) $topics;
|
|
}
|
|
|
|
$repo_details = $this->get_repository($owner, $name);
|
|
if (!is_wp_error($repo_details) && !empty($repo_details['topics']) && is_array($repo_details['topics'])) {
|
|
return $repo_details['topics'];
|
|
}
|
|
|
|
return array();
|
|
}
|
|
|
|
public function get_repository($owner, $repo_name) {
|
|
$endpoint = sprintf('%sapi/v1/repos/%s/%s', $this->base_url(), rawurlencode($owner), rawurlencode($repo_name));
|
|
$response = $this->request('GET', $endpoint);
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
if ($response['code'] < 200 || $response['code'] >= 300) {
|
|
return new WP_Error('repo_http_error', sprintf(__('Repository-endpoint svarede med HTTP %d.', 'ansico-plugins'), (int) $response['code']));
|
|
}
|
|
|
|
$repo = $this->parse_json_response($response, 'invalid_repo', __('Kunne ikke læse repository-data.', 'ansico-plugins'));
|
|
return is_wp_error($repo) ? $repo : (is_array($repo) ? $repo : array());
|
|
}
|
|
|
|
public function get_repository_topics($owner, $repo_name) {
|
|
$endpoint = sprintf('%sapi/v1/repos/%s/%s/topics', $this->base_url(), rawurlencode($owner), rawurlencode($repo_name));
|
|
$response = $this->request('GET', $endpoint);
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
if ($response['code'] < 200 || $response['code'] >= 300) {
|
|
return new WP_Error('topics_http_error', sprintf(__('Topics-endpoint svarede med HTTP %d.', 'ansico-plugins'), (int) $response['code']));
|
|
}
|
|
|
|
$body = $this->parse_json_response($response, 'invalid_topics', __('Kunne ikke læse repository-topics.', 'ansico-plugins'));
|
|
if (is_wp_error($body)) {
|
|
return $body;
|
|
}
|
|
|
|
if (isset($body['topics']) && is_array($body['topics'])) {
|
|
return $body['topics'];
|
|
}
|
|
|
|
return is_array($body) ? $body : array();
|
|
}
|
|
|
|
public function get_latest_release($owner, $repo_name) {
|
|
$endpoint = sprintf('%sapi/v1/repos/%s/%s/releases/latest', $this->base_url(), rawurlencode($owner), rawurlencode($repo_name));
|
|
$response = $this->request('GET', $endpoint);
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
if (404 === (int) $response['code']) {
|
|
return new WP_Error('release_not_found', __('Ingen release fundet.', 'ansico-plugins'));
|
|
}
|
|
if ($response['code'] < 200 || $response['code'] >= 300) {
|
|
return new WP_Error('release_http_error', sprintf(__('Release-endpoint svarede med HTTP %d.', 'ansico-plugins'), (int) $response['code']));
|
|
}
|
|
|
|
$release = $this->parse_json_response($response, 'invalid_release', __('Kunne ikke læse release-data.', 'ansico-plugins'));
|
|
return is_wp_error($release) ? $release : (is_array($release) ? $release : array());
|
|
}
|
|
|
|
public function find_zip_asset($release) {
|
|
if (empty($release['assets']) || !is_array($release['assets'])) {
|
|
return null;
|
|
}
|
|
|
|
foreach ($release['assets'] as $asset) {
|
|
$name = isset($asset['name']) ? (string) $asset['name'] : '';
|
|
if (preg_match('/\.zip$/i', $name)) {
|
|
return $asset;
|
|
}
|
|
}
|
|
|
|
if (!empty($release['zipball_url'])) {
|
|
return array(
|
|
'name' => basename((string) $release['zipball_url']),
|
|
'browser_download_url' => (string) $release['zipball_url'],
|
|
);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
public function get_repository_contents($owner, $repo_name, $path = '', $ref = '') {
|
|
$endpoint = sprintf('%sapi/v1/repos/%s/%s/contents', $this->base_url(), rawurlencode($owner), rawurlencode($repo_name));
|
|
$path = ltrim((string) $path, '/');
|
|
if ('' !== $path) {
|
|
$endpoint .= '/' . str_replace('%2F', '/', rawurlencode($path));
|
|
}
|
|
$query = array();
|
|
if ('' !== (string) $ref) {
|
|
$query['ref'] = (string) $ref;
|
|
}
|
|
if (!empty($query)) {
|
|
$endpoint .= '?' . http_build_query($query, '', '&');
|
|
}
|
|
|
|
$response = $this->request('GET', $endpoint);
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
if (404 === (int) $response['code']) {
|
|
return new WP_Error('contents_not_found', __('Fil eller mappe blev ikke fundet i repository.', 'ansico-plugins'));
|
|
}
|
|
if ($response['code'] < 200 || $response['code'] >= 300) {
|
|
return new WP_Error('contents_http_error', sprintf(__('Contents-endpoint svarede med HTTP %d.', 'ansico-plugins'), (int) $response['code']));
|
|
}
|
|
|
|
$contents = $this->parse_json_response($response, 'invalid_contents', __('Kunne ikke læse repository-indhold.', 'ansico-plugins'));
|
|
return is_wp_error($contents) ? $contents : $contents;
|
|
}
|
|
|
|
|
|
public function get_repository_readme_title($owner, $repo_name, $ref = '') {
|
|
$documentation = $this->get_repository_documentation($owner, $repo_name, $ref);
|
|
if (is_wp_error($documentation)) {
|
|
return '';
|
|
}
|
|
return !empty($documentation['title']) ? (string) $documentation['title'] : '';
|
|
}
|
|
|
|
public function get_repository_documentation($owner, $repo_name, $ref = '') {
|
|
$candidates = array('readme.txt', 'README.txt', 'README.md', 'readme.md', 'Readme.md');
|
|
foreach ($candidates as $candidate) {
|
|
$raw = $this->get_repository_text_file($owner, $repo_name, $candidate, $ref);
|
|
if ('' === $raw) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match('/\.txt$/i', $candidate)) {
|
|
$parsed = $this->parse_wordpress_readme($raw);
|
|
} else {
|
|
$parsed = $this->parse_markdown_readme($raw);
|
|
}
|
|
|
|
if (!empty($parsed['title']) || !empty($parsed['short_description']) || !empty($parsed['sections'])) {
|
|
$parsed['source'] = $candidate;
|
|
return $parsed;
|
|
}
|
|
}
|
|
|
|
return array(
|
|
'title' => '',
|
|
'short_description' => '',
|
|
'sections' => array(),
|
|
'source' => '',
|
|
);
|
|
}
|
|
|
|
private function get_repository_text_file($owner, $repo_name, $path, $ref = '') {
|
|
$file = $this->get_repository_contents($owner, $repo_name, $path, $ref);
|
|
if (is_wp_error($file) || !is_array($file) || empty($file['content']) || empty($file['encoding']) || 'base64' !== $file['encoding']) {
|
|
return '';
|
|
}
|
|
|
|
$raw = base64_decode((string) $file['content'], true);
|
|
if (false === $raw) {
|
|
return '';
|
|
}
|
|
|
|
return str_replace(array("
|
|
", "
|
|
"), "
|
|
", (string) $raw);
|
|
}
|
|
|
|
private function parse_wordpress_readme($raw) {
|
|
$raw = trim((string) $raw);
|
|
$lines = preg_split('/
|
|
/', $raw);
|
|
$title = '';
|
|
$short_description = '';
|
|
$sections = array();
|
|
$current = '';
|
|
$buffer = array();
|
|
$header_done = false;
|
|
|
|
foreach ($lines as $line) {
|
|
if ('' === $title && preg_match('/^===\s*(.+?)\s*===\s*$/', $line, $m)) {
|
|
$title = trim($m[1]);
|
|
continue;
|
|
}
|
|
|
|
if (!$header_done && preg_match('/^==\s*(.+?)\s*==\s*$/', $line, $m)) {
|
|
$header_done = true;
|
|
$current = strtolower(trim($m[1]));
|
|
$buffer = array();
|
|
continue;
|
|
}
|
|
|
|
if (!$header_done) {
|
|
if ('' === $short_description && '' !== trim($line) && false === strpos($line, ':')) {
|
|
$short_description = trim($line);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (preg_match('/^==\s*(.+?)\s*==\s*$/', $line, $m)) {
|
|
if ('' !== $current) {
|
|
$sections[$current] = trim(implode("
|
|
", $buffer));
|
|
}
|
|
$current = strtolower(trim($m[1]));
|
|
$buffer = array();
|
|
continue;
|
|
}
|
|
|
|
$buffer[] = $line;
|
|
}
|
|
|
|
if ('' !== $current) {
|
|
$sections[$current] = trim(implode("
|
|
", $buffer));
|
|
}
|
|
|
|
if ('' === $short_description && !empty($sections['description'])) {
|
|
$short_description = $this->first_paragraph($sections['description']);
|
|
}
|
|
|
|
return array(
|
|
'title' => $title,
|
|
'short_description' => $short_description,
|
|
'sections' => $sections,
|
|
);
|
|
}
|
|
|
|
private function parse_markdown_readme($raw) {
|
|
$title = '';
|
|
$short_description = '';
|
|
$sections = array();
|
|
$current = '';
|
|
$buffer = array();
|
|
$after_title = '';
|
|
|
|
foreach (preg_split('/
|
|
/', (string) $raw) as $line) {
|
|
if ('' === $title && preg_match('/^#\s+(.+)$/', $line, $m)) {
|
|
$title = trim(wp_strip_all_tags($m[1]));
|
|
continue;
|
|
}
|
|
|
|
if (preg_match('/^##\s+(.+)$/', $line, $m)) {
|
|
if ('' !== $current) {
|
|
$sections[$current] = trim(implode("
|
|
", $buffer));
|
|
}
|
|
$current = strtolower(trim(wp_strip_all_tags($m[1])));
|
|
$buffer = array();
|
|
continue;
|
|
}
|
|
|
|
if ('' === $current) {
|
|
$after_title .= $line . "
|
|
";
|
|
} else {
|
|
$buffer[] = $line;
|
|
}
|
|
}
|
|
|
|
if ('' !== $current) {
|
|
$sections[$current] = trim(implode("
|
|
", $buffer));
|
|
}
|
|
|
|
$short_description = $this->first_paragraph($after_title);
|
|
if ('' === $short_description && !empty($sections['description'])) {
|
|
$short_description = $this->first_paragraph($sections['description']);
|
|
}
|
|
|
|
return array(
|
|
'title' => $title,
|
|
'short_description' => $short_description,
|
|
'sections' => $sections,
|
|
);
|
|
}
|
|
|
|
private function first_paragraph($text) {
|
|
$text = trim((string) $text);
|
|
if ('' === $text) {
|
|
return '';
|
|
}
|
|
$parts = preg_split("/
|
|
\s*
|
|
/", $text);
|
|
if (empty($parts[0])) {
|
|
return '';
|
|
}
|
|
return trim(wp_strip_all_tags($parts[0]));
|
|
}
|
|
|
|
private function find_repository_asset_url($owner, $repo_name, $default_branch, $candidates) {
|
|
foreach ((array) $candidates as $candidate) {
|
|
$file = $this->get_repository_contents($owner, $repo_name, $candidate, $default_branch);
|
|
if (!is_wp_error($file) && is_array($file) && !empty($file['download_url'])) {
|
|
return (string) $file['download_url'];
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
public function get_repository_plugin_metadata($owner, $repo_name) {
|
|
$repo = $this->get_repository($owner, $repo_name);
|
|
if (is_wp_error($repo)) {
|
|
return $repo;
|
|
}
|
|
|
|
$default_branch = !empty($repo['default_branch']) ? (string) $repo['default_branch'] : '';
|
|
$root = $this->get_repository_contents($owner, $repo_name, '', $default_branch);
|
|
$plugin_headers = array();
|
|
|
|
if (!is_wp_error($root) && is_array($root)) {
|
|
foreach ($root as $item) {
|
|
if (!is_array($item) || empty($item['name'])) {
|
|
continue;
|
|
}
|
|
$name = (string) $item['name'];
|
|
if (empty($plugin_headers) && !empty($item['type']) && 'file' === $item['type'] && preg_match('/\.php$/i', $name)) {
|
|
$file = $this->get_repository_contents($owner, $repo_name, $name, $default_branch);
|
|
if (!is_wp_error($file) && is_array($file) && !empty($file['content']) && !empty($file['encoding']) && 'base64' === $file['encoding']) {
|
|
$raw = base64_decode((string) $file['content'], true);
|
|
if (false !== $raw) {
|
|
$plugin_headers = $this->parse_plugin_headers($raw);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$documentation = $this->get_repository_documentation($owner, $repo_name, $default_branch);
|
|
if (is_wp_error($documentation)) {
|
|
$documentation = array('title' => '', 'short_description' => '', 'sections' => array(), 'source' => '');
|
|
}
|
|
|
|
$author_name = !empty($plugin_headers['Author']) ? (string) $plugin_headers['Author'] : (!empty($repo['owner']['full_name']) ? (string) $repo['owner']['full_name'] : (!empty($repo['owner']['login']) ? (string) $repo['owner']['login'] : ''));
|
|
$author_url = !empty($plugin_headers['AuthorURI']) ? (string) $plugin_headers['AuthorURI'] : (!empty($repo['owner']['website']) ? (string) $repo['owner']['website'] : (!empty($repo['owner']['html_url']) ? (string) $repo['owner']['html_url'] : ''));
|
|
$support_url = !empty($plugin_headers['SupportURI']) ? (string) $plugin_headers['SupportURI'] : (!empty($repo['html_url']) ? trailingslashit((string) $repo['html_url']) . 'issues' : '');
|
|
$license = !empty($plugin_headers['License']) ? (string) $plugin_headers['License'] : (!empty($repo['license']['spdx_id']) ? (string) $repo['license']['spdx_id'] : '');
|
|
|
|
$screenshot_url = $this->find_repository_asset_url($owner, $repo_name, $default_branch, array('screenshot.png', 'assets/screenshot.png'));
|
|
$icon_url = $this->find_repository_asset_url($owner, $repo_name, $default_branch, array('icon-256x256.png', 'icon-128x128.png', 'assets/icon-256x256.png', 'assets/icon-128x128.png'));
|
|
$banner_url = $this->find_repository_asset_url($owner, $repo_name, $default_branch, array('banner-1544x500.png', 'banner-772x250.png', 'assets/banner-1544x500.png', 'assets/banner-772x250.png'));
|
|
|
|
return array(
|
|
'readme_title' => !empty($documentation['title']) ? $documentation['title'] : '',
|
|
'description' => !empty($documentation['short_description']) ? $documentation['short_description'] : (!empty($repo['description']) ? (string) $repo['description'] : ''),
|
|
'readme_sections' => !empty($documentation['sections']) && is_array($documentation['sections']) ? $documentation['sections'] : array(),
|
|
'readme_source' => !empty($documentation['source']) ? $documentation['source'] : '',
|
|
'author_name' => $author_name,
|
|
'author_url' => $author_url,
|
|
'plugin_headers' => $plugin_headers,
|
|
'support_url' => $support_url,
|
|
'license' => $license,
|
|
'screenshot_url' => $screenshot_url,
|
|
'icon_url' => $icon_url,
|
|
'banner_url' => $banner_url,
|
|
'default_branch' => $default_branch,
|
|
);
|
|
}
|
|
|
|
private function parse_plugin_headers($content) {
|
|
$headers = array(
|
|
'Plugin Name' => 'Name',
|
|
'Author' => 'Author',
|
|
'Author URI' => 'AuthorURI',
|
|
'Plugin URI' => 'PluginURI',
|
|
'Description' => 'Description',
|
|
'Version' => 'Version',
|
|
'Requires at least' => 'RequiresWP',
|
|
'Requires PHP' => 'RequiresPHP',
|
|
'License' => 'License',
|
|
'License URI' => 'LicenseURI',
|
|
'Text Domain' => 'TextDomain',
|
|
'Support URI' => 'SupportURI',
|
|
);
|
|
|
|
$parsed = array();
|
|
foreach ($headers as $label => $key) {
|
|
if (preg_match('/^[ \t\/*#@]*' . preg_quote($label, '/') . ':(.*)$/mi', (string) $content, $matches)) {
|
|
$parsed[$key] = trim(wp_strip_all_tags($matches[1]));
|
|
}
|
|
}
|
|
|
|
return $parsed;
|
|
}
|
|
|
|
public function request($method, $url, $allow_retry_without_auth = true) {
|
|
$method = strtoupper((string) $method);
|
|
$headers = array(
|
|
'Accept' => 'application/json',
|
|
'User-Agent' => 'Ansico-Plugins/' . ANSICO_PLUGINS_VERSION . '; ' . home_url('/'),
|
|
);
|
|
|
|
if (!empty($this->settings['access_token'])) {
|
|
$headers['Authorization'] = 'token ' . trim((string) $this->settings['access_token']);
|
|
}
|
|
|
|
$args = array(
|
|
'method' => $method,
|
|
'headers' => $headers,
|
|
'timeout' => max(5, (int) $this->settings['request_timeout']),
|
|
'sslverify' => !empty($this->settings['verify_ssl']),
|
|
);
|
|
|
|
$cache_key = $this->cache_key($method, $url);
|
|
if ('GET' === $method) {
|
|
$cached = get_transient($cache_key);
|
|
if (is_array($cached) && isset($cached['body'], $cached['code'])) {
|
|
return $cached;
|
|
}
|
|
}
|
|
|
|
$response = wp_remote_request(esc_url_raw($url), $args);
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
$normalized = $this->normalize_http_response($response);
|
|
|
|
if (
|
|
$allow_retry_without_auth &&
|
|
!empty($this->settings['access_token']) &&
|
|
in_array((int) $normalized['code'], array(401, 403), true)
|
|
) {
|
|
unset($args['headers']['Authorization']);
|
|
$retry_response = wp_remote_request(esc_url_raw($url), $args);
|
|
if (!is_wp_error($retry_response)) {
|
|
$normalized = $this->normalize_http_response($retry_response);
|
|
}
|
|
}
|
|
|
|
if ('GET' === $method) {
|
|
set_transient($cache_key, $normalized, 5 * MINUTE_IN_SECONDS);
|
|
}
|
|
|
|
return $normalized;
|
|
}
|
|
}
|