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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
<?php
/**
* DokuWiki Plugin extension (Helper Component)
*
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
* @author Michael Hamann <michael@content-space.de>
*/
use dokuwiki\Cache\Cache;
use dokuwiki\Extension\Plugin;
use dokuwiki\Extension\PluginController;
use dokuwiki\HTTP\DokuHTTPClient;
/**
* Class helper_plugin_extension_repository provides access to the extension repository on dokuwiki.org
*/
class helper_plugin_extension_repository extends Plugin
{
public const EXTENSION_REPOSITORY_API = 'https://www.dokuwiki.org/lib/plugins/pluginrepo/api.php';
private $loaded_extensions = [];
private $has_access;
/**
* Initialize the repository (cache), fetches data for all installed plugins
*/
public function init()
{
/* @var PluginController $plugin_controller */
global $plugin_controller;
if ($this->hasAccess()) {
$list = $plugin_controller->getList('', true);
$request_data = ['fmt' => 'json'];
$request_needed = false;
foreach ($list as $name) {
$cache = new Cache('##extension_manager##' . $name, '.repo');
if (
!isset($this->loaded_extensions[$name]) &&
$this->hasAccess() &&
!$cache->useCache(['age' => 3600 * 24])
) {
$this->loaded_extensions[$name] = true;
$request_data['ext'][] = $name;
$request_needed = true;
}
}
if ($request_needed) {
$httpclient = new DokuHTTPClient();
$data = $httpclient->post(self::EXTENSION_REPOSITORY_API, $request_data);
if ($data !== false) {
try {
$extensions = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
foreach ($extensions as $extension) {
$cache = new Cache('##extension_manager##' . $extension['plugin'], '.repo');
$cache->storeCache(serialize($extension));
}
} catch (JsonException $e) {
msg($this->getLang('repo_badresponse'), -1);
$this->has_access = false;
}
} else {
$this->has_access = false;
}
}
}
}
/**
* If repository access is available
*
* @param bool $usecache use cached result if still valid
* @return bool If repository access is available
*/
public function hasAccess($usecache = true)
{
if ($this->has_access === null) {
$cache = new Cache('##extension_manager###hasAccess', '.repo');
if (!$cache->useCache(['age' => 60 * 10, 'purge' => !$usecache])) {
$httpclient = new DokuHTTPClient();
$httpclient->timeout = 5;
$data = $httpclient->get(self::EXTENSION_REPOSITORY_API . '?cmd=ping');
if ($data === false) {
$this->has_access = false;
$cache->storeCache(0);
} elseif ($data !== '1') {
msg($this->getLang('repo_badresponse'), -1);
$this->has_access = false;
$cache->storeCache(0);
} else {
$this->has_access = true;
$cache->storeCache(1);
}
} else {
$this->has_access = ($cache->retrieveCache(false) == 1);
}
}
return $this->has_access;
}
/**
* Get the remote data of an individual plugin or template
*
* @param string $name The plugin name to get the data for, template names need to be prefix by 'template:'
* @return array The data or null if nothing was found (possibly no repository access)
*/
public function getData($name)
{
$cache = new Cache('##extension_manager##' . $name, '.repo');
if (
!isset($this->loaded_extensions[$name]) &&
$this->hasAccess() &&
!$cache->useCache(['age' => 3600 * 24])
) {
$this->loaded_extensions[$name] = true;
$httpclient = new DokuHTTPClient();
$data = $httpclient->get(self::EXTENSION_REPOSITORY_API . '?fmt=json&ext[]=' . urlencode($name));
if ($data !== false) {
try {
$result = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
if (count($result)) {
$cache->storeCache(serialize($result[0]));
return $result[0];
}
} catch (JsonException $e) {
msg($this->getLang('repo_badresponse'), -1);
$this->has_access = false;
}
} else {
$this->has_access = false;
}
}
if (file_exists($cache->cache)) {
return unserialize($cache->retrieveCache(false));
}
return [];
}
/**
* Search for plugins or templates using the given query string
*
* @param string $q the query string
* @return array a list of matching extensions
*/
public function search($q)
{
$query = $this->parseQuery($q);
$query['fmt'] = 'json';
$httpclient = new DokuHTTPClient();
$data = $httpclient->post(self::EXTENSION_REPOSITORY_API, $query);
if ($data === false) return [];
try {
$result = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
msg($this->getLang('repo_badresponse'), -1);
return [];
}
$ids = [];
// store cache info for each extension
foreach ($result as $ext) {
$name = $ext['plugin'];
$cache = new Cache('##extension_manager##' . $name, '.repo');
$cache->storeCache(serialize($ext));
$ids[] = $name;
}
return $ids;
}
/**
* Parses special queries from the query string
*
* @param string $q
* @return array
*/
protected function parseQuery($q)
{
$parameters = ['tag' => [], 'mail' => [], 'type' => [], 'ext' => []];
// extract tags
if (preg_match_all('/(^|\s)(tag:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$q = str_replace($m[2], '', $q);
$parameters['tag'][] = $m[3];
}
}
// extract author ids
if (preg_match_all('/(^|\s)(authorid:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$q = str_replace($m[2], '', $q);
$parameters['mail'][] = $m[3];
}
}
// extract extensions
if (preg_match_all('/(^|\s)(ext:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$q = str_replace($m[2], '', $q);
$parameters['ext'][] = $m[3];
}
}
// extract types
if (preg_match_all('/(^|\s)(type:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$q = str_replace($m[2], '', $q);
$parameters['type'][] = $m[3];
}
}
// FIXME make integer from type value
$parameters['q'] = trim($q);
return $parameters;
}
}
// vim:ts=4:sw=4:et:
|