The Pope Is Dead ::

Main Navigation

The pope is dead. Long live the pope! Just another blog about web development. If you’re interested in web stuff you may find this blog useful.

Setting up my weblog. part 1 tagging

Posted on 06/05/2008 at 08:47 PM

So a major part of my weblog setup using the core version of Expression Engine was adding a way of tagging my posts. In the end I came up with an extension to add the admin functionality and a plugin to get various data into the frontend.

Creating the extension

Ok before we start you need to make sure that:

  • Your MySql server has InnoDb table support
  • You are running PHP5 ( seriously you shouldnt be using 4 anymore! )
  • You have download Zend Framework and added into your include path

Next lets setup a skeletion structure for the extension. Create a file called ext.kp_tagging.php in the extensions dir.

The basic structure
© 2012 Keith Pope
  1. /**
  2. * Tagging extension for my weblog
  3. *
  4. * This file must be placed in the
  5. * /system/extensions/ folder in your ExpressionEngine installation.
  6. *
  7. * Important! Your mysql server must support innodb!!!!
  8. *
  9. * This extension uses Zend Framework make sure it is on the include path
  10. *
  11. * @package KPTagging
  12. * @version Version 0.0.1
  13. * @author Keith Pope
  14. * @copyright Copyright (c) 2007-2008 Keith Pope
  15. * @license New BSD License
  16. */
  17.  
  18. if ( !defined( 'EXT' ) )  exit( 'Invalid file request' );
  19.  
  20. /**
  21. * Manages extension activation, deactivation and upgrading, links class
  22. * methods to ExpressionEngine hooks and implements the administration interface.
  23. *
  24. * @package KPTagging
  25. * @version Version 0.0.1
  26. * @author Keith Pope <http://www.thepopeisdead.com>
  27. * @copyright Copyright (c) 2007-2008 Keith Pope
  28. * @license New BSD License
  29. */
  30. class kp_tagging
  31. {
  32.  
  33.     /**
  34.      * Extension settings
  35.      * @var array
  36.      */
  37.     public $settings = array( );
  38.  
  39.     /**
  40.      * Extension name
  41.      * @var string
  42.      */
  43.     public $name = 'KP Tagging';
  44.  
  45.     /**
  46.      * Extension version
  47.      * @var string
  48.      */
  49.     public $version = '0.0.1';
  50.  
  51.     /**
  52.      * Extension description
  53.      * @var string
  54.      */
  55.     public $description = 'Implements an interface to add tag data to ExpressionEngine weblog entries';
  56.  
  57.     /**
  58.      * If $settings_exist = 'y' then a settings page will be shown in the ExpressionEngine admin
  59.      * @var string
  60.      */
  61.     public $settings_exist = 'n';
  62.  
  63.     /**
  64.      * Link to extension documentation
  65.      * @var string
  66.      */
  67.     public $docs_url = 'http://www.thepopeisdead.com/tagging_extension';
  68.  
  69.     /**
  70.      * Addon Name
  71.      * @var string
  72.      */
  73.     public $addon_name = 'KP Tagging';
  74.  
  75.     /**
  76.      * Log
  77.      * @var array
  78.      */
  79.     public $log = array( );
  80.  
  81.     /**
  82.      * Debug
  83.      * @var array
  84.      */
  85.     public $debug = FALSE;
  86.  
  87.     /**
  88.      * Construct ( No setting atm )
  89.      *
  90.      * @param mixed $settings Optional settings array
  91.      */
  92.     public function __construct( $settings = '' )
  93.     {
  94.  
  95.         global $SESS;
  96.         $this->settings = $settings;
  97.     }
  98.    
  99.     /**
  100.      * Activate the extension in EE.
  101.      *
  102.      * @return    bool Always TRUE
  103.      */
  104.     public function activate_extension()
  105.     {}
  106.    
  107.     /**
  108.      * Update the extension
  109.      *
  110.      * @param string $current
  111.      */
  112.     public function update_extension( $current = '' )
  113.     {}
  114.    
  115.     /**
  116.      * Disable the plugin
  117.      */
  118.     public function disable_extension()
  119.     {}    
  120. }
