Skip to content

Commit 6f047e8

Browse files
authored
Merge pull request #5 from splitbrain/codesearch
Rebase the plugin on grok
2 parents 73a57c5 + f6d3559 commit 6f047e8

19 files changed

+913
-172
lines changed

Diff for: .gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/.* export-ignore
2+
/_test export-ignore

Diff for: .github/workflows/phpTestLinux.yml

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: PHP Tests on Linux
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
testLinux:
7+
name: PHP ${{ matrix.php-versions }} DokuWiki ${{ matrix.dokuwiki-branch }}
8+
runs-on: ubuntu-latest
9+
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
10+
11+
strategy:
12+
matrix:
13+
php-versions: ['7.2', '7.3', '7.4', '8.0']
14+
dokuwiki-branch: [ 'master', 'stable']
15+
exclude:
16+
- dokuwiki-branch: 'stable'
17+
php-versions: '8.0'
18+
fail-fast: false
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v2
23+
24+
- name: Setup PHP
25+
uses: shivammathur/setup-php@v2
26+
with:
27+
php-version: ${{ matrix.php-versions }}
28+
extensions: mbstring, intl, PDO, pdo_sqlite, bz2
29+
30+
- name: Setup problem matchers
31+
run: |
32+
echo ::add-matcher::${{ runner.tool_cache }}/php.json
33+
echo ::add-matcher::${{ runner.tool_cache }}/phpunit.json
34+
35+
- name: Download DokuWiki Test-setup
36+
run: wget https://raw.github.com/splitbrain/dokuwiki-travis/master/travis.sh
37+
38+
- name: Run DokuWiki Test-setup
39+
env:
40+
CI_SERVER: 1
41+
DOKUWIKI: ${{ matrix.dokuwiki-branch }}
42+
run: sh travis.sh
43+
44+
- name: Setup PHPUnit
45+
run: |
46+
php _test/fetchphpunit.php
47+
cd _test
48+
49+
- name: Run PHPUnit
50+
run: |
51+
cd _test
52+
php phpunit.phar --verbose --stderr --group plugin_xref

Diff for: Grok.php

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace dokuwiki\plugin\xref;
4+
5+
use dokuwiki\HTTP\DokuHTTPClient;
6+
7+
class Grok
8+
{
9+
10+
protected $baseUrl;
11+
protected $def;
12+
protected $path;
13+
14+
public function __construct($reference, $baseUrl = 'https://codesearch.dokuwiki.org')
15+
{
16+
$heuristic = new Heuristics($reference);
17+
$this->def = $heuristic->getDef();
18+
$this->path = $heuristic->getPath();
19+
$this->baseUrl = rtrim($baseUrl, '/');
20+
}
21+
22+
/**
23+
* Return the URL that leads to the search interface
24+
*
25+
* @return string
26+
*/
27+
public function getSearchUrl()
28+
{
29+
if ($this->def === '' && $this->path === '') return $this->baseUrl;
30+
31+
$url = $this->baseUrl . '/search?';
32+
$param = [
33+
'project' => 'dokuwiki',
34+
'defs' => $this->def,
35+
'path' => $this->path,
36+
];
37+
$url .= buildURLparams($param, '&');
38+
return $url;
39+
}
40+
41+
/**
42+
* Return the URL that allows to query the API
43+
*
44+
* @return string
45+
*/
46+
public function getAPIUrl()
47+
{
48+
$url = $this->baseUrl . '/api/v1/search?';
49+
$param = [
50+
'projects' => 'dokuwiki',
51+
'def' => $this->def,
52+
'path' => $this->path,
53+
];
54+
$url .= buildURLparams($param, '&');
55+
return $url;
56+
}
57+
58+
/**
59+
* Return the number of results to expect
60+
*
61+
* @return false|int false on errors
62+
*/
63+
public function getResultCount()
64+
{
65+
if ($this->def === '' && $this->path === '') return 0;
66+
67+
$http = new DokuHTTPClient();
68+
$http->timeout = 5;
69+
$json = $http->get($this->getAPIUrl());
70+
if (!$json) return false;
71+
$data = json_decode($json, true);
72+
if (!$data) return false;
73+
if (!isset($data['resultCount'])) return false;
74+
return $data['resultCount'];
75+
}
76+
}

