Wordpress

Portofoliu wordpress

I am sharing here my experience of building an announcement system based on Formidable Pro (currently at version 2.14).

The notification system is created for membership websites where admins can send personalized notifications to single or multiple users.

Components:
1. The form is a simple form with a textarea and 2 checkboxes. Leave the checkboxes empty but check the “Use separate values” checkbox in their properties
Capture1

2. The admin view and page will allow admins to create, edit and delete notifications
Capture2

3. The public view will allow recipients to read and “mark as read” the notifications
Capture3

4. The custom code that is explained below:

Populate user fields (Recipients and Read by in my case or field_id 124 and 212)

//for fields with separate values update field definition so it can render correctly in views
function update_bulk_options_db($list,$ids) {
	global $wpdb;
	$id = implode(",",$ids);
	$options = array();
	$j=0;
	foreach ($list as $key=>$val) {
		$j=$j+1;
		$options[$j]=array('value'=>(string)$key,'label'=>$val);
	}
	$save= serialize($options);
	$wpdb->query(
			"UPDATE wp_frm_fields
			 SET options = '$save'
			 WHERE id in ($id)
			" 
	);
	return;
}
//populate user related fields with users. here I use s2member plugin for role management
add_filter('frm_setup_new_fields_vars', 'paperplus_populate_users', 20, 2);
add_filter('frm_setup_edit_fields_vars', 'paperplus_populate_users', 20, 2); //use this function on edit too
function paperplus_populate_users($values, $field){
	if($field->id == 124||$field->id == 212){
		$users1q = new WP_User_Query(array( 'role' => 'subscriber' ));
		$operators = $users1q->results;
		$users2q = new WP_User_Query(array( 'role' => 's2member_level1' ));	
		$managers = $users2q->results;
		$users3q = new WP_User_Query(array( 'role' => 'administrator' ));	
		$admins = $users3q->get_results();
		$users = array_unique(array_merge($operators, $managers, $admins));	
		unset($values['options']);
		$values['options'] = array();
		foreach($users as $u){
		       $values['options'][$u->ID] = $u->display_name;
		}
		update_bulk_options_db ($values['options'], array(124,212));
		$values['use_key'] = true; 
	}
	return $values;
}

After adding this snippet to your functions.php file in your active theme you will get prepopulated checkboxes with current users registered for the subscriber, s2member_level1 and administrator roles. Of course you will use any number of roles you like or all existing users, just format properly the WP_User_Query

Filter the notifications view so that only notifications sent to current user will be displayed

Of course, a notification can be sent to several users at once. We need to filter entries that have current user id in the recipients list

//filter the notifications view if the user is in the list.
add_filter('frm_where_filter', 'filter_anunturi', 10, 2);
function filter_anunturi($where, $args){
	if ( $args['display']->ID == 82){ //change 82 with your view id 
		$user_id = get_current_user_id();
		if ($user_id > 0) {
			$where = "(FIND_IN_SET('" . $user_id . "', fn_parse_ser_array(meta_value))>0 and fi.id='124')";
		}
	}
	return $where;
}

You notice the mysql function call fn_parse_ser_array that is a custom made function. You need phpmyadmin access and rights to create functions on your database. This function is the mysql version of the PHP function unserialize.

You may try this mysql command:

BEGIN
declare cnt int;
declare i int;
declare retstr varchar(2000); 
declare mystr varchar(2000);
-- declare str varchar(2000);
if instr(str,"{")>0 then
    set str = right(str, length(str)-instr(str,"{"));
    set str = replace(str,"}","");
    -- set retstr = str;
    
    set cnt = subStringCount2(str,";");
    
    -- select @str;
    
    set i = 1;
    set retstr = '';
    WHILE i< =cnt 
    DO
    
    if mod(i,2)=0  then
         set mystr = SPLIT_STR2(str,";",i);
         set mystr = replace(mystr, '"','');
         set mystr = SUBSTRING_INDEX(mystr, ':',-1);
         if length(retstr)>0 then 
            set retstr = concat(retstr, ',', mystr);
        else
            set retstr = mystr;
        end if;
    end if;
      set i = i +1;
    END while;
else
	set retstr = str;
end if;
return retstr;

END

Also, we would want to hide the notifications that recipients have already marked as read. First idea is to use a negate condition on field 212 but… it does not work. In fact

$where = "(FIND_IN_SET('" . $user_id . "', fn_parse_ser_array(meta_value))=0 and fi.id='212')";