Parsed in 0.102 seconds, using GeSHi 1.0.7.21

So here we have created the basic structure EE uses to activate, disable, and update extensions. The next step is to write the installer / activation method body.

Add the following into your activate_extension method:

© 2012 Keith Pope
  1. /**
  2.      * Activate the extension in EE.
  3.      *
  4.      * @return    bool Always TRUE
  5.      */
  6.     public function activate_extension()
  7.     {
  8.  
  9.         global $DB, $PREFS;
  10.        
  11.         $hooks = array( 'publish_form_new_tabs' => 'publish_form_new_tabs', 'publish_form_new_tabs_block' => 'publish_form_new_tabs_block', 'submit_new_entry_end' => 'submit_new_entry_end', 'show_full_control_panel_end' => 'show_full_control_panel_end' );
  12.        
  13.         foreach( $hooks as $hook => $method )
  14.         {
  15.             $sql[] = $DB->insert_string( 'exp_extensions', array( 'extension_id' => '', 'class' => get_class( $this ), 'method' => $method, 'hook' => $hook, 'settings' => '', 'priority' => 10, 'version' => $this->version, 'enabled' => "y" ) );
  16.         }
  17.        
  18.         /**
  19.          * Now create the tagging tables, I am using the recommended schema
  20.          * from mysql forge <a href="http://forge.mysql.com/wiki/TagSchema#Schema">http://forge.mysql.com/wiki/TagSchema#Schema</a>
  21.          * I have found this to works well on other projects and its a pretty
  22.          * interesting read hopefully someone will finish it one day.
  23.          */
  24.        
  25.         //Change the exp_weblog_data to innodb
  26.         $sql[] = 'ALTER TABLE exp_weblog_data ENGINE=InnoDB';
  27.        
  28.         //create the tag table
  29.         $sql[] = 'CREATE TABLE IF NOT EXISTS exp_kp_tags (
  30.                    tag_id INT UNSIGNED NOT NULL AUTO_INCREMENT
  31.                    , tag_text VARCHAR(156) NOT NULL
  32.                    , PRIMARY KEY (tag_id)
  33.                    ,  UNIQUE INDEX (tag_text)
  34.                    ) ENGINE=InnoDB;';
  35.        
  36.         //create the tag links
  37.         $sql[] = 'CREATE TABLE IF NOT EXISTS exp_kp_weblog2tag (
  38.                    entry_id INT UNSIGNED NOT NULL
  39.                    , tag_id INT UNSIGNED NOT NULL
  40.                    , PRIMARY KEY (entry_id, tag_id)
  41.                    , INDEX (tag_id)
  42.                    , FOREIGN KEY fk_Entry (entry_id) REFERENCES exp_weblog_data (entry_id) ON DELETE CASCADE
  43.                    , FOREIGN KEY fk_Tag (tag_id) REFERENCES exp_kp_tags (tag_id) ON DELETE CASCADE
  44.                    ) ENGINE=InnoDB';
  45.        
  46.         //run the sql
  47.         foreach( $sql as $query )
  48.         {
  49.             $DB->query( $query );
  50.         }
  51.        
  52.         return true;
  53.     }
Parsed in 0.119 seconds, using GeSHi 1.0.7.21

Ok so now what have we done, firstly we need to decide what hooks we are going to get our extension to extend from. This is done by inserting information about the plugin and hook into the exp_extensions table.

