Stephan Bösch-Plepelits
7 years ago
42 changed files with 782 additions and 110 deletions
-
2README.md
-
25conf.php-dist
-
64doc/TwigJS.md
-
1lang/ast.json
-
1lang/ca.json
-
1lang/cs.json
-
1lang/da.json
-
3lang/de.json
-
1lang/el.json
-
3lang/en.json
-
1lang/es.json
-
1lang/et.json
-
1lang/fr.json
-
1lang/hu.json
-
1lang/it.json
-
1lang/ja.json
-
1lang/nl.json
-
1lang/pl.json
-
1lang/ro.json
-
1lang/ru.json
-
1lang/sr.json
-
1lang/template.json
-
1lang/uk.json
-
2lib/modulekit/form
-
2lib/modulekit/lang
-
4modulekit.php
-
3package.json
-
73repo.php
-
30src/CategoryBase.js
-
14src/CategoryIndex.js
-
20src/CategoryOverpass.js
-
207src/OpenStreetBrowserLoader.js
-
43src/RepositoryBase.php
-
52src/RepositoryDir.php
-
58src/RepositoryGit.php
-
3src/addCategories.css
-
140src/addCategories.js
-
12src/category.css
-
17src/index.js
-
12src/markers.js
-
70src/repositories.php
-
15style.css
@ -1,5 +1,6 @@ |
|||
{ |
|||
"main:options": "Opcions", |
|||
"more": "més", |
|||
"more_categories": "Més categories", |
|||
"save": "Guardar" |
|||
} |
@ -1,6 +1,7 @@ |
|||
{ |
|||
"main:options": "Opciones", |
|||
"more": "más", |
|||
"more_categories": "Más categorías", |
|||
"options:data_lang": "Idioma de datos", |
|||
"options:data_lang:local": "Idioma local", |
|||
"options:ui_lang": "Idioma de interfaz", |
|||
|
@ -1,6 +1,7 @@ |
|||
{ |
|||
"main:options": "Beállítások", |
|||
"more": "több", |
|||
"more_categories": "Több kategória", |
|||
"options:data_lang": "Adatnyelv", |
|||
"options:data_lang:local": "Helyi nyelv", |
|||
"options:ui_lang": "Menünyelv", |
|||
|
@ -1 +1 @@ |
|||
Subproject commit 819380c621e2ec79d5ca22db6af44d0eaf1c158c |
|||
Subproject commit 4a94f64c11d3f16b01a5aec6afd5cfb4b7257572 |
@ -1 +1 @@ |
|||
Subproject commit 1013930aafa47f214f6e9d4b68c684acf4922efc |
|||
Subproject commit 80118dbcaafa9ab95298be95548126071efc069f |
@ -0,0 +1,73 @@ |
|||
<?php include "conf.php"; /* load a local configuration */ ?>
|
|||
<?php session_start(); ?>
|
|||
<?php require 'vendor/autoload.php'; /* composer includes */ ?>
|
|||
<?php include "modulekit/loader.php"; /* loads all php-includes */ ?>
|
|||
<?php include "node_modules/json-multiline-strings/src/json-multiline-strings.php"; ?>
|
|||
<?php call_hooks("init"); /* initialize submodules */ ?>
|
|||
<?php |
|||
$allRepositories = getRepositories(); |
|||
|
|||
if (!isset($_REQUEST['repo'])) { |
|||
Header("Content-Type: application/json; charset=utf-8"); |
|||
print '{'; |
|||
|
|||
$c = 0; |
|||
foreach ($allRepositories as $repoId => $repoData) { |
|||
$repo = getRepo($repoId, $repoData); |
|||
|
|||
print $c++ ? ',' : ''; |
|||
print json_encode($repoId, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) . ':'; |
|||
$info = $repo->info(); |
|||
|
|||
if (isset($repoData['repositoryUrl'])) { |
|||
$info['repositoryUrl'] = $repoData['repositoryUrl']; |
|||
} |
|||
if (isset($repoData['categoryUrl'])) { |
|||
$info['categoryUrl'] = $repoData['categoryUrl']; |
|||
} |
|||
|
|||
print json_encode($info, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_FORCE_OBJECT); |
|||
} |
|||
|
|||
print '}'; |
|||
exit(0); |
|||
} |
|||
|
|||
$repoId = $_REQUEST['repo']; |
|||
if (!array_key_exists($repoId, $allRepositories)) { |
|||
Header("HTTP/1.1 404 Repository not found"); |
|||
exit(0); |
|||
} |
|||
|
|||
$repoData = $allRepositories[$repoId]; |
|||
$repo = getRepo($repoId, $repoData); |
|||
|
|||
$cacheDir = null; |
|||
$ts = $repo->timestamp($path); |
|||
if (isset($config['cache'])) { |
|||
$cacheDir = "{$config['cache']}/repo"; |
|||
@mkdir($cacheDir); |
|||
$cacheTs = filemtime("{$cacheDir}/{$repoId}.json"); |
|||
if ($cacheTs === $ts) { |
|||
Header("Content-Type: application/json; charset=utf-8"); |
|||
readfile("{$cacheDir}/{$repoId}.json"); |
|||
exit(0); |
|||
} |
|||
} |
|||
|
|||
$data = $repo->data(); |
|||
|
|||
if (isset($repoData['repositoryUrl'])) { |
|||
$data['repositoryUrl'] = $repoData['repositoryUrl']; |
|||
} |
|||
if (isset($repoData['categoryUrl'])) { |
|||
$data['categoryUrl'] = $repoData['categoryUrl']; |
|||
} |
|||
|
|||
$ret = json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); |
|||
|
|||
Header("Content-Type: application/json; charset=utf-8"); |
|||
print $ret; |
|||
|
|||
file_put_contents("{$cacheDir}/{$repoId}.json", $ret); |
|||
touch("{$cacheDir}/{$repoId}.json", $ts); |
@ -0,0 +1,43 @@ |
|||
<?php |
|||
class RepositoryBase { |
|||
function __construct ($id, $def) { |
|||
$this->def = $def; |
|||
$this->path = $def['path']; |
|||
} |
|||
|
|||
function timestamp () { |
|||
return null; |
|||
} |
|||
|
|||
function info () { |
|||
$ret = array(); |
|||
|
|||
foreach (array('name') as $k) { |
|||
if (array_key_exists($k, $this->def)) { |
|||
$ret[$k] = $this->def[$k]; |
|||
} |
|||
} |
|||
|
|||
$ret['timestamp'] = Date(DATE_ISO8601, $this->timestamp()); |
|||
|
|||
return $ret; |
|||
} |
|||
|
|||
function data () { |
|||
$data = array( |
|||
'categories' => array(), |
|||
'templates' => array(), |
|||
'timestamp' => Date(DATE_ISO8601, $this->timestamp()), |
|||
); |
|||
|
|||
return $data; |
|||
} |
|||
|
|||
function isCategory ($data) { |
|||
if (!array_key_exists('type', $data)) { |
|||
return false; |
|||
} |
|||
|
|||
return in_array($data['type'], array('index', 'overpass')); |
|||
} |
|||
} |
@ -0,0 +1,52 @@ |
|||
<?php |
|||
class RepositoryDir extends RepositoryBase { |
|||
function timestamp () { |
|||
$ts = 0; |
|||
$d = opendir($this->path); |
|||
while ($f = readdir($d)) { |
|||
$t = filemtime("{$this->path}/{$f}"); |
|||
if ($t > $ts) { |
|||
$ts = $t; |
|||
} |
|||
} |
|||
closedir($d); |
|||
|
|||
return $ts; |
|||
} |
|||
|
|||
function data () { |
|||
$data = parent::data(); |
|||
|
|||
$d = opendir($this->path); |
|||
while ($f = readdir($d)) { |
|||
if (preg_match("/^([0-9a-zA-Z_\-]+)\.json$/", $f, $m) && $f !== 'package.json') { |
|||
$d1 = json_decode(file_get_contents("{$this->path}/{$f}"), true); |
|||
|
|||
if (!$this->isCategory($d1)) { |
|||
continue; |
|||
} |
|||
|
|||
$data['categories'][$m[1]] = jsonMultilineStringsJoin($d1, array('exclude' => array(array('const')))); |
|||
} |
|||
|
|||
if (preg_match("/^(detailsBody|popupBody).html$/", $f, $m)) { |
|||
$data['templates'][$m[1]] = file_get_contents("{$this->path}/{$f}"); |
|||
} |
|||
} |
|||
closedir($d); |
|||
|
|||
return $data; |
|||
} |
|||
|
|||
function scandir($path="") { |
|||
return scandir("{$this->path}/{$path}"); |
|||
} |
|||
|
|||
function file_get_contents ($file) { |
|||
return file_get_contents("{$this->path}/{$file}"); |
|||
} |
|||
|
|||
function file_put_contents ($file, $content) { |
|||
return file_put_contents("{$this->path}/{$file}", $content); |
|||
} |
|||
} |
@ -0,0 +1,58 @@ |
|||
<?php |
|||
class RepositoryGit extends RepositoryBase { |
|||
function timestamp () { |
|||
$ts = (int)shell_exec("cd " . escapeShellArg($this->path) . "; git log -1 --pretty=format:%ct"); |
|||
|
|||
return $ts; |
|||
} |
|||
|
|||
function data () { |
|||
$data = parent::data(); |
|||
|
|||
$d = popen("cd " . escapeShellArg($this->path) . "; git ls-tree HEAD", "r"); |
|||
while ($r = fgets($d)) { |
|||
if (preg_match("/^[0-9]{6} blob [0-9a-f]{40}\t(([0-9a-zA-Z_\-]+)\.json)$/", $r, $m)) { |
|||
$f = $m[1]; |
|||
$id = $m[2]; |
|||
|
|||
if ($f === 'package.json') { |
|||
continue; |
|||
} |
|||
|
|||
$d1 = json_decode(shell_exec("cd " . escapeShellArg($this->path) . "; git show HEAD:" . escapeShellArg($f)), true); |
|||
|
|||
if (!$this->isCategory($d1)) { |
|||
continue; |
|||
} |
|||
|
|||
$data['categories'][$id] = jsonMultilineStringsJoin($d1, array('exclude' => array(array('const')))); |
|||
} |
|||
|
|||
if (preg_match("/^[0-9]{6} blob [0-9a-f]{40}\t((detailsBody|popupBody)\.html)$/", $r, $m)) { |
|||
$data['templates'][$m[2]] = shell_exec("cd " . escapeShellArg($this->path) . "; git show HEAD:" . escapeShellArg($m[1])); |
|||
} |
|||
} |
|||
pclose($d); |
|||
|
|||
return $data; |
|||
} |
|||
|
|||
function scandir($path="") { |
|||
if ($path !== '' && substr($path, -1) !== '/') { |
|||
$path .= '/'; |
|||
} |
|||
|
|||
$d = popen("cd " . escapeShellArg($this->path) . "; git ls-tree HEAD " . escapeShellArg($path), "r"); |
|||
$ret = array(); |
|||
while ($r = fgets($d)) { |
|||
$ret[] = substr($r, 53); |
|||
} |
|||
pclose($d); |
|||
|
|||
return $ret; |
|||
} |
|||
|
|||
function file_get_contents ($file) { |
|||
return shell_exec("cd " . escapeShellArg($this->path) . "; git show HEAD:" . escapeShellArg($file)); |
|||
} |
|||
} |
@ -0,0 +1,3 @@ |
|||
#content.addCategories > #contentAddCategories { |
|||
display: block; |
|||
} |
@ -0,0 +1,140 @@ |
|||
var OpenStreetBrowserLoader = require('./OpenStreetBrowserLoader') |
|||
require('./addCategories.css') |
|||
var weightSort = require('weight-sort') |
|||
|
|||
var content |
|||
|
|||
function addCategoriesShow (repo) { |
|||
if (!content) { |
|||
content = document.createElement('div') |
|||
content.id = 'contentAddCategories' |
|||
document.getElementById('content').appendChild(content) |
|||
} |
|||
|
|||
content.innerHTML = 'Loading ...' |
|||
document.getElementById('content').className = 'addCategories' |
|||
|
|||
OpenStreetBrowserLoader.getRepo(repo, {}, function (err, repoData) { |
|||
while(content.firstChild) |
|||
content.removeChild(content.firstChild) |
|||
|
|||
var backLink = document.createElement('a') |
|||
backLink.className = 'back' |
|||
backLink.href = '#' |
|||
backLink.innerHTML = '<i class="fa fa-chevron-circle-left" aria-hidden="true"></i> ' |
|||
backLink.appendChild(document.createTextNode(lang('back'))) |
|||
|
|||
var categoryUrl = null |
|||
if (repoData.categoryUrl) { |
|||
categoryUrl = OverpassLayer.twig.twig({ data: repoData.categoryUrl, autoescape: true }) |
|||
} |
|||
|
|||
var list = {} |
|||
|
|||
if (repo) { |
|||
backLink.onclick = function () { |
|||
addCategoriesShow() |
|||
return false |
|||
} |
|||
content.appendChild(backLink) |
|||
|
|||
var h = document.createElement('h2') |
|||
h.appendChild(document.createTextNode(repo)) |
|||
content.appendChild(h) |
|||
|
|||
list = repoData.categories |
|||
} else { |
|||
backLink.onclick = function () { |
|||
addCategoriesHide() |
|||
return false |
|||
} |
|||
content.appendChild(backLink) |
|||
|
|||
var h = document.createElement('h2') |
|||
h.innerHTML = lang('more_categories') |
|||
content.appendChild(h) |
|||
|
|||
if (typeof repositoriesGitea === 'object' && repositoriesGitea.url) { |
|||
var a = document.createElement('a') |
|||
a.href = repositoriesGitea.url |
|||
a.target = '_blank' |
|||
a.innerHTML = lang('more_categories_gitea') |
|||
content.appendChild(a) |
|||
} |
|||
|
|||
list = weightSort(repoData, { |
|||
key: 'timestamp', |
|||
reverse: true |
|||
}) |
|||
} |
|||
|
|||
var ul = document.createElement('ul') |
|||
|
|||
for (var id in list) { |
|||
var data = list[id] |
|||
|
|||
var repositoryUrl = null |
|||
if (data.repositoryUrl) { |
|||
repositoryUrl = OverpassLayer.twig.twig({ data: data.repositoryUrl, autoescape: true }) |
|||
} |
|||
|
|||
var li = document.createElement('li') |
|||
|
|||
var a = document.createElement('a') |
|||
if (repo) { |
|||
a.href = '#categories=' + repo + '/' + id |
|||
a.onclick = function () { |
|||
addCategoriesHide() |
|||
} |
|||
} else { |
|||
a.href = '#' |
|||
a.onclick = function (id) { |
|||
addCategoriesShow(id) |
|||
return false |
|||
}.bind(this, id) |
|||
} |
|||
|
|||
li.appendChild(a) |
|||
a.appendChild(document.createTextNode('name' in data ? lang(data.name) : id)) |
|||
|
|||
var editLink = null |
|||
if (repo && categoryUrl) { |
|||
editLink = document.createElement('a') |
|||
editLink.href = categoryUrl.render({ repositoryId: repo, categoryId: id }) |
|||
} |
|||
if (!repo && repositoryUrl) { |
|||
editLink = document.createElement('a') |
|||
editLink.href = repositoryUrl.render({ repositoryId: id }) |
|||
} |
|||
if (editLink) { |
|||
editLink.className = 'source-code' |
|||
editLink.title = 'Show source code' |
|||
editLink.target = '_blank' |
|||
editLink.innerHTML = '<i class="fa fa-file-code-o" aria-hidden="true"></i>' |
|||
li.appendChild(document.createTextNode(' ')) |
|||
li.appendChild(editLink) |
|||
} |
|||
|
|||
ul.appendChild(li) |
|||
} |
|||
|
|||
content.appendChild(ul) |
|||
}) |
|||
} |
|||
|
|||
function addCategoriesHide () { |
|||
document.getElementById('content').className = 'list' |
|||
} |
|||
|
|||
register_hook('init', function (callback) { |
|||
var link = document.createElement('a') |
|||
link.className = 'addCategories' |
|||
link.href = '#' |
|||
link.onclick = function () { |
|||
addCategoriesShow() |
|||
return false |
|||
} |
|||
link.innerHTML = '<i class="fa fa-chevron-circle-down" aria-hidden="true"></i> ' + lang('more_categories') |
|||
|
|||
document.getElementById('contentList').appendChild(link) |
|||
}) |
@ -0,0 +1,70 @@ |
|||
<?php |
|||
function getRepositories () { |
|||
global $repositories; |
|||
global $repositoriesGitea; |
|||
$result = array(); |
|||
|
|||
if (isset($repositories)) { |
|||
$result = $repositories; |
|||
} |
|||
else { |
|||
$result = array( |
|||
'default' => array( |
|||
'path' => $config['categoriesDir'], |
|||
), |
|||
); |
|||
} |
|||
|
|||
if (isset($repositoriesGitea)) { |
|||
$d1 = opendir($repositoriesGitea['path']); |
|||
while ($f1 = readdir($d1)) { |
|||
if (substr($f1, 0, 1) !== '.') { |
|||
$d2 = opendir("{$repositoriesGitea['path']}/{$f1}"); |
|||
while ($f2 = readdir($d2)) { |
|||
if (substr($f2, 0, 1) !== '.') { |
|||
$f2id = substr($f2, 0, -4); |
|||
|
|||
$r = array( |
|||
'path' => "{$repositoriesGitea['path']}/{$f1}/{$f2}", |
|||
'type' => 'git', |
|||
); |
|||
|
|||
if (array_key_exists('url', $repositoriesGitea)) { |
|||
$r['repositoryUrl'] = "{$repositoriesGitea['url']}/{{ repositoryId }}"; |
|||
$r['categoryUrl'] = "{$repositoriesGitea['url']}/{{ repositoryId }}/src/{{ categoryId }}.json"; |
|||
} |
|||
|
|||
$result["{$f1}/{$f2id}"] = $r; |
|||
} |
|||
} |
|||
closedir($d2); |
|||
} |
|||
} |
|||
closedir($d1); |
|||
} |
|||
|
|||
return $result; |
|||
} |
|||
|
|||
function getRepo ($repoId, $repoData) { |
|||
switch (array_key_exists('type', $repoData) ? $repoData['type'] : 'dir') { |
|||
case 'git': |
|||
$repo = new RepositoryGit($repoId, $repoData); |
|||
break; |
|||
default: |
|||
$repo = new RepositoryDir($repoId, $repoData); |
|||
} |
|||
|
|||
return $repo; |
|||
} |
|||
|
|||
register_hook('init', function () { |
|||
global $repositoriesGitea; |
|||
|
|||
if (isset($repositoriesGitea) && array_key_exists('url', $repositoriesGitea)) { |
|||
$d = array('repositoriesGitea' => array( |
|||
'url' => $repositoriesGitea['url'], |
|||
)); |
|||
html_export_var($d); |
|||
} |
|||
}); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue