Vanilla 1 is no longer supported or maintained. If you need a copy, you can get it here.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.
Options

Tutorials

edited February 2007 in Vanilla 1.0 Help
Hoping I don't get chastised too much for this but I'm trying to write an Add-On and my OOP skills are limited. This means I'm really struggling to make sense of the documentation provided. Anyone out there got a simple tutorial that would help me get my head around making an Add-On with basic CRUD operations with both a tabbed page and a settings page for some extra admin controls?

I've only got so far by picking apart other Add-Ons, but it'd be lovely to actually understand whats going on rather than manically copy pasting functions and hoping for the best... Any help greatly appreciated!

Comments

  • Options
    not to be harsh, but I think that learning by dissecting others work is a really good way to learn. well, it got me a job, so I guess it does.
  • Options
    There's a fair bit of documentation on the site, a lot more you get than with most free software.

    Although I understand where you're coming from and making certain add-ons is not easy, but OOP programming is a skill and the documentation can only go so far, the rest is down to experience and seeing how the code works. Usually there's an extension that does something similar and you can adapt it.
  • Options
    OK, ok. I'll get back to it. Dissecting others work is the way I've learnt nearly everything I know, I'm just hitting a brick wall a bit here. It's a shame cos I've got a great little add-in on the way and if I had the ground knowledge it'd be up and shared by end of the day probably. But you're right - no pain, no gain.
  • Options
    Well i'm sure if there's a particular part of the addon you're struggling with if you chucked us the relevant bits of code someone would be willing to suggest a way forward...
  • Options
    edited February 2007
    Well, I have a question with an extension I'm working on. It's actually a mod to the CategoryPanel extension. I've added some mysql queries to it to get certain pieces of information (date last visited) so I can add it to the Category name. It works fine on my local computer. But when I upload it, the queries come back empty. I've added the dbconnection to the extension, but still nothing. I then change the mysql to one that was used in another extension and that errored out. Can you help with this?

    I didn't want to start my own discussion, but maybe I should. Sorry.
  • Options
    First question would have to be whether you're using the same version of mysql on both boxes. Second would be (partly out of curiosity but also for clarity) whether your databases are mirrors of each other (i.e. same data). Third - lets see the code..?
  • Options
    Here it is. Thank you for looking at it. Neither mysql works on my live site, but both work locally.
    The databases are separate.
    <?php /* Extension Name: Weighted Panel Categories Extension Url: http://www.jwurster.us/gfe Description: Displays weighted categories in a list of categories with descriptions in the side panel with each Category sized according to the number of discussions and comments. This is a modified version of the PanelCategories extension by ithcy (http://htmlephant.com). Version: 0.3.1j Author: Jim Wurster Author Url: http://www.jwurster.us/ */ if (!defined('IN_VANILLA')) exit(); include($Configuration['APPLICATION_PATH'].'conf/settings.php'); //mysql_connect($Configuration['DATABASE_HOST'],$Configuration['DATABASE_USER'],$Configuration['DATABASE_PASSWORD']); //mysql_select_db($Configuration['DATABASE_NAME']); mysql_connect($Context->Configuration['DATABASE_HOST'],$Context->Configuration['DATABASE_USER'],$Context->Configuration['DATABASE_PASSWORD']); mysql_select_db($Context->Configuration['DATABASE_NAME']); $Configuration["CLOUD_PATH"] = '/extensions/CategoryCloud/'; $Context->Dictionary['WCategoryList'] = "Category Cloud"; function GetWPanelCategoryList(&$Context) { // change the following two font size variables to adjust the look on your forum $minfont = 9; $maxfont = 48; // get data for font sizing $data = mysql_fetch_assoc(mysql_query("SELECT count(*) as Number FROM ".$Context->Configuration['DATABASE_TABLE_PREFIX']."discussion WHERE DiscussionID > 0;")); $num_discussions = $data['Number']; // $query = "SELECT count(*) FROM ".$Context->Configuration['DATABASE_TABLE_PREFIX']."discussion"; // $result = mysql_query($query); // if ($result) // { // $row = @mysql_fetch_array($result); // $num_discussions = strip_tags($row[0]); // } else { // $num_discussions = 0; // } // $query = "SELECT max(CountComments) FROM ".$Context->Configuration['DATABASE_TABLE_PREFIX']."discussion"; $result = mysql_query($query); if ($result) { $row = @mysql_fetch_array($result); $maxcount = strip_tags($row[0]); } else { $maxcount = 0; } // $query = "SELECT min(CountComments) FROM ".$Context->Configuration['DATABASE_TABLE_PREFIX']."discussion"; $result = mysql_query($query); if ($result) { $row = @mysql_fetch_array($result); $mincount = strip_tags($row[0]); } else { $mincount = 0; } // $query = "SELECT count(*) FROM ".$Context->Configuration['DATABASE_TABLE_PREFIX']."comment WHERE deleted = '0'"; $result = mysql_query($query); if ($result) { $row = @mysql_fetch_array($result); $num_comments = strip_tags($row[0]); } else { $num_comments = 0; } // $total = $num_discussions + $num_comments; $spread = $maxcount - $mincount; if ($spread <= 0) { $spread = 1; }; $fontspread = $maxfont - $minfont; $fontstep = $spread / $fontspread; if ($fontspread <= 0) { $fontspread = 1; } // $MaxDescriptionLength = 70; // descriptions longer than this many characters will be trimmed and "..." added at the end $ShowWCatDescriptions = false; // set to false if you just want the list of category names $WPanelCategoryList = "\n\t<h2>" . $Context->GetDefinition('WCategoryList') ."</h2>\n\t\t<ul id=\"WPanelCategories\">\n"; $WCategoryManager = $Context->ObjectFactory->NewContextObject($Context, 'CategoryManager'); $WCategoryData = $WCategoryManager->GetCategories(0, 1); while ($Row = $Context->Database->GetRow($WCategoryData)) { $thisURL = ""; if (!isset($Row['Blocked']) || $Row['Blocked'] == 0) { $thisURL = $Context->Configuration['WEB_ROOT']; if ($Context->Configuration['URL_BUILDING_METHOD'] == 'mod_rewrite') { if ($Row['CategoryID'] > 0) { $thisURL .= $Row['CategoryID'] . '/'; } else { $thisURL .= 'discussions/'; } } else { if ($Row['CategoryID'] > 0) $thisURL .= '?CategoryID=' . $Row['CategoryID']; } // count the discussions and comments $query = "SELECT * FROM ".$Context->Configuration['DATABASE_TABLE_PREFIX']."discussion WHERE CategoryID = ".$Row['CategoryID']; $result = mysql_query($query); if ($result) { $num_results = mysql_num_rows($result); $catcount = 0; while ($row = mysql_fetch_array($result)) { $catcount = $catcount + strip_tags($row[12]); } } else { $catcount = 0; } // to get time since last post in category 2/3/7 $diff = 0; $query = "SELECT max(DateLastActive) FROM ".$Context->Configuration['DATABASE_TABLE_PREFIX']."discussion WHERE CategoryID = ".$Row['CategoryID']; $result = mysql_query($query); if ($result) { $row = mysql_fetch_array($result); $DateLastActive = strip_tags($row[0]); list($year, $month, $day, $hour, $minute, $second ) = sscanf($DateLastActive, "%d-%d-%d %d:%d:%d"); $thatdate = mktime( $hour, $minute, $second, $month, $day, $year ); $diff = time() - $thatdate; if ($diff >= 86400) // more than 1 day { $diff = $diff / 86400; $diff = round($diff); if ($diff < 2) $timesince = "(".$diff." day since last comment)"; else $timesince = "(".$diff." days since last comment)"; } else if ($diff >= 3600 and $diff < 86400) // more than 1 hour { $diff = $diff / 3600; $diff = round($diff); if ($diff < 2) $timesince = "(".$diff." hour since last comment)"; else $timesince = "(".$diff." hours since last comment)"; } else if ($diff >= 60 and $diff < 3600) // more than 1 minute { $diff = $diff / 60; $diff = round($diff); if ($diff < 2) $timesince = "(".$diff." minute since last comment)"; else $timesince = "(".$diff." minutes since last comment)"; } else { // seconds $diff = round($diff); if ($diff < 2) $timesince = "(".$diff." second since last comment)"; else $timesince = "(".$diff." seconds since last comment)"; } } else { $DateLastActive = "none"; $diff = 0; $timesince = " "; } // Assign a font-size to the word based on frequency of use. $step = catcloud_mk_step($minfont, $maxfont, $maxcount, $mincount); $size = $minfont + $catcount/$fontstep; $WPanelCategoryList .= "\t\t\t<li class=\"WPanelCatName\"><span style='font-size: " . catcloud_mk_stepped_base($minfont, $step, $catcount) . "px;'><a href=\"$thisURL\" title=\"Count: $catcount\">{$Row['Name']}</a></span> ".$timesince."</li>\n"; // if ($ShowWCatDescriptions) { $WPanelCategoryList .= "\t\t\t<li class=\"WPanelCatList\">" . nicetrim($Row['Description'], $MaxDescriptionLength) . " " . $timesince . "</li>\n"; } } } $WPanelCategoryList .= "\t\t</ul>\n"; return $WPanelCategoryList; } function nicetrim ($s, $MaxDescriptionLength) { // borrowed from someone in the php.net comments $str_to_count = html_entity_decode($s); if (strlen($str_to_count) <= $MaxDescriptionLength) { return $s; } $s2 = substr($str_to_count, 0, $MaxDescriptionLength - 3); $s2 .= "..."; return htmlentities($s2); } // Tag Cloud generation code functions function catcloud_mk_stepped_base($base, $step, $count){ return $base + $step * $count; } function catcloud_mk_step($min, $max, $maxcnt, $mincnt){ return ($max - $min) / ($maxcnt - $mincnt + 1); } // if (in_array($Context->SelfUrl, array('index.php','comments.php'))) { $Head->AddStyleSheet($Configuration["CLOUD_PATH"]."style.css"); $Panel->AddString(GetWPanelCategoryList($Context),13); } ?>
This discussion has been closed.