Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

base-tags.inc.php

Go to the documentation of this file.
00001 <?
00008 abstract class BaseTags extends MyModule
00009 {
00013     protected $tagTable;
00014 
00018     protected $joinerTable;
00019     
00023     public $plural;
00024 
00028     public $objectId = 0;
00029 
00033     public static $cachePopularTags = true;
00034 
00038     public static $popularTagsCacheLife = 3600;
00039     
00043     public static $cacheRelatedTags = true;
00044 
00048     public static $relatedTagsCacheLife = 3600;
00049 
00053     public static $weightStyles = array(
00054         'font-size: 35px;',
00055         'font-size: 25px;',
00056         'font-size: 20px;', 
00057         'font-side: 16px;',
00058         'font-size: 11px;'
00059     );
00060 
00068     public function __construct($id, $tagTable, $joinerTable)
00069     {
00070         $this->english = 'tag';
00071         $this->plural = 'tags';
00072         
00073         $this->tagTable = $tagTable;
00074         $this->joinerTable = $joinerTable;
00075         $this->objectId = (int)$id;
00076     } 
00077 
00083     public function getPagesXml()
00084     {
00085         $xml = parent::getPagesXml();
00086         $xml .= <<<XML
00087             <page name="view">
00088                 <param name="tag" regex="/^\w*$/" required="1" />
00089             </page>
00090 XML;
00091         return $xml;
00092      }
00093 
00097     public function initViewPage()
00098     {
00099         $tag = $this->params('tag');
00100 
00101         if (!$this->findTag($tag))
00102             throw new PageError("The tag $tag does not exist.");
00103 
00104         $this->pageTitle = self::prettyTag($tag);
00105 
00106         //we wanna cache the view page
00107         $this->doCachePage = true;
00108     }
00109 
00113     public function drawViewPage()
00114     {
00115         $this->drawRelatedTags();
00116     }
00117 
00121     public function drawRelatedTags()
00122     {
00123         echo "<h3>Related " . ucfirst($this->plural) . "</h3>\n";
00124         echo "<p>" . $this->getRelatedTagsList($this->params('tag')) . "</p>";
00125     }
00126 
00130     public function initMainPage()
00131     {
00132         $this->pageTitle = 'Popular ' . ucfirst($this->plural);
00133 
00134         $this->doCachePage = true;
00135     }
00136 
00140     public function drawMainPage()
00141     {
00142         echo "<p>" . $this->getWeightedPopularTagsList() . "</p>";
00143     }
00144 
00154     public static function cleanTag($tag)
00155     {
00156         //trip it!
00157         $tag = trim($tag);
00158 
00159         //make all whitespace be underscores.
00160         $tag = preg_replace("/\s/", "_", $tag);
00161         
00162         //anything not a 'word' character (alphanumeric, underscore) gets removed.
00163         $tag = preg_replace("/\W/", "", $tag);
00164 
00165         return $tag;
00166     }
00167 
00175     public static function prettyTag($tag)
00176     {
00177         return str_replace("_", " ", $tag);
00178     }
00179 
00188     public function addTag($tag)
00189     {
00190         //clean it.
00191         $tag = self::cleanTag($tag);
00192 
00193         //look for it.
00194         $id = $this->findTag($tag);
00195         
00196         //if we didnt get it...
00197         if (!$id)
00198             $id = $this->insertTag($tag);
00199 
00200         //give them the id.
00201         return $id;
00202     }
00203 
00210     protected function insertTag($tag)
00211     {
00212         $tag = self::cleanTag($tag);
00213 
00214         //insert it into the db.
00215         $id = dbExecute("
00216             INSERT INTO $this->tagTable
00217                 (tag)
00218             VALUES
00219                 ('$tag')
00220         ", true);
00221 
00222         return $id;
00223     }
00224 
00232     public function deleteTag($tag)
00233     {
00234         //clean it...
00235         $tag = self::cleanTag($tag);
00236 
00237         //delete it.
00238         $rows = dbExecute("
00239             DELETE FROM $this->tagTable
00240             WHERE tag = '$tag'
00241             LIMIT 1
00242         ", -1);
00243 
00244         return $rows;
00245     }
00246 
00254     public function findTag($tag)
00255     {
00256         //clean it...
00257         $tag = self::cleanTag($tag);
00258     
00259         //search it.
00260         $rs = dbQuery("
00261             SELECT id
00262             FROM $this->tagTable
00263             WHERE tag = '$tag'
00264         ");
00265 
00266         //get it.
00267         if (dbGetNumRows($rs))
00268         {
00269             $ar = dbFetchAssoc($rs);
00270             return $ar['id'];
00271         }
00272             
00273         //oops, no id!
00274         return false;
00275     }
00276 
00282     public function getTags()
00283     {
00284         $tags = array();
00285 
00286         //only do it if we have an id.
00287         if ($this->objectId)
00288         {
00289             $where = $this->getTagsWhere();
00290             
00291             //do our query.
00292             $rs = dbQuery("
00293                 SELECT t.id, t.tag
00294                 FROM $this->tagTable t
00295                 INNER JOIN $this->joinerTable j
00296                     ON t.id = j.tag_id
00297                 $where
00298                 ORDER BY t.tag
00299             ");
00300 
00301             //fetch it!
00302             while ($ar = dbFetchAssoc($rs))
00303                 $tags[$ar['id']] = $ar['tag'];
00304         }
00305 
00306         //send them home.
00307         return $tags;
00308     }
00309 
00310     function delete()
00311     {
00312         dbExecute("
00313             DELETE FROM $this->joinerTable WHERE object_id = $this->objectId 
00314         ");
00315     }
00316 
00322     protected function getTagsWhere()
00323     {
00324         return "WHERE j.object_id = '$this->objectId'";
00325     }
00326 
00332     public function getPrettyTags()
00333     {
00334         $tags = $this->getTags();
00335 
00336         foreach ($tags AS &$tag)
00337             $tag = self::prettyTag($tag);
00338 
00339         return $tags;
00340     }
00341 
00349     public function getObjectsSql($tagId)
00350     {
00351         //our query
00352         return "
00353             SELECT distinct(z.object_id)
00354             FROM $this->joinerTable z
00355             WHERE z.tag_id = '$tagId'
00356         ";
00357     }
00358 
00367     public function getPopularTags($count = 30)
00368     {
00369         //heres our lookup sql.
00370         $popularSql = "
00371             SELECT t.tag, count(j.object_id) AS popularity
00372             FROM $this->tagTable t
00373             INNER JOIN $this->joinerTable j
00374                 ON t.id = j.tag_id
00375             GROUP BY t.tag
00376             ORDER BY popularity DESC
00377             LIMIT $count
00378         ";
00379         $key = "BaseJumper:tags:popular:" . sha1($popularSql);
00380 
00381         //try the cache.
00382         if (self::$cachePopularTags)
00383             $tags = CacheBot::get($key, self::$popularTagsCacheLife);
00384     
00385         //did we get them?
00386         if (!$tags)
00387         {
00388             $tags = array();
00389             
00390             //do our query...
00391             $rs = dbQuery($popularSql);
00392             
00393             //get our array.
00394             while ($ar = dbFetchAssoc($rs))
00395                 $tags[] = $ar['tag'];
00396 
00397             //save it back to the cache.
00398             if (self::$cachePopularTags)
00399                 CacheBot::set($key, $tags, self::$popularTagsCacheLife);
00400         }
00401 
00402         //send it home.
00403         return $tags;
00404     }
00405 
00412     public function getPopularTagsList($count = 60)
00413     {
00414         //inital stuff.
00415         $tags = $this->getPopularTags($count);
00416 
00417         //link up!
00418         $links = $this->getLinkedTags($tags);
00419 
00420         //get 'er done.
00421         return implode(", ", $links);
00422     }
00423     
00430     public function getWeightedPopularTagsList($count = 100)
00431     {
00432         //inital stuff.
00433         $tags = $this->getPopularTags($count);
00434 
00435         //link up!
00436         $links = $this->getLinkedTags($tags);
00437 
00438         //loop thru and get the weighted stuff
00439         $i = 0;
00440         foreach ($links AS $link)
00441         {
00442             if ($i < 5)
00443             {
00444                 $class = "WeightedTagHighest";
00445                 $style = self::$weightStyles[0];
00446             }
00447             else if ($i < 20)
00448             {
00449                 $class = "WeightedTagHigh";
00450                 $style = self::$weightStyles[1];
00451             }
00452             else if ($i < 40)
00453             {
00454                 $class = "WeightedTagMedium";
00455                 $style = self::$weightStyles[2];
00456             }
00457             else if ($i < 65)
00458             {
00459                 $class = "WeightedTagLow";
00460                 $style = self::$weightStyles[3];
00461             }
00462             else
00463             {
00464                 $class = "WeightedTagLowest";
00465                 $style = self::$weightStyles[4];
00466             }
00467             
00468             $weighted[] = "<span class=\"$class\" style=\"$style\">$link</span>";
00469 
00470             $i++;
00471         }
00472 
00473         //get 'er done.
00474         return implode(" ", $weighted);
00475     }
00476 
00482     protected function getTagFieldParams()
00483     {
00484         return array(
00485             'id' => strtolower(get_class($this)),
00486             'value' => implode(", ", $this->getPrettyTags()),
00487             'title' => "Enter $this->plural<br/>(separated by commas)",
00488             'class' => 'BaseTags',
00489             'width' => '100%',
00490             'height' => '100px',
00491         );
00492     }
00493     
00501     protected function getPopularFieldParams()
00502     {
00503         return array(
00504             'title' => "Popular $this->plural<br/>(click to add)",
00505             'text' => $this->getFormPopularCloud()
00506         );
00507     }
00508 
00514     public function updateTagsForm($form)
00515     {
00516         //get our data.
00517         $data = $form->getData(strtolower(get_class($this)));
00518         $dataRs = explode(",", $data);
00519 
00520         //pass it off to our updater.
00521         $this->updateTags($dataRs);
00522     }
00523 
00529     public function updateTags($data)
00530     {
00531         //initialization
00532         $old = $this->getTags();
00533         $newTags = array();
00534         $oldTags = array();
00535         
00536         //clean them.
00537         if (count($old))
00538             foreach ($old AS $tag)
00539                 $oldTags[] = self::cleanTag($tag);
00540         if (count($data))
00541             foreach ($data AS $tag)
00542                 $newTags[] = self::cleanTag($tag);
00543 
00544         //add the news ones!
00545         if (count($newTags))
00546         {
00547             foreach ($newTags AS $tag)
00548             {
00549                 if (!in_array($tag, $oldTags))
00550                     $this->addTagLink($tag);
00551             }
00552         }
00553         
00554         //delete the old tags...
00555         if (count($oldTags))
00556         {
00557             foreach ($oldTags AS $tag)
00558             {
00559                 if (!in_array($tag, $newTags))
00560                     $this->removeTagLink($tag);
00561             }
00562         }
00563     }
00564 
00570     public function addTagLink($tag)
00571     {
00572         $tag = self::cleanTag($tag);
00573 
00574         //is it a tag?
00575         if ($tag != '')
00576         {
00577             //find/create tag.
00578             $tagId = $this->addTag($tag);
00579             
00580             //insert it.
00581             if ($tagId)
00582                 $this->addTagLinkDb($tagId);
00583         }
00584     }
00585 
00591     protected function addTagLinkDb($tagId)
00592     {
00593         dbExecute("
00594             INSERT INTO $this->joinerTable
00595                 (tag_id, object_id)
00596             VALUES
00597                 ('$tagId', '$this->objectId')
00598         ");
00599     }
00600 
00606     public function removeTagLink($tag)
00607     {
00608         //get our tag id.
00609         $tagId = $this->findTag($tag);
00610         
00611         //delete it.
00612         if ($tagId)
00613             $this->removeTagLinkDb($tagId);
00614     }
00615     
00621     public function removeTagLinkDb($tagId)
00622     {
00623         dbExecute("
00624             DELETE FROM $this->joinerTable
00625             WHERE tag_id = '$tagId'
00626                 AND object_id = '$this->objectId'
00627         ");
00628     }
00629 
00638     public function getRelatedTags($tag)
00639     {
00640         //get our tag and object.
00641         $tagId = $this->findTag($tag);
00642 
00643         $sql = "
00644             SELECT t.tag, count(t.tag) AS popularity
00645             FROM $this->tagTable t
00646             INNER JOIN $this->joinerTable j
00647                 ON t.id = j.tag_id
00648             WHERE j.object_id IN (" . $this->getObjectsSql($tagId) . ")
00649                 AND j.tag_id != '$tagId'
00650             GROUP BY t.tag
00651             ORDER BY popularity DESC, t.tag
00652             LIMIT 30
00653         ";
00654         $key = "BaseJumper:tags:popular:" . sha1($sql);
00655 
00656         //try the cache.
00657         if (self::$cacheRelatedTags)
00658             $tags = CacheBot::get($key, self::$relatedTagsCacheLife);
00659     
00660         //did we get them?
00661         if (!$tags)
00662         {
00663             //init.
00664             $tags = array();
00665         
00666             //did we get it?
00667             if ($tagId)
00668             {
00669                 //do our query to find what tags the other objects that use our tag
00670                 $tagRs = dbQuery($sql);
00671 
00672                 //get the tags.
00673                 while ($tagAr = dbFetchAssoc($tagRs))
00674                     $tags[] = $tagAr['tag'];
00675                 
00676                 //save it!
00677                 if (self::$cacheRelatedTags)
00678                     CacheBot::set($key, $tags, self::$relatedTagsCacheLife);
00679             }
00680         }
00681 
00682         return $tags;
00683     }
00684 
00692     public function getLinkedTags($tags)
00693     {
00694         $links = array();
00695 
00696         if (count($tags))
00697         {
00698             //create links.
00699             foreach ($tags AS $tag)
00700                 $links[] = $this->getLink(".view?tag=$tag", self::prettyTag($tag));
00701         }
00702 
00703         return $links;
00704     }
00705 
00712     public function getTagList($tags = null)
00713     {
00714         //inital stuff.
00715         if ($tags === null)
00716             $tags = $this->getTags();
00717 
00718         //link up!
00719         $links = $this->getLinkedTags($tags);
00720 
00721         //get 'er done.
00722         return implode(", ", $links);
00723     }
00724     
00732     public function getRelatedTagsList($tag)
00733     {
00734         $tags = $this->getRelatedTags($tag);
00735 
00736         //link up!
00737         $links = $this->getLinkedTags($tags);
00738 
00739         //get 'er done.
00740         return implode(", ", $links);
00741     }
00742 
00748     protected function getFormPopularCloud()
00749     {
00750         //get our tags.
00751         $tags = $this->getTags();
00752         $popular = $this->getPopularTags();
00753 
00754         //get the ones that we arent using already.
00755         $usable = array_diff($popular, $tags);
00756 
00757         //create our links..
00758         if (count($usable))
00759         {
00760             foreach ($usable AS $tag)
00761                 $links[] = "<a href=\"#\" onClick=\"return addTagToForm('" . strtolower(get_class($this)) . "', '" .
00762                     self::prettyTag($tag) . "');\">" . self::prettyTag($tag) . "</a>";
00763         
00764             return implode(", ", $links);
00765         }
00766 
00767         return "No popular $this->plural found.";
00768     }
00769     
00775     public function addTagField($form)
00776     {
00777         $form->add('TextAreaField', strtolower(get_class($this)), $this->getTagFieldParams()); 
00778     }
00779 
00785     public function addPopularTagField($form)
00786     {
00787         $this->needsJs("lib/js/tags.js");
00788         $form->add('LabelField', 'popular_' . strtolower(get_class($this)), $this->getPopularFieldParams());
00789     }
00790 
00797     public function addTagFields($form)
00798     {
00799         $this->addTagField($form);
00800         $this->addPopularTagField($form);
00801     }
00802     
00808     public function getCreateTableSql()
00809     {
00810         $tagFields = implode(",\n", $this->getTagFieldsArray());
00811         $tagIndexes = implode(",\n", $this->getTagIndexesArray());
00812         $sql = "CREATE TABLE IF NOT EXISTS $this->tagTable\n(\n$tagFields,\n$tagIndexes\n);\n";
00813         
00814         $joinerFields = implode(",\n", $this->getJoinerFieldsArray());
00815         $joinerIndexes = implode(",\n", $this->getJoinerIndexesArray());
00816         $sql .= "CREATE TABLE IF NOT EXISTS $this->joinerTable\n(\n$joinerFields,\n$joinerIndexes\n);\n";
00817 
00818         return $sql;
00819     }
00820 
00826     public function getTagFieldsArray()
00827     {
00828         $fields = array(
00829             "id" => "id INT(11) not null auto_increment",
00830             "tag" => "tag varchar(64) default '' not null"
00831         );
00832 
00833         return $fields;
00834     }
00835 
00841     public function getTagIndexesArray()
00842     {
00843         $fields = array(
00844             "id" => "PRIMARY KEY(id)",
00845             "tag" => "KEY (tag)"
00846         );
00847 
00848         return $fields;
00849     }
00850     
00856     public function getJoinerFieldsArray()
00857     {
00858         $fields = array(
00859             "tag_id" => "tag_id INT(11) not null default 0",
00860             "object_id" => "object_id INT(11) not null default 0",
00861         );
00862 
00863         return $fields;
00864     }
00865 
00871     public function getJoinerIndexesArray()
00872     {
00873         $fields = array(
00874             "tag_id" => "KEY(tag_id)",
00875             "object_id" => "KEY(object_id)",
00876         );
00877 
00878         return $fields;
00879     }
00880 }
00881 ?>

Generated on Fri Oct 27 12:26:40 2006 for BaseJumper by doxygen 1.3.9.1