Commit 77356ec0 authored by vermeul's avatar vermeul

...

parent 44d9eb13
......@@ -2,14 +2,9 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="28231bd6-2bb7-46e9-9022-3fa8a2d24ebf" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/.idea/deployment.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/sqldialects.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/YATA.class.php" beforeDir="false" afterPath="$PROJECT_DIR$/YATA.class.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/sql/yata.mysql.sql" beforeDir="false" afterPath="$PROJECT_DIR$/sql/yata.mysql.sql" afterDir="false" />
<change beforePath="$PROJECT_DIR$/sql/yata.postgres.sql" beforeDir="false" afterPath="$PROJECT_DIR$/sql/yata.postgres.sql" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/test.php" beforeDir="false" afterPath="$PROJECT_DIR$/tests/test.php" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
......@@ -32,7 +27,17 @@
<select />
</component>
<component name="FileEditorManager">
<leaf />
<leaf>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/YATA.class.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="369">
<caret line="593" column="7" selection-start-line="593" selection-start-column="7" selection-end-line="593" selection-end-column="7" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
......@@ -44,9 +49,11 @@
</list>
</option>
</component>
<component name="PhpServers">
<servers />
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="1440" />
<option name="y" value="-1637" />
<option name="y" value="23" />
<option name="width" value="1440" />
<option name="height" value="877" />
</component>
......@@ -55,7 +62,6 @@
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<expand>
......@@ -72,6 +78,7 @@
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
......@@ -103,23 +110,21 @@
<option name="presentableId" value="Default" />
<updated>1551878632829</updated>
<workItem from="1551878636142" duration="1645000" />
<workItem from="1551960702352" duration="157000" />
<workItem from="1552001409266" duration="239000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="1645000" />
<option name="totallyTimeSpent" value="2041000" />
</component>
<component name="ToolWindowManager">
<frame x="1440" y="-1637" width="1440" height="2537" extended-state="6" />
<frame x="0" y="23" width="1440" height="877" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="Favorites" side_tool="true" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.15665236" />
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.1602289" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Docker" show_stripe_button="false" />
<window_info anchor="bottom" id="Database Changes" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" />
<window_info anchor="bottom" id="Terminal" />
<window_info anchor="bottom" id="Event Log" side_tool="true" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="bottom" id="Run" order="2" />
......@@ -127,11 +132,37 @@
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="right" id="Database" />
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Database Changes" order="8" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" />
<window_info anchor="bottom" id="Event Log" order="11" side_tool="true" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="Database" order="3" weight="0.3297568" />
</layout>
<layout-to-restore>
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.15879828" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="bottom" id="Run" order="2" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Database Changes" order="8" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" />
<window_info anchor="bottom" id="Event Log" order="11" side_tool="true" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="Database" order="3" />
</layout-to-restore>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
......@@ -152,8 +183,8 @@
</entry>
<entry file="file://$PROJECT_DIR$/YATA.class.php">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1394">
<caret line="362" column="18" selection-start-line="362" selection-start-column="18" selection-end-line="362" selection-end-column="18" />
<state relative-caret-position="369">
<caret line="593" column="7" selection-start-line="593" selection-start-column="7" selection-end-line="593" selection-end-column="7" />
</state>
</provider>
</entry>
......
......@@ -54,8 +54,8 @@ Annotations usually contain comments and may be categorised (Categories: see bel
### Annotation per page
```
{{#annotpage: comment}}
{{#annotpage: comment | category}} # annotpage acts like a annotation, but has no corresponding annotpage_end element.
{{#annotpage: list }} # will list all annotations on that page
{{#annotpage: key=value, key2="value 2"}} # store page attributes
```
### Nested or overlapping annotations: Examples
......@@ -86,15 +86,24 @@ while annotation (b) will contain this part of the WikiText:
### display all annotations of a given page
To display all annotations on a page, just add
To display all annotations on a page, just add the magic word
```
{{#annotlist:}}
{{#annotlist:}}
{{#annot: list}} # alternative
```
somewhere in your Wikicode, preferably at the beginning or end of your page.
The output will be a sortable Wikitable which contains comment, category and
the extracted text.
somewhere in your Wikicode, preferably at the beginning or end of your page.
The output will be a sortable Wikitable which contains comment, category and
the extracted text.
If you want to display all **page annotations**, add the magic word
```
{{#annotpage: list}}
```
to your Wikipage.
## Querying annotations
......@@ -107,23 +116,21 @@ See the [SMW concepts](https://www.semantic-mediawiki.org/wiki/Help:Concepts)
### annotask Query syntax
```
[[category: category_name1 ]] # this category (and all categories below it)
[[category: category_name1, category_name2 ]] # category_name1 OR category_name2
[[category: #category_tag1, #category_tag2 ]] # category hashtags can be used as well
[[category: category_name1 ]] # every line is AND'ed, so these two lines mean:
[[category: category_name2 ]] # category_name1 AND category_name2
[[category: category_name1 ]] # this category (and all categories below it)
[[category: category_name1 || category_name2 ]] # category_name1 OR category_name2
[[category: #category_tag1 || #category_tag2 ]] # category hashtags can be used as well
[[category!: category_name1 ]] # category is NOT category_name1
[[wiki_text: %anything% ]] # wikitext LIKE %anything%
[[wiki_text: %anyth_ng% ]] # Underscore matches single characters
[[wiki_text!: %anything% ]] # wikitext NOT LIKE %anything%
[[category: category_name1 ]] # every line is AND'ed, so these two lines mean:
[[category: category_name2 ]] # category_name1 AND category_name2
[[page: comment | category_name]] # page contains comment and category
[[page: %comment% ]]
[[page: Constantinople | #place]] # ask for all pages that have place=Constantinople
[[page: 1450-1526 | #time]] # ask for all pages that have time=1450-1526
[[category!: category_name1 ]] # category is NOT category_name1
[[wiki_text: %anything% ]] # wikitext LIKE %anything%
[[wiki_text: %anyth_ng% ]] # Underscore matches single characters
[[wiki_text!: %anything% ]] # wikitext NOT LIKE %anything%
[[page: place=Constantinople ]] # only pages that have place=Constantinople
[[page: time="1450-1526" && place="Constantinople"]] # AND
[[page: time="1450-1526" || place="Constantinople"]] # OR
! "not" ("unequal")
% match any number of characters
......
......@@ -21,19 +21,24 @@ class YATA {
public static function onParserSetup( &$parser ) {
// Create a function hook associating the "example" magic word with renderExample()
$parser->setFunctionHook( 'annot', 'YATA::renderStartAnnot' );
$parser->setFunctionHook( 'annotend', 'YATA::renderEndAnnot' );
$parser->setFunctionHook( 'annotlist', 'YATA::annotations_list' );
$parser->setFunctionHook( 'annotask', 'YATA::annotation_query' );
$parser->setFunctionHook( 'annotcat', 'YATA::annotation_categories' );
$parser->setFunctionHook( 'annotpage', 'YATA::annotation_page' );
$parser->setFunctionHook('annot', 'YATA::renderStartAnnot');
$parser->setFunctionHook('annotend', 'YATA::renderEndAnnot');
$parser->setFunctionHook('annotlist', 'YATA::annotations_list');
$parser->setFunctionHook('annotask', 'YATA::annotation_query');
$parser->setFunctionHook('annotcat', 'YATA::annotation_categories');
$parser->setFunctionHook('annotpage', 'YATA::annotation_page');
}
//
// Render the output of {{#annot: comment | category | id}}.
//
public static function renderStartAnnot( $parser, $comment='', $category='', $id='' ) {
return "<span id=$id title='$comment'>";
if ($comment === 'list') {
return self::annotations_list($parser);
}
else {
return "<span id=$id title='$comment'>";
}
}
//
......@@ -98,6 +103,17 @@ class YATA {
elseif( $field === 'user' ) {
$where["u.username"] = $values;
}
elseif( $field === 'page' ) {
$keyvalues=array();
self::extract_keyvalues($values, $keyvalues);
$where[] =
"EXISTS(
SELECT NULL
FROM yata_page_annotation pa
";
// WHERE pa.page_id = ".$wikiPage->getId()
}
elseif( in_array($field, array('wiki_text', 'comment')) ) {
array_push($searches, $field . ': ' . $values);
if ( preg_match( '/[\%_]/', $values ) ) {
......@@ -353,6 +369,7 @@ EOT;
}
$title = $parser->getTitle();
$wikiPage = new WikiPage( $title );
$wikiPage->doPurge();
$dbr = wfGetDB( DB_MASTER );
$annotations = self::get_page_annotations($dbr, $wikiPage );
......@@ -370,7 +387,7 @@ EOT;
$table .= "|-\n";
$table .= "| ".$annotation->name
." || ".$annotation->value
." || ".$annotation->insert_date
." || ".wfTimestamp( TS_ISO_8601, $annotation->insert_date)
." || ".$annotation->user_name
."\n";
}
......@@ -589,8 +606,34 @@ EOT;
);
}
foreach (self::$page_annotations as $page_annotation){
$ex_page_annotations = self::get_page_annotations($dbw, $wikiPage);
$ex_annotations = array();
if ($ex_page_annotations) {
foreach ($ex_page_annotations as $ex_page_annotation) {
$ex_annotations[$ex_page_annotation->name] = $ex_page_annotation->value;
}
}
foreach( self::$page_annotations as $key => $value) {
if (array_key_exists($key, $ex_annotations)){
if ($ex_annotations[$key] != $value) {
self::update_page_annotation($dbw, $wikiPage, $key, $value);
}
else {
# value has not changed - do nothing
}
unset($ex_annotations[$key]);
}
else {
self::insert_page_annotation($dbw, $wikiPage, $user, $key, $value);
}
}
# remove the keys and values that are no longer in use.
foreach( $ex_annotations as $key => $value) {
self::delete_page_annotation($dbw, $wikiPage, $key, $value);
}
}
public static function add_category($dbw, $category_name, $hashtag, $description, $parent) {
......@@ -792,6 +835,9 @@ EOT;
public static function get_page_annotations($dbr, $wikiPage) {
$order_by = array('ORDER BY' => 'name');
$where = array(
'pa.page_id' => $wikiPage->getId()
);
$annotations = $dbr->select(
array('pa' => 'yata_page_annotation',
......@@ -804,9 +850,7 @@ EOT;
'pa.insert_date',
'u.user_name'
),
array(
'pa.page_id' => $wikiPage->getId()
),
$where,
__METHOD__,
$order_by,
array(
......@@ -816,6 +860,44 @@ EOT;
return $annotations;
}
public static function update_page_annotation($dbw, $wikiPage, $key, $value) {
$dbw->update(
'yata_page_annotation',
array(
"value" => $value,
"modified_date" => $dbw->timestamp(),
),
array(
"page_id" => $wikiPage->getId(),
"name" => $key
)
);
}
public static function insert_page_annotation($dbw, $wikiPage, $user, $key, $value) {
$dbw->insert(
'yata_page_annotation',
array(
"page_id" => $wikiPage->getId(),
"name" => $key,
"value" => $value,
"user_id" => $user->getId(),
"insert_date" => $dbw->timestamp(),
"modified_date" => $dbw->timestamp(),
)
);
}
public static function delete_page_annotation($dbw, $wikiPage, $key, $value) {
$dbw->delete(
'yata_page_annotation',
array(
"page_id" => $wikiPage->getId(),
"name" => $key,
"value" => $value,
)
);
}
public static function search_categories($dbr, $where, $order_by) {
if (! $order_by) {
......@@ -1011,6 +1093,26 @@ EOT;
return $id;
}
public static function extract_keyvalues($string, &$keyvalues=array()) {
// Match key-value pairs in a given string.
// Will match key and values that are:
// within single quotes ' \'.*?(?<!\\\\)\'
// within double quotes " \".*?(?<!\\\\)\"
// with no quotes at all (and no spaces): [^\s]+
$re =
'/(?P<key>\'.*?(?<!\\\\)\'|\".*?(?<!\\\\)\"|[^\s]+)'
.'\s*?=\s*?'
.'(?P<val>\'.*?(?<!\\\\)\'|\".*?(?<!\\\\)\"|[^\s]+)/';
preg_match_all($re, $string, $matches, PREG_SET_ORDER, 0);
foreach($matches as $match) {
# trim keys and values: remove any spaces and quotes
$key = trim($match["key"], " '\"");
$val = trim($match["val"], " '\"");
$keyvalues[$key] = $val;
}
}
# Main function to parse all annotations,
# insert a random id (where it doesn't exist)
public static function parse_annotations($dbw, &$data, $wikiPage){
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment