Skip to content

Commit 518bf35

Browse files
authored
Merge pull request #737 from cosmocode/hsbund
hsbund improvements
2 parents 074c9a5 + 9d26e36 commit 518bf35

24 files changed

+571
-88
lines changed

_test/SearchConfigTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,40 @@ public function test_filtervars_simple()
3333
$this->assertEquals(date('Y-m-d'), $searchConfig->applyFilterVars('$DATE(now)$'));
3434
}
3535

36+
public function test_filtervars_nsorid()
37+
{
38+
global $INFO;
39+
40+
41+
$searchConfig = new SearchConfig([]);
42+
43+
// normal page
44+
$INFO['id'] = 'foo:bar:baz';
45+
$this->assertEquals('foo:bar:baz', $searchConfig->applyFilterVars('$NSORID$'));
46+
47+
// start page: start in namespace
48+
$INFO['id'] = 'foo:bar:start';
49+
saveWikiText($INFO['id'], 'start page', 'start created');
50+
$this->assertEquals('foo:bar', $searchConfig->applyFilterVars('$NSORID$'));
51+
saveWikiText($INFO['id'], '', 'start page deleted');
52+
clearstatcache();
53+
54+
// start page: same as namespace in namespace
55+
$INFO['id'] = 'foo:bar:bar';
56+
saveWikiText($INFO['id'], 'start page', 'start created');
57+
$this->assertEquals('foo:bar', $searchConfig->applyFilterVars('$NSORID$'));
58+
saveWikiText($INFO['id'], '', 'start page deleted');
59+
clearstatcache();
60+
61+
// start page: same as namespace in above namespace
62+
// incidally this is the same as a normal page
63+
$INFO['id'] = 'foo:bar';
64+
saveWikiText($INFO['id'], 'start page', 'start created');
65+
$this->assertEquals('foo:bar', $searchConfig->applyFilterVars('$NSORID$'));
66+
saveWikiText($INFO['id'], '', 'start page deleted');
67+
clearstatcache();
68+
}
69+
3670
public function test_filtervars_struct()
3771
{
3872
global $INFO;

action/migration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ protected function getFixedValues($row)
413413
}
414414
}
415415