© 2012 Keith Pope
  1. $hooks = array(
  2.             'publish_form_new_tabs' => 'publish_form_new_tabs',
  3.             'publish_form_new_tabs_block' => 'publish_form_new_tabs_block',
  4.             'submit_new_entry_end' => 'submit_new_entry_end',
  5.             'show_full_control_panel_end' => 'show_full_control_panel_end'
  6.         );
  7.        
  8.         foreach( $hooks as $hook => $method )
  9.         {
  10.             $sql[] = $DB->insert_string( 'exp_extensions', array( 'extension_id' => '',
  11.                                                                   'class' => get_class( $this ),
  12.                                                                   'method' => $method,
  13.                                                                   'hook' => $hook,
  14.                                                                   'settings' => '',
  15.                                                                   'priority' => 10,
  16.                                                                   'version' => $this->version,
  17.                                                                   'enabled' => "y" ) );
  18.         }
Parsed in 0.083 seconds, using GeSHi 1.0.7.21

Next we need to create a table for our tags and then a table to map our relationships. Also we alter the exp_weblog_data so its innodb, this is so we can have foreign key constrants.

Note about the tagging schema

I have used the tagging schema suggested on the MySQL Forge wiki, its well worth having a look at there are many tips on the performance of such a schema. http://forge.mysql.com/wiki/TagSchema#Schema

© 2012 Keith Pope
  1. //Change the exp_weblog_data to innodb
  2.         $sql[] = 'ALTER TABLE exp_weblog_data ENGINE=InnoDB';
  3.        
  4.         //create the tag table
  5.         $sql[] = 'CREATE TABLE IF NOT EXISTS exp_kp_tags (
  6.                    tag_id INT UNSIGNED NOT NULL AUTO_INCREMENT
  7.                    , tag_text VARCHAR(156) NOT NULL
  8.                    , PRIMARY KEY (tag_id)
  9.                    ,  UNIQUE INDEX (tag_text)
  10.                    ) ENGINE=InnoDB;';
  11.        
  12.         //create the tag links
  13.         $sql[] = 'CREATE TABLE IF NOT EXISTS exp_kp_weblog2tag (
  14.                    entry_id INT UNSIGNED NOT NULL
  15.                    , tag_id INT UNSIGNED NOT NULL
  16.                    , PRIMARY KEY (entry_id, tag_id)
  17.                    , INDEX (tag_id)
  18.                    , FOREIGN KEY fk_Entry (entry_id) REFERENCES exp_weblog_data (entry_id) ON DELETE CASCADE
  19.                    , FOREIGN KEY fk_Tag (tag_id) REFERENCES exp_kp_tags (tag_id) ON DELETE CASCADE
  20.                    ) ENGINE=InnoDB';
  21.        
  22.         //run the sql
  23.         foreach ($sql as $query)
  24.         {
  25.             $DB->query($query);
  26.         }
Parsed in 0.033 seconds, using GeSHi 1.0.7.21

Ok so thats the activation dealt with now we need to create the disable method body.

© 2012 Keith Pope
  1. /**
  2.      * Disable the plugin ( we wont delete the tags do that yourself )
  3.      */
  4.     public function disable_extension()
  5.     {
  6.         global $DB;
  7.         $DB->query("DELETE FROM exp_extensions WHERE class = '" . get_class($this) . "'");
  8.     }
Parsed in 0.016 seconds, using GeSHi 1.0.7.21

This is very simple its just un-hooks the hooks in the ext_extensions table, I didn't delete the other tables I created as there may be valuable data there and its better to do it manually!

Obviously we dont have any upgrades to do so just make the update_extension method return true.

Ok thats it we have an extension that can be activated in the admin now, wait dont activate it just yet! Yeah we need to actually write the hooks else EE will try and call not existant methods!

The Hooks

Right to do what we want, we need to use the following hooks:

  • publish_form_new_tabs
  • publish_form_new_tabs_block
  • submit_new_entry_end
  • show_full_control_panel_end

For a full list of hooks available to you goto http://expressionengine.com/developers/extension_hooks/ this details all the aailable hooks and what they do.

