Completed
Push — sidebaracl ( 7a112d...7c3e4a )
by Andreas
04:38
created

helper_plugin_extension_repository   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 170
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4
Metric Value
wmc 31
lcom 1
cbo 4
dl 0
loc 170
rs 9.8

5 Methods

Rating   Name   Duplication   Size   Complexity  
D init() 0 32 9
A hasAccess() 0 21 4
B getData() 0 20 6
A search() 0 21 3
D parse_query() 0 42 9
1
<?php
2
/**
3
 * DokuWiki Plugin extension (Helper Component)
4
 *
5
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6
 * @author  Michael Hamann <[email protected]>
7
 */
8
9
#define('EXTENSION_REPOSITORY_API', 'http://localhost/dokuwiki/lib/plugins/pluginrepo/api.php');
10
11
if (!defined('EXTENSION_REPOSITORY_API_ENDPOINT'))
12
    define('EXTENSION_REPOSITORY_API', 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php');
13
14
// must be run within Dokuwiki
15
if(!defined('DOKU_INC')) die();
16
17
/**
18
 * Class helper_plugin_extension_repository provides access to the extension repository on dokuwiki.org
19
 */
20
class helper_plugin_extension_repository extends DokuWiki_Plugin {
21
    private $loaded_extensions = array();
22
    private $has_access = null;
23
    /**
24
     * Initialize the repository (cache), fetches data for all installed plugins
25
     */
26
    public function init() {
27
        /* @var Doku_Plugin_Controller $plugin_controller */
28
        global $plugin_controller;
29
        if ($this->hasAccess()) {
30
            $list = $plugin_controller->getList('', true);
31
            $request_data = array('fmt' => 'php');
32
            $request_needed = false;
33
            foreach ($list as $name) {
34
                $cache = new cache('##extension_manager##'.$name, '.repo');
35
36
                if (!isset($this->loaded_extensions[$name]) && $this->hasAccess() && !$cache->useCache(array('age' => 3600 * 24))) {
37
                    $this->loaded_extensions[$name] = true;
38
                    $request_data['ext'][] = $name;
39
                    $request_needed = true;
40
                }
41
            }
42
43
            if ($request_needed) {
44
                $httpclient = new DokuHTTPClient();
45
                $data = $httpclient->post(EXTENSION_REPOSITORY_API, $request_data);
46
                if ($data !== false) {
47
                    $extensions = unserialize($data);
48
                    foreach ($extensions as $extension) {
49
                        $cache = new cache('##extension_manager##'.$extension['plugin'], '.repo');
50
                        $cache->storeCache(serialize($extension));
51
                    }
52
                } else {
53
                    $this->has_access = false;
54
                }
55
            }
56
        }
57
    }
58
59
    /**
60
     * If repository access is available
61
     *
62
     * @return bool If repository access is available
63
     */
64
    public function hasAccess() {
65
        if ($this->has_access === null) {
66
            $cache = new cache('##extension_manager###hasAccess', '.repo');
67
68
            if (!$cache->useCache(array('age' => 3600 * 24, 'purge'=>1))) {
69
                $httpclient = new DokuHTTPClient();
70
                $httpclient->timeout = 5;
0 ignored issues
show
Bug introduced by
The property timeout cannot be accessed from this context as it is declared private in class HTTPClient.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
71
                $data = $httpclient->get(EXTENSION_REPOSITORY_API.'?cmd=ping');
72
                if ($data !== false) {
73
                    $this->has_access = true;
74
                    $cache->storeCache(1);
75
                } else {
76
                    $this->has_access = false;
77
                    $cache->storeCache(0);
78
                }
79
            } else {
80
                $this->has_access = ($cache->retrieveCache(false) == 1);
81
            }
82
        }
83
        return $this->has_access;
84
    }
85
86
    /**
87
     * Get the remote data of an individual plugin or template
88
     *
89
     * @param string $name  The plugin name to get the data for, template names need to be prefix by 'template:'
90
     * @return array The data or null if nothing was found (possibly no repository access)
91
     */
92
    public function getData($name) {
93
        $cache = new cache('##extension_manager##'.$name, '.repo');
94
95
        if (!isset($this->loaded_extensions[$name]) && $this->hasAccess() && !$cache->useCache(array('age' => 3600 * 24))) {
96
            $this->loaded_extensions[$name] = true;
97
            $httpclient = new DokuHTTPClient();
98
            $data = $httpclient->get(EXTENSION_REPOSITORY_API.'?fmt=php&ext[]='.urlencode($name));
99
            if ($data !== false) {
100
                $result = unserialize($data);
101
                $cache->storeCache(serialize($result[0]));
102
                return $result[0];
103
            } else {
104
                $this->has_access = false;
105
            }
106
        }
107
        if (file_exists($cache->cache)) {
108
            return unserialize($cache->retrieveCache(false));
109
        }
110
        return array();
111
    }
112
113
    /**
114
     * Search for plugins or templates using the given query string
115
     *
116
     * @param string $q the query string
117
     * @return array a list of matching extensions
118
     */
119
    public function search($q){
120
        $query = $this->parse_query($q);
121
        $query['fmt'] = 'php';
122
123
        $httpclient = new DokuHTTPClient();
124
        $data = $httpclient->post(EXTENSION_REPOSITORY_API, $query);
125
        if ($data === false) return array();
126
        $result = unserialize($data);
127
128
        $ids = array();
129
130
        // store cache info for each extension
131
        foreach($result as $ext){
132
            $name = $ext['plugin'];
133
            $cache = new cache('##extension_manager##'.$name, '.repo');
134
            $cache->storeCache(serialize($ext));
135
            $ids[] = $name;
136
        }
137
138
        return $ids;
139
    }
140
141
    /**
142
     * Parses special queries from the query string
143
     *
144
     * @param string $q
145
     * @return array
146
     */
147
    protected function parse_query($q){
148
        $parameters = array(
149
            'tag'  => array(),
150
            'mail' => array(),
151
            'type' => array(),
152
            'ext'  => array()
153
        );
154
155
        // extract tags
156
        if(preg_match_all('/(^|\s)(tag:([\S]+))/', $q, $matches, PREG_SET_ORDER)){
157
            foreach($matches as $m){
158
                $q = str_replace($m[2], '', $q);
159
                $parameters['tag'][] = $m[3];
160
            }
161
        }
162
        // extract author ids
163
        if(preg_match_all('/(^|\s)(authorid:([\S]+))/', $q, $matches, PREG_SET_ORDER)){
164
            foreach($matches as $m){
165
                $q = str_replace($m[2], '', $q);
166
                $parameters['mail'][] = $m[3];
167
            }
168
        }
169
        // extract extensions
170
        if(preg_match_all('/(^|\s)(ext:([\S]+))/', $q, $matches, PREG_SET_ORDER)){
171
            foreach($matches as $m){
172
                $q = str_replace($m[2], '', $q);
173
                $parameters['ext'][] = $m[3];
174
            }
175
        }
176
        // extract types
177
        if(preg_match_all('/(^|\s)(type:([\S]+))/', $q, $matches, PREG_SET_ORDER)){
178
            foreach($matches as $m){
179
                $q = str_replace($m[2], '', $q);
180
                $parameters['type'][] = $m[3];
181
            }
182
        }
183
184
        // FIXME make integer from type value
185
186
        $parameters['q'] = trim($q);
187
        return $parameters;
188
    }
189
}
190
191
// vim:ts=4:sw=4:et:
192