__('Forgejo base URL', 'ansico-plugins'),
'forgejo_owner' => __('Bruger eller organisation', 'ansico-plugins'),
'access_token' => __('Access token', 'ansico-plugins'),
'topic_filter' => __('Topic-filter', 'ansico-plugins'),
'request_timeout' => __('Timeout (sekunder)', 'ansico-plugins'),
);
foreach ($fields as $key => $label) {
add_settings_field($key, $label, array($this, 'render_field'), 'ansico-plugins', 'ansico_plugins_connection', array('key' => $key));
}
add_settings_field('owner_type', __('Owner-type', 'ansico-plugins'), array($this, 'render_owner_type_field'), 'ansico-plugins', 'ansico_plugins_connection');
add_settings_field('verify_ssl', __('SSL-verifikation', 'ansico-plugins'), array($this, 'render_verify_ssl_field'), 'ansico-plugins', 'ansico_plugins_connection');
add_settings_section(
'ansico_plugins_self_update',
__('Opdatering af Ansico Plugins', 'ansico-plugins'),
'__return_false',
'ansico-plugins'
);
add_settings_field('self_update_enabled', __('Slå selvopdatering til', 'ansico-plugins'), array($this, 'render_self_update_enabled_field'), 'ansico-plugins', 'ansico_plugins_self_update');
add_settings_field('self_update_owner', __('Ansico plugins owner', 'ansico-plugins'), array($this, 'render_field'), 'ansico-plugins', 'ansico_plugins_self_update', array('key' => 'self_update_owner'));
add_settings_field('self_update_repo', __('Ansico plugins repository', 'ansico-plugins'), array($this, 'render_field'), 'ansico-plugins', 'ansico_plugins_self_update', array('key' => 'self_update_repo'));
}
public function sanitize_settings($input) {
$output = Ansico_Plugins::get_settings();
$output['forgejo_base_url'] = isset($input['forgejo_base_url']) ? esc_url_raw(trim((string) $input['forgejo_base_url'])) : '';
$output['forgejo_owner'] = isset($input['forgejo_owner']) ? sanitize_text_field($input['forgejo_owner']) : '';
$output['owner_type'] = isset($input['owner_type']) && in_array($input['owner_type'], array('user', 'org'), true) ? $input['owner_type'] : 'org';
$output['access_token'] = isset($input['access_token']) ? sanitize_text_field($input['access_token']) : '';
$output['topic_filter'] = isset($input['topic_filter']) ? sanitize_text_field($input['topic_filter']) : 'wordpress-plugin';
$output['verify_ssl'] = !empty($input['verify_ssl']) ? 1 : 0;
$output['request_timeout'] = isset($input['request_timeout']) ? max(5, (int) $input['request_timeout']) : 20;
$output['self_update_enabled'] = !empty($input['self_update_enabled']) ? 1 : 0;
$output['self_update_owner'] = isset($input['self_update_owner']) ? sanitize_text_field($input['self_update_owner']) : '';
$output['self_update_repo'] = isset($input['self_update_repo']) ? sanitize_text_field($input['self_update_repo']) : '';
Ansico_Plugins::clear_http_cache();
wp_clean_plugins_cache(true);
delete_site_transient('update_plugins');
return $output;
}
public function maybe_handle_reset_defaults() {
if (!is_admin() || !current_user_can('manage_options') || empty($_GET['ansico_reset_defaults'])) {
return;
}
if (!isset($_GET['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'ansico_plugins_reset_defaults')) {
return;
}
update_option(ANSICO_PLUGINS_OPTION, Ansico_Plugins::default_settings(), false);
Ansico_Plugins::clear_http_cache();
wp_clean_plugins_cache(true);
delete_site_transient('update_plugins');
wp_safe_redirect(admin_url('options-general.php?page=ansico-plugins&ansico_reset_done=1'));
exit;
}
public function maybe_show_reset_notice() {
if (!current_user_can('manage_options') || empty($_GET['ansico_reset_done'])) {
return;
}
echo '
' . esc_html__('Ansico standardindstillinger er gendannet.', 'ansico-plugins') . '
';
}
public function render_field($args) {
$settings = Ansico_Plugins::get_settings();
$key = $args['key'];
$value = isset($settings[$key]) ? $settings[$key] : '';
$type = 'text';
if ('access_token' === $key) {
$type = 'password';
} elseif ('request_timeout' === $key) {
$type = 'number';
} elseif ('forgejo_base_url' === $key) {
$type = 'url';
}
printf(
' ',
esc_attr($type),
esc_attr(ANSICO_PLUGINS_OPTION),
esc_attr($key),
esc_attr($value),
'request_timeout' === $key ? 'min="5" step="1"' : ''
);
$help = array(
'forgejo_base_url' => __('Eksempel: https://forgejo.ditdomæne.dk/', 'ansico-plugins'),
'forgejo_owner' => __('Navn på bruger eller organisation som ejer repositories.', 'ansico-plugins'),
'access_token' => __('PAT med adgang til at læse repos/releases. Kræves ofte for private repos.', 'ansico-plugins'),
'topic_filter' => __('Kun repos med dette topic vises. Brug tomt felt for at vise alle repos.', 'ansico-plugins'),
'request_timeout' => __('Øg værdien hvis Forgejo-serveren er langsom.', 'ansico-plugins'),
'self_update_owner' => __('Organisation eller bruger som ejer Ansico Plugins-repository.', 'ansico-plugins'),
'self_update_repo' => __('Repository-navn for Ansico Plugins, fx Ansico-plugins.', 'ansico-plugins'),
);
if (isset($help[$key])) {
echo '' . esc_html($help[$key]) . '
';
}
}
public function render_owner_type_field() {
$settings = Ansico_Plugins::get_settings();
?>
/>
/>
/>
/>
test_connection();
if (is_wp_error($result)) {
printf(
'',
esc_html__('Forgejo-forbindelse fejlede:', 'ansico-plugins'),
esc_html($result->get_error_message())
);
return;
}
printf(
'',
esc_html__('Forbindelse OK. Forgejo-version:', 'ansico-plugins'),
esc_html($result['version'])
);
}
public function render_catalog_page() {
if (!current_user_can('install_plugins')) {
return;
}
$client = new Ansico_Plugins_Client();
$repos = $client->get_repositories();
if (isset($_GET['ansico_view']) && 'details' === sanitize_key(wp_unslash($_GET['ansico_view']))) {
$this->render_details_page($client, $repos, false);
return;
}
$settings = Ansico_Plugins::get_settings();
$owner_label = !empty($settings['forgejo_owner']) ? $settings['forgejo_owner'] : __('din organisation', 'ansico-plugins');
$forgejo_link = !empty($settings['forgejo_base_url']) ? trailingslashit($settings['forgejo_base_url']) . rawurlencode($owner_label) : '';
?>
render_catalog_styles(); ?>
%s
', esc_html($repos->get_error_message()));
echo '' . esc_html__('Gå til indstillinger', 'ansico-plugins') . '
';
echo '';
return;
}
if (empty($repos)) {
echo '' . esc_html__('Ingen repositories matchede de valgte kriterier.', 'ansico-plugins') . '
';
echo '' . esc_html__('Forgejo svarer, men ingen repos matchede topic-filteret. Kontrollér topic-navn og gem indstillingerne igen for at rydde cache.', 'ansico-plugins') . '
';
echo '';
return;
}
if (!function_exists('get_plugins')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$installed_plugins = get_plugins();
$managed_plugins = Ansico_Plugins::get_managed_plugins();
echo '';
foreach ($repos as $repo) {
$release = $client->get_latest_release($repo['owner']['login'], $repo['name']);
$zip_asset = !is_wp_error($release) ? $client->find_zip_asset($release) : null;
$plugin_state = $this->get_plugin_state($repo, $installed_plugins, $managed_plugins, $release);
$metadata = $client->get_repository_plugin_metadata($repo['owner']['login'], $repo['name']);
$metadata = is_wp_error($metadata) ? array() : $metadata;
$display_name = !empty($metadata['readme_title']) ? $metadata['readme_title'] : $repo['name'];
$details_url = $this->get_details_url($repo['name']);
$badge = $this->get_state_badge($plugin_state);
$version_label = is_wp_error($release) ? '—' : $this->normalize_release_version($release);
echo '
';
echo '
';
echo '
' . esc_html(!empty($repo['description']) ? $repo['description'] : __('Ingen beskrivelse angivet.', 'ansico-plugins')) . '
';
echo '
';
echo '' . esc_html__('Installeret', 'ansico-plugins') . ': ' . esc_html($plugin_state['installed_version'] !== '' ? $plugin_state['installed_version'] : '—') . ' ';
echo '' . esc_html__('Seneste', 'ansico-plugins') . ': ' . esc_html($version_label) . ' ';
echo '
';
echo '
';
echo $this->get_details_inline_markup($repo, $release, $zip_asset, $plugin_state, $metadata); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '
';
}
echo '
';
}
private function render_details_page($client, $repos, $is_modal = false) {
$repo_name = isset($_GET['repo']) ? sanitize_text_field(wp_unslash($_GET['repo'])) : '';
$repo = null;
if (!is_wp_error($repos)) {
foreach ($repos as $candidate) {
if (!empty($candidate['name']) && $candidate['name'] === $repo_name) {
$repo = $candidate;
break;
}
}
}
if (!$repo) {
wp_die(esc_html__('Repository blev ikke fundet.', 'ansico-plugins'));
}
if (!function_exists('get_plugins')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$installed_plugins = get_plugins();
$managed_plugins = Ansico_Plugins::get_managed_plugins();
$release = $client->get_latest_release($repo['owner']['login'], $repo['name']);
$zip_asset = !is_wp_error($release) ? $client->find_zip_asset($release) : null;
$plugin_state = $this->get_plugin_state($repo, $installed_plugins, $managed_plugins, $release);
$metadata = $client->get_repository_plugin_metadata($repo['owner']['login'], $repo['name']);
$metadata = is_wp_error($metadata) ? array() : $metadata;
$back_url = admin_url('plugins.php?page=ansico-plugins-catalog');
echo '';
$this->render_catalog_styles();
echo '
' . esc_html(!empty($metadata['readme_title']) ? $metadata['readme_title'] : $repo['name']) . ' ';
echo '
' . esc_html__('Tilbage til katalog', 'ansico-plugins') . ' ';
echo '';
echo $this->get_details_content_markup($repo, $release, $zip_asset, $plugin_state, $metadata); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '
';
exit;
}
private function build_action_buttons($repo, $plugin_state, $zip_asset) {
$buttons = array();
$repo_name = $repo['name'];
$slug = $repo['name'];
if (!$plugin_state['is_installed'] && $zip_asset) {
$buttons[] = '' . esc_html__('Installér', 'ansico-plugins') . ' ';
return $buttons;
}
if ($plugin_state['is_installed'] && !$plugin_state['is_active']) {
$buttons[] = '' . esc_html__('Aktivér', 'ansico-plugins') . ' ';
$buttons[] = '' . esc_html__('Afinstallér', 'ansico-plugins') . ' ';
return $buttons;
}
if ($plugin_state['is_installed'] && $plugin_state['has_update']) {
$buttons[] = '' . esc_html__('Opdatér', 'ansico-plugins') . ' ';
$buttons[] = '' . esc_html__('Afinstallér', 'ansico-plugins') . ' ';
return $buttons;
}
if ($plugin_state['is_installed'] && $plugin_state['is_active']) {
$buttons[] = '' . esc_html__('Geninstallér', 'ansico-plugins') . ' ';
$buttons[] = '' . esc_html__('Afinstallér', 'ansico-plugins') . ' ';
}
return $buttons;
}
private function get_plugin_state($repo, $installed_plugins, $managed_plugins, $release) {
$plugin_file = '';
foreach ($managed_plugins as $candidate_plugin_file => $meta) {
if (!empty($meta['owner']) && !empty($meta['repo']) && $meta['owner'] === $repo['owner']['login'] && $meta['repo'] === $repo['name']) {
$plugin_file = $candidate_plugin_file;
break;
}
}
if ('' === $plugin_file) {
foreach ($installed_plugins as $candidate_plugin_file => $plugin_data) {
if (dirname($candidate_plugin_file) === sanitize_title($repo['name'])) {
$plugin_file = $candidate_plugin_file;
break;
}
}
}
$is_installed = '' !== $plugin_file && isset($installed_plugins[$plugin_file]);
$installed_version = $is_installed && !empty($installed_plugins[$plugin_file]['Version']) ? (string) $installed_plugins[$plugin_file]['Version'] : '';
$is_active = $is_installed ? is_plugin_active($plugin_file) : false;
$remote_version = !is_wp_error($release) ? $this->normalize_release_version($release) : '';
$has_update = $is_installed && '' !== $installed_version && '' !== $remote_version && version_compare($remote_version, $installed_version, '>');
return array(
'plugin_file' => $plugin_file,
'is_installed' => $is_installed,
'is_active' => $is_active,
'installed_version' => $installed_version,
'remote_version' => $remote_version,
'has_update' => $has_update,
);
}
private function normalize_release_version($release) {
$version = '';
if (!empty($release['tag_name'])) {
$version = (string) $release['tag_name'];
} elseif (!empty($release['name'])) {
$version = (string) $release['name'];
}
$version = ltrim($version, 'vV');
return '' !== $version ? $version : '—';
}
private function get_state_badge($plugin_state) {
if (!$plugin_state['is_installed']) {
if (empty($plugin_state['remote_version']) || '—' === $plugin_state['remote_version']) {
return '' . esc_html__('Ikke udgivet', 'ansico-plugins') . ' ';
}
return '' . esc_html__('Ikke installeret', 'ansico-plugins') . ' ';
}
if ($plugin_state['has_update']) {
return '' . esc_html__('Opdatering klar', 'ansico-plugins') . ' ';
}
if (!$plugin_state['is_active']) {
return '' . esc_html__('Installeret', 'ansico-plugins') . ' ';
}
return '' . esc_html__('Aktiv', 'ansico-plugins') . ' ';
}
private function get_self_plugin_status_markup($client) {
$settings = Ansico_Plugins::get_settings();
if (empty($settings['self_update_enabled']) || empty($settings['self_update_owner']) || empty($settings['self_update_repo'])) {
return '';
}
if (!function_exists('get_plugin_data')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugin_file = plugin_basename(ANSICO_PLUGINS_FILE);
$plugin_data = get_plugin_data(ANSICO_PLUGINS_FILE, false, false);
$current_version = !empty($plugin_data['Version']) ? (string) $plugin_data['Version'] : ANSICO_PLUGINS_VERSION;
$release = $client->get_latest_release($settings['self_update_owner'], $settings['self_update_repo']);
if (is_wp_error($release)) {
return '' . esc_html__('Ansico Plugins: kunne ikke hente opdateringsstatus.', 'ansico-plugins') . '
';
}
$remote_version = $this->normalize_release_version($release);
$repo_url = trailingslashit($settings['forgejo_base_url']) . rawurlencode($settings['self_update_owner']) . '/' . rawurlencode($settings['self_update_repo']);
if ('' === $remote_version || '—' === $remote_version) {
return '' . esc_html__('Ansico Plugins: ingen udgivet version fundet endnu.', 'ansico-plugins') . '
';
}
if (version_compare($remote_version, $current_version, '>')) {
$update_url = esc_url(admin_url('plugins.php'));
return '' . sprintf(
wp_kses(
__('Ansico Plugins: version %1$s er installeret, og version %2$s er tilgængelig fra %4$s . Opdater fra den almindelige Plugins-side .', 'ansico-plugins'),
array('a' => array('href' => array(), 'target' => array(), 'rel' => array()))
),
esc_html($current_version),
esc_html($remote_version),
esc_url($repo_url),
esc_html($settings['self_update_repo']),
esc_url($update_url)
) . '
';
}
return '' . sprintf(
wp_kses(
__('Ansico Plugins er opdateret. Installeret version %1$s matcher seneste release i %3$s .', 'ansico-plugins'),
array('a' => array('href' => array(), 'target' => array(), 'rel' => array()))
),
esc_html($current_version),
esc_url($repo_url),
esc_html($settings['self_update_repo'])
) . '
';
}
private function get_details_url($repo_name) {
return '#TB_inline?width=920&height=648&inlineId=ansico-plugin-details-' . rawurlencode(sanitize_title($repo_name));
}
private function build_action_url($action, $repo_name, $slug, $plugin_file = '') {
$url = admin_url('plugins.php?page=ansico-plugins-catalog&ansico_action=' . rawurlencode($action) . '&repo=' . rawurlencode($repo_name) . '&slug=' . rawurlencode($slug));
if ('' !== $plugin_file) {
$url .= '&plugin_file=' . rawurlencode($plugin_file);
}
return wp_nonce_url($url, 'ansico_plugins_action');
}
private function get_details_inline_markup($repo, $release, $zip_asset, $plugin_state, $metadata) {
$id = 'ansico-plugin-details-' . sanitize_title($repo['name']);
return '' .
'
' .
$this->get_details_content_markup($repo, $release, $zip_asset, $plugin_state, $metadata) .
'
';
}
private function get_details_content_markup($repo, $release, $zip_asset, $plugin_state, $metadata) {
$display_name = !empty($metadata['readme_title']) ? $metadata['readme_title'] : $repo['name'];
$html = '';
$html .= '';
$html .= '
AP
';
$html .= '
';
$html .= '
' . esc_html($display_name) . ' ';
$html .= '
' . esc_html(!empty($repo['description']) ? $repo['description'] : __('Ingen beskrivelse angivet.', 'ansico-plugins')) . '
';
$html .= $this->get_state_badge($plugin_state);
$html .= '
';
$html .= '';
$html .= '';
if (!empty($metadata['screenshot_url'])) {
$html .= '';
$html .= '
' . esc_html__('Screenshot', 'ansico-plugins') . ' ';
$html .= '
';
$html .= '
';
}
if (!is_wp_error($release) && !empty($release['body'])) {
$html .= '' . esc_html__('Release-noter', 'ansico-plugins') . ' ';
$html .= '' . wp_kses_post(wpautop($release['body'])) . '
';
}
return $html;
}
private function render_catalog_styles() {
echo '';
}
}