First off we need to add in a tab on the entry add/edit page. So we use the publish_form_new_tabs hook.

© 2012 Keith Pope
  1. /**
  2.      * Adds a new tab to the publish / edit form
  3.      *
  4.      * @param    array $publish_tabs Array of existing tabs
  5.      * @param    int $weblog_id Current weblog id
  6.      * @param    int $entry_id Current entry id
  7.      * @param    array $hidden Hidden form fields
  8.      * @return    array Modified tab list
  9.      */
  10.     public function publish_form_new_tabs( $publish_tabs, $weblog_id, $entry_id, $hidden )
  11.     {
  12.         global $EXT;
  13.  
  14.         if( $EXT->last_call !== FALSE )
  15.         {
  16.             $publish_tabs = $EXT->last_call;
  17.         }
  18.        
  19.         $publish_tabs['kpt'] = 'Tagging';
  20.  
  21.         return $publish_tabs;
  22.     }
Parsed in 0.033 seconds, using GeSHi 1.0.7.21

So here we are simply adding in a new tab with the text 'Tagging' into the $publish_tabs array. There are a couple of important things to note here.

It is very important to use the $EXT->last_call, if you just add the new tab and return the array no other extensions that use the same hook will work! This goes for all the hooks!

Also the key you you give your tab ( $publish_tabs['kpt'] ) is used to indentify your tab block, so remember it from later!

Ok now we have a tab but no tab block so the next thing to do is create the block.

Now here I chose to use Zend_View as I dont like creating html output in my php code! If you want to use the standard EE way look at the $DSP global var which has a load of methods for creating html. I personally dont like this method of creating html as it ties display with logic and is also very hard to read! I have enough problems creating DOM elements this way in Javascript.

So first add this into the header of the file:

© 2012 Keith Pope
  1. if ( !defined( 'EXT' ) )  exit( 'Invalid file request' );
  2.  
  3. /* Zend_View */
  4. require_once 'Zend/Loader.php';
  5. Zend_Loader::loadClass( 'Zend_View' );
Parsed in 0.022 seconds, using GeSHi 1.0.7.21

This will load Zend_View, now we can create the tab block.