416-
if (!empty($fixes)) {
416+
if ($fixes !== []) {
417417
$fixes = array_map(static fn($set, $key) => "$key = '$set'", $fixes, array_keys($fixes));
418418
}
419419

helper/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class helper_plugin_struct_config extends Plugin
2020
*/
2121
public function parseSort($val)
2222
{
23-
if (substr($val, 0, 1) == '^') {
23+
if (str_starts_with($val, '^')) {
2424
return [substr($val, 1), false];
2525
}
2626
return [$val, true];

jsoneditor/setup.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ jQuery(function () {
2828
this.updateEditor = function () {
2929
editor.setText($config.val());
3030
};
31+
// collapse all nodes except for the new element
32+
if(!$config.parents('.new').length) {
33+
editor.collapseAll();
34+
}
3135
});
3236

3337
/**

lang/en/lang.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@
8181
$lang['Exception no sqlite'] = 'The struct plugin requires the sqlite plugin. Please install and enable it.';
8282
$lang['Exception column not in table'] = 'There is no column %s in schema %s.';
8383
$lang['Exception datefilter'] = 'The filter: \'<code>$Date(%s)$</code>\' contains an unsupported value.';
84-
$lang['Warning: no filters for cloud'] = 'Filters are not supported for struct clouds.';
8584
$lang['sort'] = 'Sort by this column';
8685
$lang['next'] = 'Next page';
8786
$lang['prev'] = 'Previous page';

meta/Assignments.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,12 @@ protected function matchPagePattern($pattern, $page, $pns = null)
291291
}
292292

293293
$ans = ':' . cleanID($pattern) . ':';
294-
if (substr($pattern, -2) == '**') {
294+
if (str_ends_with($pattern, '**')) {
295295
// upper namespaces match
296-
if (strpos($pns, $ans) === 0) {
296+
if (str_starts_with($pns, $ans)) {
297297
return true;
298298
}
299-
} elseif (substr($pattern, -1) == '*') {
299+
} elseif (str_ends_with($pattern, '*')) {
300300
// namespaces match exact
301301
if ($ans == $pns) {
302302
return true;

meta/Column.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ public static function allTypes($reload = false)
193193
$files = glob(DOKU_PLUGIN . 'struct/types/*.php');
194194
foreach ($files as $file) {
195195
$file = basename($file, '.php');
196-
if (substr($file, 0, 8) == 'Abstract') continue;
197-
if (substr($file, 0, 5) == 'Trait') continue;
198-
if (substr($file, 0, 4) == 'Auto') continue;
196+
if (str_starts_with($file, 'Abstract')) continue;
197+
if (str_starts_with($file, 'Trait')) continue;
198+
if (str_starts_with($file, 'Auto')) continue;
199199
$map[$file] = 'dokuwiki\\plugin\\struct\\types\\' . $file;
200200
}
201201

meta/ConfigParser.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class ConfigParser
3030
'csv' => true,
3131
'nesting' => 0,
3232
'index' => 0,
33-
'classes' => []
33+
'classes' => [],
34+
'actcol' => -1,
3435
];
3536

3637
/**
@@ -131,6 +132,11 @@ public function __construct($lines)
131132
case 'classes':
132133
$this->config['classes'] = $this->parseClasses($val);
133134
break;
135+
case 'actcol':
136+
case 'actioncol':
137+
case 'actioncolumn':
138+
$this->config['actcol'] = (int) $val;
139+
break;
134140
default:
135141
$data = ['config' => &$this->config, 'key' => $key, 'val' => $val];
136142
$ev = new Event('PLUGIN_STRUCT_CONFIGPARSER_UNKNOWNKEY', $data);

meta/SchemaEditor.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function getEditor()
6363
$form->addHTML($this->adminColumn($col->getColref(), $col));
6464
}
6565

66-
// FIXME new one needs to be added dynamically, this is just for testing
66+
// Add one new field at the end
6767
$form->addHTML($this->adminColumn('new1', new Column($this->schema->getMaxsort() + 10, new Text()), 'new'));
6868

6969
$form->addHTML('</table>');
@@ -117,6 +117,7 @@ protected function adminColumn($column_id, Column $col, $key = 'cols')
117117
$base = 'schema[' . $key . '][' . $column_id . ']'; // base name for all fields
118118

119119
$class = $col->isEnabled() ? '' : 'disabled';
120+
if ($key === 'new') $class .= ' new';
120121

121122
$html = "<tr class=\"$class\">";
122123

meta/SearchCloud.php

Lines changed: 29 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,48 +14,40 @@ class SearchCloud extends SearchConfig
1414
protected $limit = '';
1515

1616
/**
17-
* Transform the set search parameters into a statement
17+
* We do not have pagination in clouds, so we can work with a limit within SQL
1818
*
19-
* @return array ($sql, $opts) The SQL and parameters to execute
19+
* @param int $limit
2020
*/
21-
public function getSQL()
21+
public function setLimit($limit)
2222
{
23-
if (!$this->columns) throw new StructException('nocolname');
24-
25-
$QB = new QueryBuilder();
26-
reset($this->schemas);
27-
$schema = current($this->schemas);
28-
$datatable = 'data_' . $schema->getTable();
29-
30-
$QB->addTable($datatable);
31-
32-
// add conditional page clauses if pid has a value
33-
$subAnd = $QB->filters()->whereSubAnd();
34-
$subAnd->whereAnd("$datatable.pid = ''");
35-
36-
$subOr = $subAnd->whereSubOr();
37-
$subOr->whereAnd("GETACCESSLEVEL($datatable.pid) > 0");
38-
$subOr->whereAnd("PAGEEXISTS($datatable.pid) = 1");
39-
$subOr->whereSubOr()
40-
->whereAnd('ASSIGNED == 1')
41-
->whereSubOr()
42-
->whereAnd("$datatable.rid > 0")
43-
->whereAnd("ASSIGNED IS NULL");
44-
45-
// add conditional schema assignment check
46-
$QB->addLeftJoin(
47-
$datatable,
48-
'schema_assignments',
49-
'',
50-
"$datatable.pid != ''
51-
AND $datatable.pid = schema_assignments.pid
52-
AND schema_assignments.tbl = '{$schema->getTable()}'"
53-
);
54-
55-
$QB->filters()->whereAnd("$datatable.latest = 1");
56-
$QB->filters()->where('AND', 'tag IS NOT \'\'');
23+
$this->limit = " LIMIT $limit";
24+
}
25+
26+
/**
27+
* @inheritdoc
28+
*/
29+
protected function runSQLBuilder()
30+
{
31+
$sqlBuilder = new SearchSQLBuilder();
32+
$sqlBuilder->setSelectLatest($this->selectLatest);
33+
$sqlBuilder->addSchemas($this->schemas, false);
34+
$this->addTagSelector($sqlBuilder);
35+
$sqlBuilder->getQueryBuilder()->addGroupByStatement('tag');
36+
$sqlBuilder->getQueryBuilder()->addOrderBy('count DESC');
37+
$sqlBuilder->addFilters($this->filter);
38+
return $sqlBuilder;
39+
}
40+
41+
/**
42+
* Add the tag selector to the SQLBuilder
43+
*/
44+
protected function addTagSelector(SearchSQLBuilder $builder)
45+
{
46+
$QB = $builder->getQueryBuilder();
5747

5848
$col = $this->columns[0];
49+
$datatable = "data_{$col->getTable()}";
50+
5951
if ($col->isMulti()) {
6052
$multitable = "multi_{$col->getTable()}";
6153
$MN = $QB->generateTableAlias('M');
@@ -77,23 +69,8 @@ public function getSQL()
7769
$colname = $datatable . '.' . $col->getColName();
7870
}
7971
$QB->addSelectStatement("COUNT($colname)", 'count');
80-
$QB->addSelectColumn('schema_assignments', 'assigned', 'ASSIGNED');
81-
$QB->addGroupByStatement('tag');
82-
$QB->addOrderBy('count DESC');
83-
84-
[$sql, $opts] = $QB->getSQL();
85-
return [$sql . $this->limit, $opts];
8672
}
8773

88-
/**
89-
* We do not have pagination in clouds, so we can work with a limit within SQL
90-
*
91-
* @param int $limit
92-
*/
93-
public function setLimit($limit)
94-
{
95-
$this->limit = " LIMIT $limit";
96-
}
9774

9875
/**
9976
* Execute this search and return the result

meta/SearchConfig.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace dokuwiki\plugin\struct\meta;
44

5+
use dokuwiki\File\PageResolver;
6+
57
/**
68
* Class SearchConfig
79
*
@@ -93,9 +95,9 @@ protected function determineCacheFlag($filters)
9395
foreach ($filters as $filter) {
9496
if (is_array($filter)) $filter = $filter[2]; // this is the format we get fro the config parser
9597

96-
if (strpos($filter, '$USER$') !== false) {
98+
if (str_contains($filter, '$USER$')) {
9799
$flags |= self::$CACHE_USER;
98-
} elseif (strpos($filter, '$TODAY$') !== false) {
100+
} elseif (str_contains($filter, '$TODAY$')) {
99101
$flags |= self::$CACHE_DATE;
100102
}
101103
}
@@ -116,6 +118,7 @@ protected function applyFilterVars($filter)
116118
if (!isset($INFO['id'])) {
117119
$INFO['id'] = '';
118120
}
121+
$ns = getNS($INFO['id']);
119122

120123
// apply inexpensive filters first
121124
$filter = str_replace(
@@ -128,14 +131,30 @@ protected function applyFilterVars($filter)
128131
],
129132
[
130133
$INFO['id'],
131-
getNS($INFO['id']),
134+
$ns,
132135
noNS($INFO['id']),
133136
$INPUT->server->str('REMOTE_USER'),
134137
date('Y-m-d')
135138
],
136139
$filter
137140
);
138141

142+
// apply namespace or id placeholder #712
143+
// returns the namespace for start pages, otherwise the ID
144+
if (preg_match('/\$NSORID\$/', $filter)) {
145+
$resolver = new PageResolver('');
146+
147+
$start = $resolver->resolveId($ns . ':');
148+
if ($start === $INFO['id']) {
149+
// This is a start page, we return the namespace
150+
$val = $ns;
151+
} else {
152+
// This is a normal page, we return the ID
153+
$val = $INFO['id'];
154+
}
155+
$filter = str_replace('$NSORID$', $val, $filter);
156+
}
157+
139158
// apply struct column placeholder (we support only one!)
140159
// or apply date formula, given as strtotime
141160
if (preg_match('/^(.*?)(?:\$STRUCT\.(.*?)\$)(.*?)$/', $filter, $match)) {

meta/SearchSQLBuilder.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ public function __construct()
2727
* Add the schemas to the query
2828
*
2929
* @param Schema[] $schemas Schema names to query
30+
* @param bool $selectMeta Select meta columns (pid, rid, rev, assigned)
3031
*/
31-
public function addSchemas($schemas)
32+
public function addSchemas($schemas, $selectMeta = true)
3233
{
3334
// basic tables
3435
$first_table = '';
@@ -60,12 +61,14 @@ public function addSchemas($schemas)
6061
AND schema_assignments.tbl = '{$schema->getTable()}'"
6162
);
6263

63-
$this->qb->addSelectColumn($datatable, 'rid');
64-
$this->qb->addSelectColumn($datatable, 'pid', 'PID');
65-
$this->qb->addSelectColumn($datatable, 'rev');
66-
$this->qb->addSelectColumn('schema_assignments', 'assigned', 'ASSIGNED');
67-
$this->qb->addGroupByColumn($datatable, 'pid');
68-
$this->qb->addGroupByColumn($datatable, 'rid');
64+
if ($selectMeta) {
65+
$this->qb->addSelectColumn($datatable, 'rid');
66+
$this->qb->addSelectColumn($datatable, 'pid', 'PID');
67+
$this->qb->addSelectColumn($datatable, 'rev');
68+
$this->qb->addSelectColumn('schema_assignments', 'assigned', 'ASSIGNED');
69+
$this->qb->addGroupByColumn($datatable, 'pid');
70+
$this->qb->addGroupByColumn($datatable, 'rid');
71+
}
6972

7073
$first_table = $datatable;
7174
}

renderer/csv.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public function emaillink($address, $name = null)
168168

169169
public function plugin($name, $args, $state = '', $match = '')
170170
{
171-
if (substr($name, 0, 7) == 'struct_') {
171+
if (str_starts_with($name, 'struct_')) {
172172
parent::plugin($name, $args, $state, $match);
173173
} else {
174174
$this->cdata($match);

script.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ jQuery(function () {
55
/* DOKUWIKI:include script/AggregationEditor.js */
66
/* DOKUWIKI:include script/InlineEditor.js */
77
/* DOKUWIKI:include script/StructFilter.js */
8+
/* DOKUWIKI:include_once script/vanilla-combobox.js */
89

910
function init() {
1011
EntryEditor(jQuery('#dw__editform, form.bureaucracy__plugin'));
1112
SchemaEditor();
1213
jQuery('div.structaggregationeditor table').each(AggregationEditor);
13-
InlineEditor(jQuery('div.structaggregation table'));
14+
InlineEditor(jQuery('div.structaggregation table, #plugin__struct_output table'));
1415
}
1516

1617
jQuery(init);

0 commit comments

Comments
 (0)