Diff for: Heuristics.php

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<?php
2+
3+
namespace dokuwiki\plugin\xref;
4+
5+
/**
6+
* Figure out what to send to Grok to hopefully show the right, single hit
7+
*/
8+
class Heuristics
9+
{
10+
11+
/** @var string the definition to search */
12+
protected $def = '';
13+
/** @var string the path to use */
14+
protected $path = '';
15+
16+
/**
17+
* Try to gues what the given reference means and how to best search for it
18+
*
19+
* @param string $reference
20+
*/
21+
public function __construct($reference)
22+
{
23+
if ($reference !== '') $reference = $this->checkHash($reference);
24+
if ($reference !== '') $reference = $this->checkFilename($reference);
25+
if ($reference !== '') $reference = $this->checkNamespace($reference);
26+
if ($reference !== '') $reference = $this->checkClassPrefix($reference);
27+
if ($reference !== '') $reference = $this->checkVariable($reference);
28+
if ($reference !== '') $reference = $this->checkFunction($reference);
29+
if ($reference !== '') $reference = $this->checkPSRClass($reference);
30+
if ($reference !== '') $this->def = $reference;
31+
}
32+
33+
/**
34+
* @return string
35+
*/
36+
public function getDef()
37+
{
38+
return trim(preg_replace('/[^\w]+/', '', $this->def));
39+
}
40+
41+
/**
42+
* @return string
43+
*/
44+
public function getPath()
45+
{
46+
return trim(preg_replace('/[^\w.]+/', ' ', $this->path));
47+
}
48+
49+
/**
50+
* Handle things in the form path#symbol
51+
*
52+
* @param string $reference
53+
* @return string
54+
*/
55+
protected function checkHash($reference)
56+
{
57+
if (strpos($reference, '#') === false) return $reference;
58+
list($this->path, $this->def) = explode('#', $reference, 2);
59+
return '';
60+
}
61+
62+
/**
63+
* Known file extension?
64+
*
65+
* @param string $reference
66+
* @return mixed|string
67+
*/
68+
protected function checkFilename($reference)
69+
{
70+
if (preg_match('/\.(php|js|css|html)$/', $reference)) {
71+
$this->def = '';
72+
$this->path = $reference;
73+
return '';
74+
}
75+
return $reference;
76+
}
77+
78+
/**
79+
* Namespaces are paths
80+
*
81+
* @param string $reference
82+
* @return string
83+
*/
84+
protected function checkNamespace($reference)
85+
{
86+
if (strpos($reference, '\\') === false) return $reference;
87+
88+
$parts = explode('\\', $reference);
89+
$parts = array_filter($parts);
90+
$reference = array_pop($parts); // last part may be more than a class
91+
92+
// our classes are in inc
93+
if ($parts[0] == 'dokuwiki') $parts[0] = 'inc';
94+
95+
$this->path = join(' ', $parts);
96+
97+
return $reference;
98+
}
99+
100+
/**
101+
* Is there something called on a class?
102+
*/
103+
protected function checkClassPrefix($reference)
104+
{
105+
if (
106+
strpos($reference, '::') === false &&
107+
strpos($reference, '->') === false
108+
) {
109+
return $reference;
110+
}
111+
list($class, $reference) = preg_split('/(::|->)/', $reference, 2);
112+
113+
$this->path .= ' ' . $class;
114+
$this->def = $reference;
115+
return '';
116+
}
117+
118+
/**
119+
* Clearly a variable
120+
*
121+
* @param string $reference
122+
* @return string
123+
*/
124+
protected function checkVariable($reference)
125+
{
126+
if ($reference[0] == '$') {
127+
$this->def = $reference;
128+
return '';
129+
}
130+
return $reference;
131+
}
132+
133+
/**
134+
* It's a function
135+
*
136+
* @param string $reference
137+
* @return string
138+
*/
139+
protected function checkFunction($reference)
140+
{
141+
if (substr($reference, -2) == '()') {
142+
$this->def = $reference;
143+
return '';
144+
}
145+
if (preg_match('/\(.+?\)$/', $reference)) {
146+
[$reference, /* $arguments */] = explode('(', $reference, 2);
147+
$this->def = $reference;
148+
return '';
149+
}
150+
return $reference;
151+
}
152+
153+
/**
154+
* Upercase followed by lowercase letter, must be a class
155+
*
156+
* Those are in their own files, so add it to the path
157+
* @param $reference
158+
* @return mixed|string
159+
*/
160+
protected function checkPSRClass($reference)
161+
{
162+
if (preg_match('/^[A-Z][a-z]/', $reference)) {
163+
$this->def = $reference;
164+
$this->path .= ' ' . $reference;
165+
return '';
166+
}
167+
return $reference;
168+
}
169+
}

0 commit comments

Comments
 (0)