© 2012 Keith Pope
  1. /**
  2.      * Render the tagging form block, uses Zend_View as
  3.      * I was too lazy to write loads of php to produce the html :)
  4.      *
  5.      * @param int $weblog_id
  6.      * @return string
  7.      */
  8.     public function publish_form_new_tabs_block( $weblog_id )    
  9.     {
  10.         global $DB, $EXT, $PREFS, $SESS, $LANG, $REGX, $IN, $DSP;
  11.  
  12.         if( $EXT->last_call !== FALSE )
  13.         {
  14.             $ret = $EXT->last_call;
  15.         }
  16.        
  17.         $view = new Zend_View();
  18.         $view->Doctype( 'XHTML1_STRICT' );
  19.         $view->tagText = '';
  20.        
  21.         //editing?
  22.         if( $entry_id = $IN->GBL( 'entry_id', 'GET' ) )
  23.         {
  24.             // get the tags
  25.             $query = $DB->query( 'SELECT tag_text
  26.                                    FROM exp_kp_tags, exp_kp_weblog2tag
  27.                                    where exp_kp_tags.tag_id = exp_kp_weblog2tag.tag_id
  28.                                    AND exp_kp_weblog2tag.entry_id = "' . $entry_id . '"
  29.                                    GROUP BY exp_kp_tags.tag_id' );    
  30.  
  31.             // if records
  32.             if( $query->num_rows > 0 )
  33.             {
  34.                 $tags = array();
  35.  
  36.                 foreach( $query->result as $row )
  37.                 {
  38.                     $tags[] = $row['tag_text'];
  39.                 }
  40.                
  41.                 $view->tagText = join( ',', $tags );
  42.             }
  43.         }
  44.        
  45.         $path = realpath( dirname( __FILE__ ) );
  46.         $view->setScriptPath( $path . '/kp_tagging' );
  47.         $view->prefs = $PREFS;
  48.        
  49.         $ret = $view->render( 'tagging_block_view.phtml' );
  50.        
  51.         return $ret;
  52.     }
Parsed in 0.091 seconds, using GeSHi 1.0.7.21

And the view file can be placed in extensions/kp_tagging/tagging_block_view.phtml

© 2012 Keith Pope
  1. <div id="blockkpt">
  2.     <div class="publishTabWrapper">
  3.         <div class="publishBox">
  4.             <div class="publishInnerPad">
  5.             <table cellspacing="0" cellpadding="0" border="0" style="width: 99%;">
  6.                 <tr>
  7.                     <td>
  8.                         <h5>Enter Tags</h5>
  9.                         <?php echo $this->formText( 'kp_tags', $this->tagText ); ?>
  10.                         <p>Seperate tags with commas</p>    
  11.                     </td>
  12.                     <td style="width: 350px;">
  13.                         <?php echo $this->formButton( 'kp_gentags', 'Auto-Generate', array( 'title' => $this->prefs->default_ini['system_folder'] ) ); ?>
  14.                     </td>
  15.                 </tr>
  16.             </table>
  17.             </div>
  18.         </div>
  19.     </div>
  20. </div>
Parsed in 0.088 seconds, using GeSHi 1.0.7.21

This will give us this:

Also in this method we check if we are editing a record by checking the GET for entry_id, if we are editing we retrieve the tags for this entry.

Now we need to handle submit_new_entry_end hook, this hook is called when you add/edit an entry.

© 2012 Keith Pope
  1. /**
  2.      * Add the tags into the db
  3.      *
  4.      * @param int    $entry_id
  5.      * @param array  $data
  6.      * @param string $ping_message
  7.      */
  8.     public function submit_new_entry_end( $entry_id, $data, $ping_message )
  9.     {
  10.         global $DB, $PREFS, $SESS, $IN;
  11.        
  12.         if( isset( $_POST['kp_tags'] ) && $_POST['kp_tags'] != '' )
  13.         {
  14.             $tags = $_POST['kp_tags'];
  15.             $tags = ltrim( $tags, ',' );
  16.             $tags = rtrim( $tags, ',' );
  17.  
  18.             $tags = explode( ',', $tags );
  19.  
  20.             $count = 0;
  21.             $addedTags = array();
  22.            
  23.             foreach( $tags as $tag )
  24.             {
  25.                 if( trim( $tag ) == '' )
  26.                 {
  27.                     continue;
  28.                 }
  29.    
  30.                 $count++;
  31.                
  32.                 //first add any new tags!
  33.                
  34.                 $query = $DB->query( "SELECT * FROM    exp_kp_tags WHERE tag_text='" . $DB->escape_str( $tag ) . "' LIMIT 1" );
  35.                
  36.                 if ($query->num_rows == 0)
  37.                 {
  38.                     $tagText = trim( $tag );
  39.                     $insert = $DB->insert_string( 'exp_kp_tags', array( 'tag_text' => $tagText ) );
  40.                     $DB->query( $insert );
  41.                    
  42.                     $addedTags[] = $DB->insert_id;
  43.                     continue;
  44.                 }
  45.                
  46.                 $existingTag = $query->row;
  47.                 $addedTags[] = $existingTag['tag_id'];
  48.                
  49.             }
  50.            
  51.             if( $count != 0 )
  52.             {
  53.                 //unlink all (not most efficient but we have no edit hook :( )
  54.                 $sql = "DELETE FROM exp_kp_weblog2tag WHERE entry_id = " . $entry_id;
  55.                 $DB->query( $sql );
  56.                
  57.                 //now link the tags to the entry    
  58.                 foreach( $addedTags as $tagID )
  59.                 {
  60.                     $row = array( 'entry_id' => $entry_id, 'tag_id' => $tagID );
  61.                     $insert = $DB->insert_string( 'exp_kp_weblog2tag', $row );
  62.                     $DB->query( $insert );
  63.                 }
  64.             }
  65.         }
  66.     }
Parsed in 0.179 seconds, using GeSHi 1.0.7.21

Here for some reason there isnt a edit hook, so I just delete all the tags and re-add them for each submission. I will tidy this up as time goes by but it works for now...

The final hook is the show_full_control_panel_end this gives you the full page of the control panel so we have to do a replace to insert our JS and CSS.

© 2012 Keith Pope
  1. /**
  2.      * Process the final control panel output
  3.      *
  4.      * @param string $out
  5.      * @return string
  6.      */
  7.     public function show_full_control_panel_end( $out )
  8.     {
  9.         global $EXT;
  10.  
  11.         if( $EXT->last_call !== FALSE )
  12.         {
  13.             $out = $EXT->last_call;
  14.         }
  15.  
  16.         $r =  '<script type="text/javascript" src="/scripts/mootools_full.js"></script>' . "\n";
  17.         $r .= '<script type="text/javascript" src="/scripts/kptagging.js"></script>' . "\n";
  18.         $r .= "<style type='text/css' media='screen'>
  19.                #blockkpt{display:none;}
  20.                    #blockkpt input,
  21.                    #blockkpt textarea{display:block; width:99%}
  22.                #blockkpt .highlight{margin:10px;}
  23.                #blockkpt .multi{overflow:auto;}
  24.                    #blockkpt .multi div{float:left; width:33%;}
  25.                    #blockkpt .multi input,
  26.                    #blockkpt .multi select{display:block; width:80%;}
  27.                #blockkpt .character-count{margin:9px 0}
  28.                #blockkpt .toomuch{color:#ff0000};
  29.                #blockkpt .keywords input{display:inline; margin-right:5px; width:80%}
  30.                #blockkpt .hidden{display:none;}
  31.            </style>";
  32.        
  33.         // add the script string before the closing head tag
  34.         $out = str_replace( "</head>", $r . "</head>", $out );
  35.         // make sure we don't add it again
  36.            
  37.         return $out;
  38.     }
Parsed in 0.062 seconds, using GeSHi 1.0.7.21
The Plugin

Once the extension is created you should be able to enable it in the control panel! But there is one more part to the extension, thats a plugin to pull the data into the frontend.

Plugins are quite simple in EE however I didn't want to reproduce the weblog functionality in my plugin so it got a little complex with me opting to extend the weblog module. This is not the best way to do this but again I wanted something up quickly.

Heres the plugin code ( pi.kp_tag.php )

© 2012 Keith Pope
  1. <?php
  2. /**
  3.  * Plugin File for kp tagging
  4.  *
  5.  * This file must be placed in the
  6.  * /system/plugins/ folder in your ExpressionEngine installation.
  7.  *
  8.  * @package KPTagging
  9.  * @version Version 0.0.1
  10.  * @author Keith Pope <http://www.thepopeisdead.com>
  11.  * @copyright Copyright (c) 2007-2008 Keith Pope
  12.  * @license New BSD License
  13.  */
  14.  
  15. /**
  16.  * Plugin information used by ExpressionEngine
  17.  * @global array $plugin_info
  18.  */
  19. $plugin_info = array(
  20.     'pi_name'             => 'KP Tagging',
  21.     'pi_version'         => '0.0.1',
  22.     'pi_author'         => 'Keith Pope',
  23.     'pi_author_url'     => 'http://www.thepopeisdead.com/',
  24.     'pi_description'    => 'Get a tag cloud',
  25.     'pi_usage'             => 'Its easy...'
  26. );
  27.  
  28. $p = realpath( PATH_MOD . '/weblog/' );
  29. require_once $p . '/mod.weblog' . EXT;
  30.  
  31. /**
  32.  * Tag cloud....
  33.  *
  34.  * @package KPTagging
  35.  * @version Version 0.0.1
  36.  * @author Keith Pope <http://www.thepopeisdead.com>
  37.  * @copyright Copyright (c) 2007-2008 Keith Pope
  38.  * @license New BSD License
  39.  */
  40. class Kp_tag extends Weblog
  41. {
  42.     /**
  43.      * Returned string
  44.      * @var array
  45.      */
  46.     public $return_data = "";
  47.  
  48.     /**
  49.      * Plugin version
  50.      * @var array
  51.      */
  52.     public $version = "0.0.1";
  53.    
  54.     /**
  55.      * Store for when we are getting tagged
  56.      * items for one tag.
  57.      *
  58.      * @var string
  59.      */
  60.     private $kp_tag;
  61.    
  62.     /**
  63.      * Not used...
  64.      *
  65.      * @return Kp_tag
  66.      */
  67.     public function Kp_tag()
  68.     {}
  69.    
  70.     /**
  71.      * Get the tag cloud
  72.      *
  73.      * @return string
  74.      */
  75.     public function cloud()
  76.     {
  77.         global $DB, $TMPL, $PREFS, $FNS, $LANG, $OUT, $SESS;
  78.        
  79.         $output = '';
  80.        
  81.         $sql = 'SELECT tag_text
  82.                , COUNT(*) as num_items
  83.                FROM exp_kp_weblog2tag i2t
  84.                INNER JOIN exp_kp_tags t
  85.                ON i2t.tag_id = t.tag_id
  86.                GROUP BY tag_text';
  87.        
  88.         $query = $DB->query( $sql );
  89.        
  90.         if( $query->num_rows > 0 )
  91.         {
  92.             $tags   = array();
  93.             $totals = array();
  94.            
  95.             foreach( $query->result as $row )
  96.             {
  97.                 $tags[]   = $row['tag_text'];
  98.                 $totals[] = $row['num_items'];
  99.             }
  100.            
  101.             //do some calculations
  102.             $max_size = 30; // max font size in pixels
  103.             $min_size = 11; // min font size in pixels
  104.            
  105.             // largest and smallest array values
  106.             $max_qty = max( array_values( $totals ) );
  107.             $min_qty = min( array_values( $totals ) );
  108.            
  109.             // find the range of values
  110.             $spread = $max_qty - $min_qty;
  111.             if( $spread == 0 )
  112.             {
  113.                 $spread = 1;
  114.             }
  115.            
  116.             // set the font-size increment
  117.             $step = ( $max_size - $min_size ) / ( $spread );
  118.             $output = '';
  119.            
  120.             // loop through the tag array
  121.             foreach( $tags as $key => $value )
  122.             {
  123.                 $size = round( $min_size + ( ( $totals[$key] - $min_qty ) * $step ) );
  124.                 $output .= '<a href="/main/tagged/' .
  125.                             urlencode( $value ) .
  126.                             '" style="font-size: ' .
  127.                             $size .
  128.                             'px" title="' .
  129.                             $totals[$key] .
  130.                             ' things tagged with ' .
  131.                             $value . '">' .
  132.                             strtolower( $value ) . '</a> ';
  133.             }
  134.         }
  135.        
  136.         return $output;
  137.     }
  138.    
  139.     /**
  140.      * Get entires tagged with something...
  141.      *
  142.      * Expects tag in $_GET
  143.      *
  144.      * @see parse_weblog_entries()
  145.      * @return string
  146.      */
  147.     public function GetTaggedEntries()
  148.     {
  149.         global $DB, $TMPL, $PREFS, $FNS, $LANG, $OUT, $SESS, $IN, $TYPE;
  150.        
  151.         $this->limit = 1;
  152.        
  153.         $this->kp_tag = !isset( $IN->SEGS[3] ) ? '' : $IN->SEGS[3] ;
  154.        
  155.         parent::Weblog();  
  156.         parent::entries();
  157.        
  158.         return $this->return_data;
  159.     }
  160.    
  161.     /**
  162.      * Override the parsing in parent::entries so
  163.      * we can augment the query and use the same tags
  164.      * we normally do in all the weblog entries!
  165.      *
  166.      * This does run 2 queries but this was the only way
  167.      * I could work around...
  168.      */
  169.     public function parse_weblog_entries()
  170.     {
  171.         global $DB, $TMPL;
  172.        
  173.         $this->p_limit = 10;
  174.         $this->page_next = '';
  175.         $this->page_previous = '';
  176.         $this->pagination_links = '';
  177.         $this->total_pages = 1;
  178.  
  179.         $sql = "select wt.entry_id FROM exp_kp_tags t
  180.                JOIN exp_kp_weblog2tag wt ON t.tag_id = wt.tag_id
  181.                where t.tag_text = '{$DB->escape_str( $this->kp_tag )}'";
  182.        
  183.         $q = $DB->query( $sql );
  184.        
  185.         if( $q->num_rows == 0 )
  186.         {
  187.             $this->return_data = 'No items tagged ' . $this->kp_tag;
  188.             return;
  189.         }
  190.        
  191.         $ids = array();
  192.        
  193.         foreach( $q->result as $row )
  194.         {
  195.             $ids[] = $row['entry_id'];
  196.         }
  197.        
  198.        
  199.         $this->sql = preg_replace('/IN \\((.+)\\)/i', 'IN( ' . join( ',', $ids ) . ')', $this->sql);
  200.        
  201.         $total = $q->num_rows;
  202.         $this->create_pagination($total);
  203.        
  204.         $page = $this->p_page == null ? 0 : $this->p_page;
  205.         $this->sql .= " LIMIT ". $page . ', ' . $this->p_limit;
  206.  
  207.         $this->query = $DB->query( $this->sql );
  208.        
  209.         parent::parse_weblog_entries();
  210.     }
  211.  
  212.     /**
  213.      * Plugin usage documentation
  214.      *
  215.      * @return    string Plugin usage instructions
  216.      */
  217.     public static function Usage()
  218.     {
  219.         return "For usage visit: <a href="http://www.thepopeisdead.com";">http://www.thepopeisdead.com";</a>
  220.     }
  221. }
Parsed in 0.357 seconds, using GeSHi 1.0.7.21

The plugin does two things it gets a tag cloud and get entries related to a tag. I still think there must be a better way of doing this in EE hopefully I will figure it out as I go along! At the moment I am rewriting the query in parse_weblog_entries which works but its not very pretty. One good thing is that our plugin has all the same tag support as the weblog module now :)

Thats about it for the tagging extension, the only bit I have left out is the Ajax auto-suggest. But I want to do some tutorials on Mootools soon anyway. For now you can download the source below:

Download KpTagging Extension 0.0.1

There are still loads of improvements I want to add to this but it got me up and running quickly, I will update with improvements when I get time. If you need any help leave a comment or email me...

Comments

Looking good so far :) There’s no styling in the RSS though so it’s hard to read in Google Reader…

Posted by Alex Mace  on  09/05/2008  at  06:50 AM

Thx dude, yeah I am still going through fixing stuff :)

It turned out to be more work than I throught hehe…

Posted by [MuTe]  on  09/05/2008  at  05:11 PM
Page 1 of 1 comments

Next entry: Continuous Integration Fun & Whats Coming Soon...

Previous entry: Easy Javascript / CSS Compression with phing

about me

I am a web developer/ project manager from Birmingham Uk, currently I am working for inflight productions as a technical project manager. Hopefully I will be posting here as regularly as possible on my experiences with various technologies that I am using and maybe the odd random thing..

the book

comment on this

Name:

Email:

Location:

URL:

Remember my personal information

Notify me of follow-up comments?