Skip to content

Commit

Permalink
Merge pull request #5 from splitbrain/codesearch
Browse files Browse the repository at this point in the history
Rebase the plugin on grok
  • Loading branch information
splitbrain committed Aug 7, 2023
2 parents 73a57c5 + f6d3559 commit 6f047e8
Show file tree
Hide file tree
Showing 19 changed files with 913 additions and 172 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/.* export-ignore
/_test export-ignore
52 changes: 52 additions & 0 deletions .github/workflows/phpTestLinux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: PHP Tests on Linux

on: [push, pull_request]

jobs:
testLinux:
name: PHP ${{ matrix.php-versions }} DokuWiki ${{ matrix.dokuwiki-branch }}
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository

strategy:
matrix:
php-versions: ['7.2', '7.3', '7.4', '8.0']
dokuwiki-branch: [ 'master', 'stable']
exclude:
- dokuwiki-branch: 'stable'
php-versions: '8.0'
fail-fast: false

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, intl, PDO, pdo_sqlite, bz2

- name: Setup problem matchers
run: |
echo ::add-matcher::${{ runner.tool_cache }}/php.json
echo ::add-matcher::${{ runner.tool_cache }}/phpunit.json
- name: Download DokuWiki Test-setup
run: wget https://raw.github.com/splitbrain/dokuwiki-travis/master/travis.sh

- name: Run DokuWiki Test-setup
env:
CI_SERVER: 1
DOKUWIKI: ${{ matrix.dokuwiki-branch }}
run: sh travis.sh

- name: Setup PHPUnit
run: |
php _test/fetchphpunit.php
cd _test
- name: Run PHPUnit
run: |
cd _test
php phpunit.phar --verbose --stderr --group plugin_xref
76 changes: 76 additions & 0 deletions Grok.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace dokuwiki\plugin\xref;

use dokuwiki\HTTP\DokuHTTPClient;

class Grok
{

protected $baseUrl;
protected $def;
protected $path;

public function __construct($reference, $baseUrl = 'https://codesearch.dokuwiki.org')
{
$heuristic = new Heuristics($reference);
$this->def = $heuristic->getDef();
$this->path = $heuristic->getPath();
$this->baseUrl = rtrim($baseUrl, '/');
}

/**
* Return the URL that leads to the search interface
*
* @return string
*/
public function getSearchUrl()
{
if ($this->def === '' && $this->path === '') return $this->baseUrl;

$url = $this->baseUrl . '/search?';
$param = [
'project' => 'dokuwiki',
'defs' => $this->def,
'path' => $this->path,
];
$url .= buildURLparams($param, '&');
return $url;
}

/**
* Return the URL that allows to query the API
*
* @return string
*/
public function getAPIUrl()
{
$url = $this->baseUrl . '/api/v1/search?';
$param = [
'projects' => 'dokuwiki',
'def' => $this->def,
'path' => $this->path,
];
$url .= buildURLparams($param, '&');
return $url;
}

/**
* Return the number of results to expect
*
* @return false|int false on errors
*/
public function getResultCount()
{
if ($this->def === '' && $this->path === '') return 0;

$http = new DokuHTTPClient();
$http->timeout = 5;
$json = $http->get($this->getAPIUrl());
if (!$json) return false;
$data = json_decode($json, true);
if (!$data) return false;
if (!isset($data['resultCount'])) return false;
return $data['resultCount'];
}
}
169 changes: 169 additions & 0 deletions Heuristics.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<?php

namespace dokuwiki\plugin\xref;

/**
* Figure out what to send to Grok to hopefully show the right, single hit
*/
class Heuristics
{

/** @var string the definition to search */
protected $def = '';
/** @var string the path to use */
protected $path = '';

/**
* Try to gues what the given reference means and how to best search for it
*
* @param string $reference
*/
public function __construct($reference)
{
if ($reference !== '') $reference = $this->checkHash($reference);
if ($reference !== '') $reference = $this->checkFilename($reference);
if ($reference !== '') $reference = $this->checkNamespace($reference);
if ($reference !== '') $reference = $this->checkClassPrefix($reference);
if ($reference !== '') $reference = $this->checkVariable($reference);
if ($reference !== '') $reference = $this->checkFunction($reference);
if ($reference !== '') $reference = $this->checkPSRClass($reference);
if ($reference !== '') $this->def = $reference;
}

/**
* @return string
*/
public function getDef()
{
return trim(preg_replace('/[^\w]+/', '', $this->def));
}

/**
* @return string
*/
public function getPath()
{
return trim(preg_replace('/[^\w.]+/', ' ', $this->path));
}

/**
* Handle things in the form path#symbol
*
* @param string $reference
* @return string
*/
protected function checkHash($reference)
{
if (strpos($reference, '#') === false) return $reference;
list($this->path, $this->def) = explode('#', $reference, 2);
return '';
}

/**
* Known file extension?
*
* @param string $reference
* @return mixed|string
*/
protected function checkFilename($reference)
{
if (preg_match('/\.(php|js|css|html)$/', $reference)) {
$this->def = '';
$this->path = $reference;
return '';
}
return $reference;
}

/**
* Namespaces are paths
*
* @param string $reference
* @return string
*/
protected function checkNamespace($reference)
{
if (strpos($reference, '\\') === false) return $reference;

$parts = explode('\\', $reference);
$parts = array_filter($parts);
$reference = array_pop($parts); // last part may be more than a class

// our classes are in inc
if ($parts[0] == 'dokuwiki') $parts[0] = 'inc';

$this->path = join(' ', $parts);

return $reference;
}

/**
* Is there something called on a class?
*/
protected function checkClassPrefix($reference)
{
if (
strpos($reference, '::') === false &&
strpos($reference, '->') === false
) {
return $reference;
}
list($class, $reference) = preg_split('/(::|->)/', $reference, 2);

$this->path .= ' ' . $class;
$this->def = $reference;
return '';
}

/**
* Clearly a variable
*
* @param string $reference
* @return string
*/
protected function checkVariable($reference)
{
if ($reference[0] == '$') {
$this->def = $reference;
return '';
}
return $reference;
}

/**
* It's a function
*
* @param string $reference
* @return string
*/
protected function checkFunction($reference)
{
if (substr($reference, -2) == '()') {
$this->def = $reference;
return '';
}
if (preg_match('/\(.+?\)$/', $reference)) {
[$reference, /* $arguments */] = explode('(', $reference, 2);
$this->def = $reference;
return '';
}
return $reference;
}

/**
* Upercase followed by lowercase letter, must be a class
*
* Those are in their own files, so add it to the path
* @param $reference
* @return mixed|string
*/
protected function checkPSRClass($reference)
{
if (preg_match('/^[A-Z][a-z]/', $reference)) {
$this->def = $reference;
$this->path .= ' ' . $reference;
return '';
}
return $reference;
}
}
Loading

0 comments on commit 6f047e8

Please sign in to comment.