Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase the plugin on grok #5

Merged
merged 12 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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')
splitbrain marked this conversation as resolved.
Show resolved Hide resolved
{
$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) == '()') {
splitbrain marked this conversation as resolved.
Show resolved Hide resolved
$this->def = $reference;
return '';
}
splitbrain marked this conversation as resolved.
Show resolved Hide resolved
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
Loading