Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
#793 2017-04-13 16:37:20
Re: tru_tags: A tagging plugin for textpattern
Thanks for keeping this really important plugin working!
Offline
#794 2017-07-18 13:22:42
Re: tru_tags: A tagging plugin for textpattern
I found out that tru_tags works rather slowly. Debug shows that:
* 42,02 | 28,56 | <txp:tru_tags_list showcounts="1" countwrapchars="()" />
42,09 | 0,10 | [SQL: SELECT name FROM ztxp_section as txp_section WHERE searchable != '1' ]
42,19 | | [Rows: 11]
42,26 | 10,46 | [SQL: SELECT Keywords FROM zl10n_txp_uk_ua as l10n_txp_uk_ua WHERE Keywords <> ''and Section != ''AND Section != 'tag' AND Section != 'archive' AND Section != 'search' AND Section != 'sitemap' AND Section != 'rss-feed' AND Section != 'contact' AND Section != 'copyright' AND Section != 'sources' AND Section != 'searchy' AND Section != 'help' AND Section != 'archives' and Status >= '4' and Posted <= now() and (now() <= Expires or Expires IS NULL) ]
52,74 | | [Rows: 275]
56,47 | 0,15 | [SQL: SELECT name FROM ztxp_section as txp_section WHERE searchable != '1' ]
56,63 | | [Rows: 11]
56,73 | 10,20 | [SQL: SELECT Keywords FROM zl10n_txp_uk_ua as l10n_txp_uk_ua WHERE Keywords <> ''and Section != ''AND Section != 'tag' AND Section != 'archive' AND Section != 'search' AND Section != 'sitemap' AND Section != 'rss-feed' AND Section != 'contact' AND Section != 'copyright' AND Section != 'sources' AND Section != 'searchy' AND Section != 'help' AND Section != 'archives' and Status >= '4' and Posted <= now() and (now() <= Expires or Expires IS NULL) ]
66,95 | | [Rows: 275]
You can see that the same queries are executed twice. And one of them is a heavy, noncached query.
The reason is that the function tru_tags_cloud_query()
is called twice. I don’t know if it’s intended or it’s a mistake… But for myself I wrote a hack that fixes duplication of a heavy query.
Before:
<!-- Trace summary:
Runtime : 80,45 ms
Query time: 39,53 ms
Queries : 32
Memory (*): 2254 kB
-->
* 42,02 | 28,56 | <txp:tru_tags_list showcounts="1" countwrapchars="()" />
42,09 | 0,10 | [SQL: SELECT name FROM ztxp_section as txp_section WHERE searchable != '1' ]
42,19 | | [Rows: 11]
42,26 | 10,46 | [SQL: SELECT Keywords FROM zl10n_txp_uk_ua as l10n_txp_uk_ua WHERE Keywords <> ''and Section != ''AND Section != 'tag' AND Section != 'archive' AND Section != 'search' AND Section != 'sitemap' AND Section != 'rss-feed' AND Section != 'contact' AND Section != 'copyright' AND Section != 'sources' AND Section != 'searchy' AND Section != 'help' AND Section != 'archives' and Status >= '4' and Posted <= now() and (now() <= Expires or Expires IS NULL) ]
52,74 | | [Rows: 275]
56,47 | 0,15 | [SQL: SELECT name FROM ztxp_section as txp_section WHERE searchable != '1' ]
56,63 | | [Rows: 11]
56,73 | 10,20 | [SQL: SELECT Keywords FROM zl10n_txp_uk_ua as l10n_txp_uk_ua WHERE Keywords <> ''and Section != ''AND Section != 'tag' AND Section != 'archive' AND Section != 'search' AND Section != 'sitemap' AND Section != 'rss-feed' AND Section != 'contact' AND Section != 'copyright' AND Section != 'sources' AND Section != 'searchy' AND Section != 'help' AND Section != 'archives' and Status >= '4' and Posted <= now() and (now() <= Expires or Expires IS NULL) ]
66,95 | | [Rows: 275]
After:
<!-- Trace summary:
Runtime : 69,91 ms
Query time: 28,87 ms
Queries : 31
Memory (*): 2322 kB
-->
36,10 | 18,57 | <txp:tru_tags_list showcounts="1" countwrapchars="()" />
36,18 | 0,12 | [SQL: SELECT name FROM ztxp_section as txp_section WHERE searchable != '1' ]
36,30 | | [Rows: 11]
36,37 | 11,05 | [SQL: SELECT Keywords FROM zl10n_txp_uk_ua as l10n_txp_uk_ua WHERE Keywords <> ''and Section != ''AND Section != 'tag' AND Section != 'archive' AND Section != 'search' AND Section != 'sitemap' AND Section != 'rss-feed' AND Section != 'contact' AND Section != 'copyright' AND Section != 'sources' AND Section != 'searchy' AND Section != 'help' AND Section != 'archives' and Status >= '4' and Posted <= now() and (now() <= Expires or Expires IS NULL) ]
47,43 | | [Rows: 275]
51,07 | 0,14 | [SQL: SELECT name FROM ztxp_section as txp_section WHERE searchable != '1' ]
51,21 | | [Rows: 11]
Last edited by spiridon (2017-07-20 10:30:50)
Offline
#795 2017-07-18 16:32:04
Re: tru_tags: A tagging plugin for textpattern
Thank you for this!
tru_tags_cloud_query
is called from a bunch of places; it’s how tru_tags figures out what tags exist. Depending on what you’re showing on a page, it could easily be called many times. It might also be the case that there’s a call tree where it’s being called redundantly; I’d have to know more about your site and the particular page you are testing, to guess.
But still, caching the query result does seem like a good idea, given how that function is used, and that it makes a heavy database call. But I am generally super-paranoid about any sort of caching; it usually leads to subtle bugs. (Like do we know if the $rs
is just a list, or does it contain other state that might not be safe to cache? I don’t remember my php and textpattern well enough to be sure.)
Looking at your before and after, it looks like you only saved about 10ms (~13%) on the runtime – is that worth it? But of course, you saved about 25% on the query time, and if that query is used many times in a page, it might have a much bigger effect. Do you have any experimental results that would show that?
So on the whole, I think this is probably a good thing you’ve done. I looked over your code changes and I like them, except I think you should reuse $query_key
on line 358. If you’d make that change and submit a PR, I’d happily merge it and publish a new version.
Thanks again!
Offline
#796 2017-07-20 10:30:19
Re: tru_tags: A tagging plugin for textpattern
truist wrote #306330:
tru_tags_cloud_query
is called from a bunch of places; it’s how tru_tags figures out what tags exist.
I found that I had a call stack like this:
tru_tags_cloud() {
tru_tags_list() {
tru_tags_cloud_query()
tru_tags_render_cloud() {
tru_tags_tag_parameter() {
tru_tags_cloud_query()
}
}
}
}
But still, caching the query result does seem like a good idea, given how that function is used, and that it makes a heavy database call. But I am generally super-paranoid about any sort of caching; it usually leads to subtle bugs. (Like do we know if the
$rs
is just a list, or does it contain other state that might not be safe to cache? I don’t remember my php and textpattern well enough to be sure.)
This is not dangerous. The function safe_row
always returns array (empty array in case of error).
Looking at your before and after, it looks like you only saved about 10ms (~13%) on the runtime – is that worth it? But of course, you saved about 25% on the query time, and if that query is used many times in a page, it might have a much bigger effect. Do you have any experimental results that would show that?
You can ignore it, but I can not.
I do not have any experimental results, except those that published earlier. I just found the inefficiency in the code.
If you’d make that change and submit a PR, I’d happily merge it and publish a new version.
Done.
Offline
#797 2017-07-20 12:11:31
Re: tru_tags: A tagging plugin for textpattern
spiridon wrote #306323:
But for myself I wrote a hack that fixes duplication of a heavy query.
Note that in Txp 4.6+ you can significantly speed up queries with txp/php function now() This approach makes it possible to use mysql query_cache
and in this case there is no need for additional caching.
Example usage (copy-paste from the plugin aks_article)
// Using SQL caching capabilities. Txp 4.6+ if (function_exists('now')) { $where_posted = now('posted'); $where_expired = " AND (".now('expires')." <= Expires OR Expires IS NULL)"; } else { $where_posted = "now()"; $where_expired = " AND (now() <= Expires OR Expires = ".NULLDATETIME.")"; } switch ($time) { case 'any': $time = ""; break; case 'all': $time = ""; $expired = 1; break; case 'future': $time = " AND Posted > ".$where_posted; break; default: $time = " AND Posted <= ".$where_posted; } if (!$expired) { $time .= $where_expired; }
Can adapt and add to the functions tru_tags_cloud_query
and tru_tags_redo_article_search
Last edited by makss (2017-07-20 12:26:06)
aks_cron : Cron inside Textpattern | aks_article : extended article_custom tag
aks_cache : cache for TxP | aks_dragdrop : Drag&Drop categories (article, link, image, file)
Offline
#798 2017-07-20 13:23:19
Re: tru_tags: A tagging plugin for textpattern
Please check my patch
Unfortunately, I can not check it on a real site.
aks_cron : Cron inside Textpattern | aks_article : extended article_custom tag
aks_cache : cache for TxP | aks_dragdrop : Drag&Drop categories (article, link, image, file)
Offline
#799 2017-07-20 14:48:28
Re: tru_tags: A tagging plugin for textpattern
michaelkpate wrote #305227:
I am trying to get tru_tags 3.9 working on a site running 4.7 dev. I am constantly getting this error in the backend.
A problem occurred while loading the plugin: tru_tags -> User_Error: Table '[databasename].tru_tags_prefs' doesn't exist on line 409...
Perhaps fixed , please check.
aks_cron : Cron inside Textpattern | aks_article : extended article_custom tag
aks_cache : cache for TxP | aks_dragdrop : Drag&Drop categories (article, link, image, file)
Offline
#800 2017-07-20 17:21:18
Re: tru_tags: A tagging plugin for textpattern
makss wrote #306361:
Note that in Txp 4.6+ you can significantly speed up queries with txp/php function now() This approach makes it possible to use mysql
query_cache
and in this case there is no need for additional caching.
This will lead to malfunction of the plugin. And besides it fills caches with useless queries.
Offline
#801 2017-07-23 09:39:45
Re: tru_tags: A tagging plugin for textpattern
With textpattern 4.6.2 and tru_tags 3.9 the for me very important auto complete function stopped working. Stylesheet and script are now placed right before the <!DOCTYPE html>
The javascript file doesn’t seems to be still necessary, because the autocomplete function is now part of jquery-ui
which is also loaded by the admin-side theme.
How to get the code back into the html body or the head? There is this “head_end” callback, but I don’t know how to change the code for using it right, due to my limited programming skills.
Offline
#802 2017-07-23 21:30:43
Re: tru_tags: A tagging plugin for textpattern
A quick and dirty solution, which is working for me and with the help of this auto complete example from here:
function tru_tags_admin_write_tab_handler($event, $step, $data) {
global $tru_tags_prefs;
$atts = tru_tags_get_standard_cloud_atts(array(), true, true, true);
$cloud = array_unique(tru_tags_cloud_query($atts));
natcasesort($cloud);
$id = (empty($GLOBALS['ID']) ? gps('ID') : $GLOBALS['ID']);
$article_tags = (empty($id) ? array() : tru_tags_get_tags_for_article($id));
$links = array();
global $raw_cloud;
$raw_cloud = '';
foreach ($cloud as $tag) {
$style = (in_array($tag, $article_tags) ? ' class="tag_chosen"' : '');
$links[] = '<a href="#advanced"'.$style.' onclick="toggleClass(this, toggleTag(\\\''.addslashes(addslashes(htmlspecialchars($tag))).'\\\')); return false;">' . addslashes(htmlspecialchars($tag)) . '<\/a>';
$raw_cloud .= '"' . addSlashes($tag) . '",';
}
$raw_cloud = substr($raw_cloud, 0, strlen($raw_cloud) - 1);
$to_insert = join(', ', $links);
if ($tru_tags_prefs[TAGS_IN_WRITE_TAB]->value) {
$js = <<<EOF
var keywordsField = document.getElementById('keywords');
keywordsField.parentNode.appendChild(document.createElement('br'));
var cloud = document.createElement('span');
keywordsField.parentNode.appendChild(cloud);
cloud.setAttribute('class', 'tru_tags_admin_tags');
cloud.innerHTML = '{$to_insert}';
var styleElement = document.createElement('style');
styleElement.setAttribute("type", "text/css");
var styleText = 'a.tag_chosen{background-color: #FEB; color: black;}';
if (styleElement.styleSheet) { //IE
styleElement.styleSheet.cssText = styleText;
} else {
var textNode = document.createTextNode(styleText);
styleElement.appendChild(textNode);
}
var headElement = document.getElementsByTagName('head')[0];
headElement.appendChild(styleElement);
function toggleTag(tagName) {
var regexTag = tagName.replace(/([\\\\\^\\$*+[\\]?{}.=!:(|)])/g,"\\\\$1");
var tagRegex = new RegExp("((^|,)\\\s*)" + regexTag + "\\\s*(,\\\s*|$)");
var textarea = document.getElementById('keywords');
var curval = textarea.value.replace(/,?\s+$/, '');
if ('' == curval) {
textarea.value = tagName;
} else if (curval.match(tagRegex)) {
textarea.value = curval.replace(tagRegex, '$1').replace(/,?\s+$/, '');
return '';
} else if (',' == curval.charAt(curval.length - 1)) {
textarea.value += ' ' + tagName;
} else {
textarea.value += ', ' + tagName;
}
return 'tag_chosen';
}
function toggleClass(element, className) {
element.setAttribute('class', className);
element.setAttribute('className', className); /* for IE */
}
EOF;
return $data . script_js($js);
}
if ($tru_tags_prefs[AUTOCOMPLETE_IN_WRITE_TAB]->value) {
register_callback('tru_tags_admin_write_tab_bodyend', 'admin_side', 'body_end');
function tru_tags_admin_write_tab_bodyend ($event, $step) {
global $raw_cloud;
$output='<link rel="stylesheet" type="text/css" href="../js/jquery.autocomplete.css" media="projection, screen" />
<script language="JavaScript" type="text/javascript"><!--
$(document).ready(function(){
var availableTags = ['.$raw_cloud.'];
function split( val ) { return val.split( /,\s*/ ); }
function extractLast( term ) { return split( term ).pop(); }
$("#keywords").autocomplete({ minLength: 0,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
availableTags, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
return false;
}});
});
//--></script>';
echo n.$output.n;
}
}
}
Last edited by whocarez (2017-07-23 21:44:29)
Offline
#803 2018-05-01 19:51:51
- moon blake
- Member
- From: near Hannover, Germany
- Registered: 2009-07-16
- Posts: 76
Re: tru_tags: A tagging plugin for textpattern
michaelkpate wrote #305227:
As someone who has been using tru_tags on their personal site for nearly a decade, good to have you back.
I am trying to get tru_tags 3.9 working on a site running 4.7 dev. I am constantly getting this error in the backend.
A problem occurred while loading the plugin: tru_tags -> User_Error: Table '[databasename].tru_tags_prefs' doesn't exist on line 409...
While michaelkpate reports an issue with true_tags under 4.7 I get the said error under 4.6.2
Any idea how to solve this?
Looking it up in phpMyAdmin I am also wondering if it is correct that there seems to be no table added to the database by the true_tags plugin.
Thanks for any hint.
Offline
#804 2018-05-01 20:11:48
- uli
- Moderator
- From: Cologne
- Registered: 2006-08-15
- Posts: 4,306
Re: tru_tags: A tagging plugin for textpattern
In bad weather I never leave home without wet_plugout, smd_where_used and adi_form_links
Offline