would work on its own but this will never work:

$where = "(FIND_IN_SET('" . $user_id . "', fn_parse_ser_array(meta_value))>0 and fi.id='124') AND (FIND_IN_SET('" . $user_id . "', fn_parse_ser_array(meta_value))=0 and fi.id='212')";

Therefore my solution was to hide the read notifications in the table itself by using DataTables jQuery plugin

Mark as read system for notifications

This system will both hide notifications for users that read them and will show admins who actually read their notifications

First add this snippet to functions.php file then add the [mark_as_read entry_id='[id]’] shortcode into the last column of the notifications table inside the view

//mark notifications as read by users
add_shortcode('mark_as_read','function_mark_as_read');
function function_mark_as_read($atts) {
	$entry = $atts["entry_id"];
	$val = FrmProEntriesController::get_field_value_shortcode(array('field_id' => 212, 'entry' => $entry, 'show' => 1));
	if ($val)
		$val = explode(",",str_replace(" ","",$val));
	else
		$val = array();
	if (in_array(get_current_user_id(),$val))
		return "Read";
	else
		array_push($val,get_current_user_id());
	//$val = array_unique($val);
	$new_val = "[" . implode(",",$val) . "]";
	//return FrmProEntriesController::entry_update_field(array('id' => $entry, 'field_id' => 212, 'label' => 'Mark as read', 'class' => '', 'value' => $new_val, 'message' => 'Succes!'));
	return 'Mark as read';
}

Note that the attempt to use Formidable API failed in this case because instead of this new value [1,2,3] it will always insert this new value ‘[1,2,3]’ messing the checkbox values in the database… (maybe this is a Formidable but at this moment). So I had to copy the behaviour and hardcode it in the last line.

In the datatables initialization we need to add the searchCols filtering as in the next example:

jQuery(document).ready(function() {jQuery('.ppl_table').DataTable({
"language": {
    "url": "//cdn.datatables.net/plug-ins/1.10.9/i18n/Romanian.json"
  },
  "searchCols": [
    null,
    null,
    { "search": "Mark" }
  ]
} );} );

Download

Below you can copy this exported definition of the form and views for your reference and save it as xml file, then import it into Formidable plugin. Please check the fields id that may change, also in the previous section I translated Mark and Read, in the original definitions they are in Romanian language

< ?xml version="1.0" encoding="UTF-8" ?>

	Paper Plus
	Sat, 03 Oct 2015 11:06:59 +0000

	
13 < ![CDATA[2yx0no]]> < ![CDATA[Anunturi personalizate]]> < ![CDATA[]]> 2015-08-05 08:42:57 0 0 0 1 < ![CDATA[{"submit_value":"Trimite","success_action":"redirect","success_msg":"Your responses were successfully submitted. Thank you!","show_form":0,"akismet":"","no_save":0,"ajax_load":0,"form_class":"","custom_style":"1","before_html":"[form_name]< \/legend>\r\n[if form_name]

[form_name]< \/h3>[\/if form_name]\r\n[if form_description]

< ![CDATA[published]]> 0 120 < ![CDATA[9iabnr]]> < ![CDATA[Mesaj nou]]> < ![CDATA[]]> < ![CDATA[textarea]]> < ![CDATA[]]> 0 13 < ![CDATA[]]> < ![CDATA[{"size":"","max":"5","label":"","blank":"This field cannot be blank.","required_indicator":"*","invalid":"","separate_value":0,"clear_on_focus":0,"default_blank":0,"classes":"frm_first frm_third","custom_html":"
\r\n 124 < ![CDATA[9dqxn5]]> < ![CDATA[Destinatari]]> < ![CDATA[]]> < ![CDATA[checkbox]]> < ![CDATA[]]> 1 13 < ![CDATA[{"1":{"value":"12","label":"anca1 Nume"},"2":{"value":"13","label":"QUADRANT TEST"},"3":{"value":"3","label":"Anca Badetoiu"},"4":{"value":"2","label":"Emanuel I"},"5":{"value":"1","label":"Richard Vencu"}}]]> < ![CDATA[{"size":"","max":"","label":"","blank":"This field cannot be blank.","required_indicator":"*","invalid":"","separate_value":"1","clear_on_focus":0,"default_blank":0,"classes":"frm_third","custom_html":"
\r\n 212 < ![CDATA[dlqcx6]]> < ![CDATA[Marcat ca citit de]]> < ![CDATA[]]> < ![CDATA[checkbox]]> < ![CDATA[]]> 2 13 < ![CDATA[{"1":{"value":"12","label":"anca1 Nume"},"2":{"value":"13","label":"QUADRANT TEST"},"3":{"value":"3","label":"Anca Badetoiu"},"4":{"value":"2","label":"Emanuel I"},"5":{"value":"1","label":"Richard Vencu"}}]]> < ![CDATA[{"size":"","max":"","label":"","blank":"This field cannot be blank.","required_indicator":"*","invalid":"","separate_value":"1","clear_on_focus":0,"default_blank":0,"classes":"frm_third","custom_html":"
\r\n 211 < ![CDATA[j52ux0]]> < ![CDATA[User ID]]> < ![CDATA[]]> < ![CDATA[user_id]]> < ![CDATA[]]> 3 13 < ![CDATA[]]> < ![CDATA[{"size":"","max":"","label":"","blank":"","required_indicator":"*","invalid":"","separate_value":0,"clear_on_focus":0,"default_blank":0,"classes":"","custom_html":"","custom_field":"","post_field":"","taxonomy":"category","exclude_cat":0,"slide":0,"form_select":"","show_hide":"show","any_all":"any","align":"block","hide_field":[],"hide_field_cond":["=="],"hide_opt":[],"star":0,"ftypes":[],"data_type":"select","restrict":0,"start_year":2000,"end_year":2020,"read_only":0,"admin_only":"","locale":"","attach":false,"minnum":0,"maxnum":9999,"step":1,"clock":12,"start_time":"00:00","end_time":"23:59","unique":0,"use_calc":0,"calc":"","calc_dec":"","dyn_default_value":"","multiple":0,"unique_msg":"","autocom":0,"format":"","repeat":0,"add_label":"Add","remove_label":"Remove","conf_field":"","conf_input":"","conf_desc":"","conf_msg":"The entered values do not match","other":0}]]> Anunturi Personalizate < ![CDATA[emi]]> < ![CDATA[[120][created-at][mark_as_read entry_id='[id]']]]> < ![CDATA[]]> 82 2015-08-06 20:51:18 2015-08-06 17:51:18 closed closed anunturi-personalizate publish 0 0 frm_display 0 _edit_lock < ![CDATA[1443870262:1]]> _edit_last 1 frm_param < ![CDATA[entry]]> frm_dyncontent < ![CDATA[]]> frm_insert_loc < ![CDATA[none]]> frm_type < ![CDATA[id]]> frm_show_count < ![CDATA[all]]> frm_form_id 13 frm_post_id < ![CDATA[]]> frm_options < ![CDATA[{"date_field_id":"created_at","edate_field_id":"","repeat_event_field_id":"","repeat_edate_field_id":"","before_content":"\r\n","no_rt":"1","after_content":"< \/tbody>< \/table> Anunturi Personalizate Admin < ![CDATA[emi]]> < ![CDATA[]]>< ![CDATA[]]>842015-08-06 21:27:422015-08-06 18:27:42closedclosedanunturi-personalizate-adminpublish00frm_display0 _edit_lock < ![CDATA[1443730443:1]]> _edit_last 1 frm_param < ![CDATA[entry]]> frm_dyncontent < ![CDATA[]]> frm_insert_loc < ![CDATA[none]]> frm_type < ![CDATA[id]]> frm_show_count < ![CDATA[all]]> frm_form_id 13 frm_post_id < ![CDATA[]]> frm_options < ![CDATA[{"date_field_id":"created_at","edate_field_id":"","repeat_event_field_id":"","repeat_edate_field_id":"","before_content":"
Mesajul< \/th>Data< \/th>Marcheaza ca citit< \/th>\r\n< \/tr>< \/thead>
[120][124][212][created-at format="Y-m-d H:i"][editlink location="front" label="Editeaza" page_id=78][deletelink label="Sterge" confirm="Esti sigur ca vrei sa stergi acest mesaj?..."]
\r\n","no_rt":"1","after_content":"< \/tbody>< \/table> Email Notification < ![CDATA[rvencu]]> < ![CDATA[{"email_to":"office@paperplus.ro","cc":"","bcc":"","reply_to":"","from":"[sitename] <[admin_email]>","email_subject":"Un nou anunt a fost publicat pe situl de comenzi","email_message":"[default-message]","inc_user_info":"1","event":["create"],"conditions":{"send_stop":"send","any_all":"any"}}]]> < ![CDATA[email]]> 77 2015-08-05 11:42:57 2015-08-05 08:42:57 closed closed 13_email_77 publish 0 13 frm_form_actions 0 _wp_old_slug < ![CDATA[13_email_]]>

So you have a VPS with cPanel/WHM (11.48) and want to run Varnish 4 reverse proxy to accelerate the server for your WordPress installations while monitoring Varnish 4 with Munin.

1. Install Varnish 4 – just follow these instructions https://www.varnish-cache.org/installation/redhat

2. Configure Varnish listening port to 80 by editing /etc/sysconfig/varnish file. In same file decide where to store the cache (on disk – default option, or on memory).

3. Configure vcl files by following these instructions: http://www.jaritimonen.com/make-wordpress-faster-with-varnish-cache/ Please note that you should use the backend server public IP and a chosen port such as 8080 in the <pre>backend default {}</pre> section. In default.vcl file just delete the websites filter (his wife’s websites) or modify them as necessary.

4. Tweak settings for Apache in WHM and set non-SSL port to 8080 (or another port you chosen at step 3)

5. Restart Apache and start varnish with

service varnish start

. If the varnish service does not start you need to debug your vcl files, most probably you introduced a typo. At this time you should be able to access all websites via varnish proxy. You can check it by accessing the WordPress websites and inspecting elements headers, you should be able to see Age and X-Varnish headers. Please do not login into backend of WordPress, the logged in users are not receiving cached files and Age header will always be 0.

6. Download varnish4_ plugin for Munin from here: https://github.com/munin-monitoring/contrib/tree/master/plugins/varnish4

7. Edit the plugin file and change first line with:

#!/usr/local/cpanel/3rdparty/perl/514/bin/perl

8. Upload the file to munin plugins folder at /usr/local/cpanel/3rdparty/share/munin/plugins and make it executable (change permissions to 755)

9. Create symlinks for all necessary aspects with these commands:

ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_request_rate
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_hit_rate
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_backend_traffic
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_objects
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_transfer_rates
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_threads
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_memory_usage
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_uptime
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_session
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_expunge
ln -s /usr/local/cpanel/3rdparty/share/munin/plugins/varnish4_ /etc/munin/plugins/varnish4_ban

10. Edit /etc/munin/plugin-conf.d/cpanel.conf file and add this section:

[varnish4_*]
user root
group wheel
env.varnishstat varnishstat

11. restart munin by

service munin-node restart

12. After few minutes varnish graphs will appear in WHM under Munin plugin.

Tags: , , ,

Here is a XML-RPC interface extension plugin for WordPress in order to specify the attachment author and parent post at the time of upload. It can be useful when remotely publishing posts with media galleries where the client uploads the post, receives the post_id of the newly created post then uploads a number of media files.

The plugin can be downloaded here : XMLRPC-Extended-Media-Upload or from WordPress plugins repository.

Next you may find a C# project for a Windows Form demo application that emulates a XML-RPC client which utilizes the extended API method.

You can download the C# demo solution here: VS-2010-SOLUTION-NET-XML-RPC-CLIENT-WINDOWS-FORM.

Tags: ,

Today we release the initial version for the Optio Integration Tools plugin. It can be downloaded from the WordPress plugin repository at this link: http://wordpress.org/extend/plugins/optio-integration-tools/

We developed this plugin for use in Dentfix Pro’s website.

This plugin integrates Option Publishing videos in your WordPress based dentistry site by means of shortcodes. The following shortcodes are available to use:

  1. complete library [optio type=”library” scope=”all”]
  2. partial library (useful for partial subscriptions) [optio type=”library” scope=”dentistry”], [optio type=”library” scope=”orthodontics”], [optio type=”library” scope=”cosmetics”], [optio type=”library” scope=”kids”]
  3. lightbox single video [optio type=”single” scope=”dentistry/missing_tooth/implant_fixed”]
  4. option to use widget instead or in combination with shortcodes. Useful when multiple videos are related to the current post or page

== Installation ==

Upload `optio-integration-tools.zip` to the `/wp-content/plugins/` directory
Unzip the archive
Activate the plugin through the ‘Plugins’ menu in WordPress
Fill up the required option settings

== Frequently Asked Questions ==

= How do I use this plugin? =

First you need to have an active subscription for Optio Publishing services. You can get one here: http://www.optiopublishing.com/dental-videos

This plugin automatically loads all javascript and css files needed to perform the integration of Optio media library in your dentistry website.
It generates automatically a “video of the day” that is rotated every day inside the Optio Publishing Movies widget in case the current post has no related videos
defined. The definition of the related videos is made via a custom field attached to the respective post, page or custom post type.

This plugin offers multiple ways of posts – videos association management. In the Edit Post screen it introduces a specific metabox that allows for videos browsing
and addition/removal tools for the current post. Also a checkbox offers the control to cancel the usage of the association of the videos for that particular post without deleting the
association itself, this being useful for temporary suspension of the function.

Another way to manage the association of videos with posts, pages or custom post types is done via Quick Edit screens where both Quick Edit and Bulk Edit modes can be used. Functionality
is similar to one presented above.

The Optio Publishing Movies widget can be inserted into a sidebar/widgetized area. At the admin interface the plugin can be activated in various contexts, besides the single post/pages/custom post types.
Therefore the Optio Publishing Movies widget can function in homepage, archive pages, search pages, tag pages, category pages, author pages, etc. In case some context is disabled the widget can be automatically taken out
of view. This is done by using the Widget Logic plugin (http://wordpress.org/extend/plugins/widget-logic/) and by manual insertion of this logic statement for Optio Publishing Movies widget:
`global $optiodisplay; return $optiodisplay;`

In single pages the Optio Publishing Movies widget will render the video of the day in case there is no association defined for the current post. If there is an association defined, the associated video thumbnails
will be rendered in the original order of the video catalog/library. This will keep proper order of videos such as in the concept of Introduction -> Problem -> Solution.

The usage of shortcodes is quite trivial, they will be rendered in the place of usage as described in the “Plugin Description” section.

== Screenshots ==

  1. Administration interface
  2. Edit Post metabox interface
  3. Library view modal dialog
  4. Quick Edit mode interface
  5. Bulk Edit mode interface
  6. Optio Publishing Movies Widget administration interface

 

== Known Issues ==

1. tba

== Changelog ==

= 0.1 =
Incipient version

captura imagine website wikitip.info

o captura a paginii principale a sitului web wikitip.info

Recently we started a new project named WikiTip at wikitip.info. This project came out from a long search of the best solution to provide a comprehensive glossary tooltip for some websites administered by us that have content in multiple languages and use different characters including simplified Chinese ones.

We came up with an server/client architecture based on a WordPress platform at the server side, with collaboration tools for developping the dictionaries, and a RESTful API based on JSON to consume the definitions from a target website. We also developed a client module for WordPress incarnated in the WikiTip Knowledge Cluster ToolTip for WordPress plugin that provides webmasters an easy tool to integrate remote definitions tooltips into their WordPress based websites. We named any wikitip site as a Knowledge Cluster since the definitions there will be clustered around a central concept.

At this point in time webmasters should ask for an account at wikitip.info and they will receive a free site like mycluster.wikitip.info where they can start building (or importing) their glossaries / dictionaries. Then on their own WordPress blogs they need to install the plugin and configure it with proper credentials, pointing to their knowledge cluster. Every post in the cluster is making a definition, and any tag associated to that post is a term to be explained. Those terms can be in any language, use any kind of characters, etc. For instance an English definition of the term ming men (life gate in Chinese) will be tagged with ming, ming men, mingmen, and 命门, making all terms that should receive the definition of ming men in the target websites.

By using WPML plugin, all clusters can hold translated definitions in several languages, while keeping the tags as defined terms (some related features are still in development).

The best feature of this system is that a cluster of knowldge may be reused on multiple websites, so webmasters in the same fields or that administer multiple websites can easily consume definitions from a single cluster at wikitip.info.

We are still developing the solution and we are now concerned with scalability issues. Because of this we have imported a bunch or dictionaries freely available in Romania at http://dexonline.ro and created our own version of dexonline at http://dexonline.wikitip.info. Currently we have imported over 250000 definitions and over 145000 base terms with over 900000 inflected forms. We decided to implement an algorithm that is language and punctuation independent, so we need to prepare our dictionaries before actual usage in order to reduce the processing time of identification of terms in the target website page text.

Below are some results we got on our VPS with 1 processor at around 2.4GHz and 2GB RAM:

Number of terms: 145000

Mesajul< \/th>Destinatari< \/th>Citit de< \/th>Data< \/th>Editare< \/th>Stergere< \/th>\r\n< \/tr>< \/thead>
Terms source Preprocessing/loading dictionary object (sec) Actual search duration within the text (sec) Dictionary object size Used memory
DB (preprocessing) 38  – 2MB 161MB
Object retrieved from file cache 1,74 0,37 2MB 130MB
Object retrieved from memory cache 1,32 0,44 2MB 128MB

 

Number of terms: 1050000

Terms source Preprocessing/loading dictionary object (sec) Actual search duration within the text (sec) Dictionary object size Used memory
DB (preprocessing) 409  – 12MB 1GB
Object retrieved from file cache 5,19 1,2 12MB 790MB
Object retrieved from memory cache 2,18 1,09 12MB 778MB

 

Therefore our strategy for large clusters is to preprocess once a day the dictionary into the binary format and to save it into the file cache. Subsequently, first reader will load it from the file cache to the memory cache and all following readers will use this object from memory. If the memory cache fails by any reason, then it will be again retrieved from the file cache in reasonable time. Thus the scalability of our system allows usage of quite large dictionaries within normal user expectations.

Of course, specialized – therefore small – dictionaries will be processed in split seconds by the same algorithm.

When launching in production, the VPS will be upgraded to 8GB of RAM to accomodate several simultaneous requests against the largest knowledge clusters.

Tags: , , , ,

I am using a modified jQuery Thesaurus for some project and I want to explain my solution for the case we have a huge terms database.

The original code provides the following functions:

1. checks the content of a HTML node in a webpage for terms against a dictionary

2. marks the found terms and construct links for AJAX calls to the terms definitions

3. on mouseover constructs a tooltip on the fly and populates it with the term definition

My modified version is using a JSON feed instead of the default DB controller, but this is not the subject to discuss in this article.

The js code waits for page to complete then downloads (or loads from DB) the full list of terms as a javascript object. At this moment, if the database has a big number of terms the speed of execution decreases until the tool becomes unusuable. There are reports that over 400-500 terms the solution is already out of question.

Here I want to explain my solution to this problem. I decided that any webpage content should be much more smaller than a list of terms from a database with several thousand of entries (or even 130k entries as mentioned in the above report). In that case it makes sense to pass the text to the DB controller then filter the list of terms only to the terms that actually exists in the target webpage.

Therefore I have modified the project to handle this request: (code was updated to address the issue mentioned in the first commentary)

1. Change this function as follows

/**
     * 1) Loads list of terms from server
     * 2) Searches terms in DOM
     * 3) Marks up found terms
     * 4) Binds eventhandlers to them
     */
    bootstrap : function() {
		var words;
		var list;
		$.each(this.options.containers, $.proxy(function(i, node) {
                	words += " " + $(node).text().replace(/[\d!;:<>.=\-_`~@*?,%\"\'\\(\\)\\{\\}]/g, ' ').replace(/\s+/g, ' ');
			list = words.split(" ");
			list = removeDuplicates(list);
			words = list.join(" ");
            }, this));
        $.getJSON(this.options.JSON_TERMS_URI+'&words='+words+'&callback=?', $.proxy(function(data){
            this.terms = this._processResponseTerm(data);
            $.each(this.options.containers, $.proxy(function(i, node) {
                this._searchTermsInDOM(node);
                this._markup(node);
            }, this));
            this.bindUI('body');
        }, this));
    },

You can see I am accessing my JSON feed instead of the DB controller but this is not an issue, the idea remains the same. I am passing the extracted text from the containers declared in the Thesaurus Options.

2. Filter the terms in the DB controller (syntax is for generating a JSON feed)

$tgs = $this->get_thesaurus(); //make an array of all terms in the dictionary
$words = $_GET['words']; //load list of unique words from target
$tags = array();

foreach ($tgs as $tag) {
	$list = explode(" ",$tag); //make list of words from each term
	foreach ($list as $word) {
		if (stristr($words, $word)) { //check if any of the words are present at target
			$tags[] = $tag;
			break;
		}
	}
}
		
return array( //return JSON
  'count' => count($tags),
  'tags' => $tags
);

By using this method the size of the dictionary terms loaded in the javascript object falls back to a small number and the speed of the solution is not anymore compromised. It is true that for webpages with massive content the list of words cannot be sent to the server, but for most of the cases this solution will work well.

Tags: ,

O traducere în limba română pentru modulul bbPress 2.0.x pentru WordPress.

Se instalează în directorul …/plugins/bbpress/bbp-languages/

bbPress20-ro_RO.zip

733 de șiruri traduse (100%).

(This is bbPress 2.0 plugin translation into Romanian language.)

Tags:

« Older entries