Inline query for listing all pages from a namespace without any subobjects - mediawiki

I need an inline query that lists all pages from a specific namespace, but without listing subobjects specified on these pages.
Restricting results to a namespace is possible like that:
{{#ask: [[ExampleNamespace:+]] }}
But it lists all subobjects, too.
Workarounds:
Specify a category on these pages (subobjects don’t inherit it) and query for the category instead:
{{#ask: [[ExampleCategory]] }}
Specify a property on these pages (and never on the subobjects) and query for the property (with a wildcard value) instead:
{{#ask: [[ExampleProperty::+]] }}
But both workarounds require editing, which I would like to avoid. Is there a better way to solve this?

Not sure if it's a better way, but it looks like array formats/arrays and their #arraymap and #arrayunique functions are a way to go in order to trim SMW subobject tags and make the DISTINCT operation. Unfortunately, the solution below has a query result limit issue described as well (at least out of what I understand in SMW). In general, it may look like the following, and I will appreciate if someone suggests a nicer solution:
<!-- Fetch all pages from the "Live event" namespace -->
{{#arraydefine: QUERY_RESULT
| {{#ask: [[Live event:+]]
| format = array
| link = none <!-- NOTE: array item link -->
| limit = 10000 <!-- NOTE: limit -->
}}
}}
<!-- Store the mapped result into another array -->
{{#arraydefine: MAPPED_QUERY_RESULT
| {{#arraymap: {{#arrayprint: QUERY_RESULT}}
| ,
| $O <!-- NOTE: array map iterator value -->
| {{#explode: $O <!-- NOTE: explode by hash -->
| #
| 0
}}
}}
| ,
| unique
}}
<!-- Generate links markup -->
{{#arraymap: {{#arrayprint: MAPPED_QUERY_RESULT}}
| ,
| $O
| [[$O]] <!-- NOTE: plain links -->
}}
The notes from the code above:
NOTE: array item link - Not suppressing the links causes the mapper to be more complicated (including parsing HTML <span> tags and class attributes).
NOTE: limit - This is probably the biggest issue here as the number of subobjects affects the query result. SMW by default limits the query results, and the maximum query limit cannot be overridden as far as I know. Having more rows, which count is greater than the limits is, will cause the 'Further limits' link to appear. Actually speaking, I have no idea how to work around it nicely.
NOTE: array map iterator value - {{#arraymap}} seems to replace strings in the simplest way like sed or a simple text editor app do. So $O is used as the iterator value placeholder for the formula parameter trying not to clash with other string tokens.
NOTE: explode by hash - #ask subobject results generate hashed links like PageA#_159c1f213de2fcaf165f2c9c5c56686b. Just getting rid of them. In case you need to strip wiki links, you might also play around with [[ or | (encoded like [<nowiki/>[ and <nowiki>|</nowiki> respectively)
NOTE: plain links - The generated links will have underscores instead of spaces. Unfortunately, [[{{#replace: $O | _ | <nowiki> </nowiki>}}]] didn't work for me -- the underscores are simply consumed for some reason, however this approach is also recommended at the #replace function wiki page.
Some links:
SMW array result format
SMW configuration
SMW further results
#arraymap:
#explode:
#replace:
Help:List the set of unique values for a property (pay attention at the "Limitations and issues" section)

Related

Meta tags in skin from MediaWiki template

Let's say i have a template in my MediaWiki like
<includeonly>
<div id="custom-person">
* <span>Birthday:</span> {{#if: {{{birth date|}}} | <b>{{#ol-time:|{{{birth date}}}}}</b> | — }}
{{#if: {{{full name|}}} | * <span>full name:</span> <b>{{{full name}}}</b>}}
{{#if: {{{birth place|}}} | * <span>birth place:</span> <b>{{{birth place}}}</b>}}
{{#if: {{{age|}}} | * <span> age:</span> <b>{{{age}}}</b>}}
{{#if: {{{nationality|}}} | * <span> nationality:</span> <b>{{{nationality}}}</b>}}
<div class="clear"></div>
</div>
[[Category:Person]]
__NOTOC__
</includeonly>
All these pages are in one Namespace (0).
I need to generate head meta tags with data from this template.
I figured out how to filter such a pages and add title tags in my SkinPerson.php
if ( $out->getTitle()->getNamespace() == 0 ) {
$out->addMeta( "description", $out->getPageTitle());
$out->addHeadItem( 'og:description', '<meta property="og:description" content="' . $out->getPageTitle() . '">');
}
But I'm really stuck on how can I insert in, say, 'og:description' tag something like {{{full name}}} + {{{age}}} ?
That's simply not possible, and I would wonder what your use case here would be, why you want to do that. First some explanation, why this is not possible in the way you want to achieve that:
The template is evaluated by a piece of software we call the Parser. The parser is generating a html representation of your wikitext, including all the templates and so on. The result of that is then saved in the ParserOutput and probably cached in ParserCache (so that not every time it needs to be parsed again).
However, the skin, where you want to add the head item, is using the output of the parser directly, so it does not really know about the wikitext (including template parameters) anymore, and really shouldn't.
One possible solution for what you want to achieve is probably to extend the wikitext markup language by providing a tag extension, parsing that during the parsing of the wikitext, and save the values for the head items in the database. During the output of the page you can then retrieve these values from the database again and add them into the head items like you want. See more information about that in the documentation.
There might be other ways, apart from the database, to get information from the parsing time into the output time, which I'm not aware of.

Formatting query result of Url as given string in Semantic MediaWiki

I want to embed the result of an ask query on a page in Semantic MediaWiki. The result column has the type Url as in [[Has type:Url]]. However, when embedding the code I would like to show the URL not explicitly since it is very long but as a fixed string (e.g. "Website" )as I would have typed:
[https://someURL.com Website]
I tried to set the name on the page in the property assignment itself by including:
[[Has website::https://someURL.com | Website]]
This is the basic structure of an example query.
{{#ask: [[Has website_example::true]]
|?Has website
|format=table
|limit=50 |offset=0
|link=all
|sort=
|order=asc
|headers=show
|searchlabel=... further results
|class=sortable wikitable smwtable
}}
Is it possible to render the ?Has website as a link with the text "Website" in the table?
You may be have to pass through a 'template' format, and reconstruct your rows based on this template.
Example :
|-
! [{{{1}}} | Website]
then just surround your 'ask' request by table headers and footers.

REGEX in mysql table containing html data

I have a table that stores html templates in a mysql database. Now I have to perform some text replacement on them. However my target text is also present in some of the anchor tags and I don't want that to be replaced.
EX :
<body> ... (has huge html crap)... .........(Some more html crap) ... (a bit more of html crap) ... </body>
Task is to replace the occurrences of the "KEYWORD" with "NEW KEYWORD" in the body but not the urls.
It would also be helpful if I can first find such cases where the KEYWORD is a part of a link in a given template.
MySQL is not capable of such advanced string manipulation.
However, if you were to have a one-time-use PHP script do the editing (ie. select from the table, for each row process and update), you can do this:
// foreach row as $row
$newtext = preg_replace("(<a\b.*?>(*SKIP)(*FAIL)|KEYWORD)","NEW KEYWORD",$row['data']);
What this does is look for links (very approximate Regex but should suffice in almost all cases here), then skip over them. Then, it looks for KEYWORD and replaces it with NEW KEYWORD.
You can use this to quickly and easily handle the replacement.
If that "almost all cases" thing above turns out to not be enough, you can use DOMDocument to load the HTML into a parser and process text nodes only from there.
Maybe you could find the cases where the KEYWORD is a part of a link with something like this:
SELECT * FROM tbl WHERE html REGEXP '<a[^>]*KEYWORD';

Replace Placeholder HTML comment with HTML element

I'm developing an iOS app that needs to display HTML content inside a HTML powered textview (DTCoreText).
For whatever reaso nthe client has decided to provide videos inside special HTML comments that I'm supposed to turn into a tag.
The comment format is as such
<!-- placeholder_video:url_of_video.mp4 -->
I was hoping I could write a regex to match the entire comment, extract the content and replace it with a element pointing to the correct URL through NSRegularExpression's stringByReplacingMatchesInString:options:range:withTemplate: but I can't for the life of me figure out Regular Expressions.
The best I could come up with is
(?<=<!-- placeholder_video:)(.*)(?=-->)
Which matches the comment's content (the mp4 URL), but I need it to match the entire comment instead and extract the content as a sub pattern (that I would later access through \1 if I understand correctly) so I can use a replace pattern to quickly replace the comment with the proper <video src="url_of_video.mp4"> string
Can it be done? Or am I better off trying to do it in two passes instead? (match the entire comment then run another regex on that comment to extract the URL and replace the former?
Based on the way your question looks right now (Having forgotten to paste the example of how the comment looks) it's hard to give a good answer.
But since you mention that this:
(?<=<!-- placeholder_video:)(.*)(?=-->)
will manage to fetch the content of the comment. And since you say all you want is to capture the entire comment.
Then if I understand this correctly I would say all you really need to do is add a capturing group around your entire expression and drop the lookback and lookahead.
(Maybe also avoid grabbing the leading and trailing spaces)
(<!-- placeholder_video:\s*(.*)\s*-->)
When testing with the following:
<!-- placeholder_video: url_of_video.mp4 -->
I will get 2 groups:
1: <!-- placeholder_video: url_of_video.mp4 -->
2: url_of_video.mp4
You can also give your groups names if you like, to make it easier to reference them:
(?<comment><!-- placeholder_video:\s*(?<url>.*)\s*-->)
It is also true that you can use \n to reference group n inside the regular expression.
If you plan to replace the first capturing group with the second one in a single regex, then how you do it would depend on the language. Some languages like C# will allow you to provide your own replacing method, which is one option. But I'm assuming you're not in C# here.
In Javascript you can simply use $n to reference the n'th matched group as the replaced value. (You can also provide a function, but you don't need to)
A full working example in JS (Using jQuery but not needed):
<div id="example">
<!-- placeholder_video: url_of_video.mp4 -->
</div>
<script>
var str = $("#example").html();
var str2 = str.replace(/(<!-- placeholder_video:\s*(.*)\s*-->)/g, "<video src=\"$2\">");
alert(str2);
</script>
You can see the working jsfiddle example here: http://jsfiddle.net/72WeZ/

use ask as a parameter in semantic media wiki

How can I pass an ask as a parameter of a query?
For example:
myvar={#ask: [[Category:City]][[London]]
|?population
|?currency
|}
Then use the data again in a custom function:
{#ask: [[England]]
|?population
|?currency
|capital=myvar
|}
If I try using something like the code below, when I debug the application, capital is equal to an empty String ( it's declared but empty ):
{#ask: [[England]]
|?population
|?currency
|capital={#ask: [[Category:City]][[London]]
|?population
|?currency
|}
|}
Your syntax is not correct.
It should be like this:
{{#ask: [[Category:City]] [[located in::England]]
| ?population
| ?currency
}}
You can have more informations about inline queries at the Semantic MediaWiki website.
And you can see how build nested queries at this question: Semantic mediawiki #ask query: Displaying nested properties on the same query
Hope that help you. Thanks!